ValueError: setting an array element with a sequence symbolic - python

I am beginner with python. I have the following code:
import Deformation
import Qtheta
import numpy as np
import sympy as sp
def champs_de_contraintes(epaisseurs,angles,El,Et,Glt,Nult):
E0=np.mat('[0;0;0]') #inizialising E0
K=np.mat('[0;0;0]') #inizialising K
E0K=np.mat('[0;0;0;0;0;0]') #inizialising K
E0K = Deformation.defos(epaisseurs,angles,El,Et,Glt,Nult) #function that return a 6x1 matrix type <class 'numpy.matrixlib.defmatrix.matrix'>
E0=E0K[:3] #Slicing E0K into 2 vectors E0 and K
K=E0K[3:]
nb_composantes = 3 #sigma x, sigma y, taux xy
Sigmaxy=np.zeros((nb_composantes,len(epaisseurs))) #sigma x, sigma y, taux xy, Array
#===============This bloc calculate the altitude of a ply =================
z=[]
e=[]
z.append(-(np.sum(epaisseurs))/2)
for k in (range(len(epaisseurs))): #initialising e[k]
e[len(e):] = [0] #Values to add to get the altitude
for i in (range(len(epaisseurs))):
e[i]= e[i-1] + epaisseurs[i] #sum e
z[len(z):] = [z[0] + e[i]] #Altitude
#===========================This bloc calculate a vector===================
for i in (range(len(epaisseurs))):
newcolumn= Qtheta.Qtheta(angles[i],El,Et,Glt,Nult)*E0+z[i]*Qtheta.Qtheta(angles[i],El,Et,Glt,Nult)*K #z is the altitude
#3x1 = 3x3*3x1 + 1x1*3x3*3x1
for m in (range(len(newcolumn))):
Sigmaxy[i,m]=newcolumn[m]
return Sigmaxy
This returns me the error
Sigmaxy[i,m]=newcolumn[m]
ValueError: setting an array element with a sequence
Basically, what i want to do is to save the vector "newcolumn" in a newcolumn in the Sigmaxy matrix.
I think that I get this error because "newcolumn" is symbolic. Actually, E0 and K depend on 2 variables.
Could anybody help me with this one ?
Thanks in advance !

If you want to set elements of your array in this way, you need to make sure that the shapes are matching.
The error you get is thrown if you try something like this:
my_1d_array = np.array([1,2,3])
my_1d_array[0] = [4, 5, 6]
As the error explains, you are trying to set a single element to a sequence of elements, which is not possible. Debug your code, and make sure that the shapes (.shape) of Sigmaxy[i,m] and newcolumn[m] are matching.
Initialize your array with the correct size with space for all the elements in the beginning. If you don't know the exact size, you can create bigger arrays by adding columns, see other questions for this.

Related

Obtaining the value of a 'GK_Operators' class

The main purpose of this question is to figure out how to obtain the value of what seems to be a 'GK.Operator'. I am new in the gekko environment and I may be not specific enough but I will try my best.
Here it is an example code
from gekko import GEKKO
from numpy import triu_indices, diag_indices, full
#Create a gekko model
model=GEKKO()
n=2
idx=triu_indices(n,1)
#Create a 1xn array
T=model.Array(model.CV, n)
#Create a nxn array
R = full((n, n), 0, dtype=object)
#Fill only the upper and lower triangle of the R matrix
if n>1:
R[idx] = model.FV(name='R')
R[idx[::-1]] = R[idx]
#Same as R array
Q = full((n, n), 0, dtype=object)
Q[diag_indices(n)] = model.Const(0)
if n>1:
Q[idx] = (T[idx[1]] - T[idx[0]]) / R[idx]
Q[idx[::-1]] = -Q[idx]
#Assign values to T and R
T[1].VALUE,T[0].VALUE=25,12
R[0,1].VALUE=4
print(R)
model.solve(disp=False)
print(R)
print(Q[0,1].VALUE)
print(T[1].MODEL,T[0].MODEL,R[0,1].VALUE)
print(type(R[0,1]),
type(Q[0,1]))
First of all, I think that it would be useful to say that this code comes from a bigger one that simulates a dynamic system, there is not an objective function and therefore is not an optimization problem.
The problem here, is that I can not obtain the value of any of the items of the Q array. As long as I am concerned, the attribute .VALUE or .MODEL will return the value of a gekko variable. However, it seems like it is not working with the variable Q[0,1] which is supposed to be equal to the result of the operation (T[1]-T[0])/R[0,1] or (25-12)/4. When asking for that value with Q[0,1].VALUE a 0 is returned, but that is clearly not the result of that operation. I thought that the class of that variable could have something to do with this, and when checking with type(Q[0,1]), it returns a GK.Operator. I am not sure about what really a GK.Operator is, but I guess that using the attributes .VALUE or .MODEL will not work. It is quite important for me to be able to obtain the values of Q.
In addition, there is another problem with the array R. Before solving the model, that array is what it is supposed to be. However, after solving the model some items of that array become themselves arrays.
I hope that you can help me understanding these doubts. Thanks for reading.
The Q value needs to be a Gekko Var, Param, or Intermediate to use .value. Here is a simplified version of the code that works:
from gekko import GEKKO
from numpy import triu_indices, diag_indices, full
#Create a gekko model
model=GEKKO()
#Create a 1xn array
T=model.Array(model.Var,2)
#Create a nxn array
R = full((2,2), 0, dtype=object)
#Fill only the upper and lower triangle of the R matrix
R[0,1] = model.FV(name='R')
R[1,0] = R[0,1]
#Same as R array
Q = full((2,2), 0, dtype=object)
Q[0,0] = 0
Q[1,1] = 0
Q[0,1] = model.Intermediate((T[1] - T[0]) / R[0,1])
Q[1,0] = model.Intermediate(-Q[0,1])
#Assign values to T and R
T[1].VALUE,T[0].VALUE=25,12
R[0,1].VALUE=4
print('R before solve: ',R)
model.solve(disp=False)
print('R after solve: ',R)
print('Q[0,1]:',Q[0,1].value)
print('Q[1,0]:',Q[1,0].value)
print('T[1],T[0]:',T[1].value,T[0].value)
print('R[0,1] type:',type(R[0,1]))
print('Q[0,1] type:',type(Q[0,1]))
Results:
R before solve: [[0 4]
[4 0]]
R after solve: [[0 [4.0]]
[[4.0] 0]]
Q[0,1]: [3.25]
Q[1,0]: [-3.25]
T[1],T[0]: [25.0] [12.0]
R[0,1] type: <class 'gekko.gk_parameter.GK_FV'>
Q[0,1] type: <class 'gekko.gk_operators.GK_Intermediate'>

ValueError: x and y must have same first dimension, but have shapes (101,) and (1,) [duplicate]

This question already has answers here:
Plotting: ValueError: x and y must have same first dimension
(2 answers)
Closed 1 year ago.
enter image description hereI am new in coding and in using JupyterNotebook and I wanted to ask how will I graph x(as any time t)=(0,10,101) and y(as acceleration)=-2.2 . those are the values given to us by our professor but when I try to plot, it gives me an error and it says that ValueError: x and y must have same first dimension, but have shapes (101,) and (1,). thank you.
Your description wasn't clear, I highly suggest next time you post to provide an example of the code that you are facing a problem. Have a look at how others frame their questions. Anyways I will try my best to help you.
We know that:
x = 0.5at^2 +V0t
Where:
x: position
a: acceleration
V0: initial velocity
t: time
In real life time is continous, however having an absolutley continous variable in programming is impossible, therefore the next best thing to do is use a range with a very small step size.
Let's start with assuming that the initial velocity is zero --> x = 0.5at*t
Now that we have simplified the equation let's tackle the problem of time.
import numpy as np
import matplotlib.pyplot as plt
# acceleration is a constant variable
a = -2.2
# get array for the time
t = np.arange(0,10,0.1)
# calculate position at each time and store in array
x = 0.5*a*t*t
plt.plot(t,x)
plt.show()
out:
[]
Above we calculated each value of x for the list of values in time, as you can see, in order to plot the values of position vs time, their the lengths of the arrays need to be the same. we can check the lengths of the arrays using the len function:
print(f"length of time: {len(t)} ")
print(f"length of position: {len(x)}" )
out:
length of time: 100
length of position: 100
Here are some sources to help you get started with learning python:
Great free Course covering all the basics by Microsoft
List Comprehension
Functions in python
Some channels on Youtube that I recommend:
Real Python
Corey Schafer
DataCamp
When you want to plot x versus y data you need to have matching shapes for x and y data.
So in order to plot horziontal line at y = -2.2 for x from 0 to 10 with 101 points instead of
y = (-2.2)
You need to use
y = np.full(101, -2.2)
Or better
y = np.full(x.shape, -2.2)
So that y would be of shape 101 matching x shape
Use this:
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0,10,101)
y = np.repeat(-2.2,101) # map y constant value
plt.plot(x,y)
plt.show()

Matrix left division of stacked arrays using numpy

I'm working on a program to solve the Bloch (or more precise the Bloch McConnell) equations in python. So the equation to solve is:
where A is a NxN matrix, A+ its pseudoinverse and M0 and B are vectors of size N.
The special thing is that I wanna solve the equation for several offsets (and thus several matrices A) at the same time. The new dimensions are:
A: MxNxN
b: Nx1
M0: MxNx1
The conventional version of the program (using a loop over the 1st dimension of size M) works fine, but I'm stuck at one point in the 'parallel version'.
At the moment my code looks like this:
def bmcsim(A, b, M0, timestep):
ex = myexpm(A*timestep) # returns stacked array of size MxNxN
M = np.zeros_like(M0)
for n in range(ex.shape[0]):
A_tmp = A[n,:,:]
A_b = np.linalg.lstsq(A_tmp ,b, rcond=None)[0]
M[n,:,:] = np.abs(np.real(np.dot(ex[n,:,:], M0[n,:,:] + A_b) - A_b))
return M
and I would like to get rid of that for n in range(ex.shape[0]) loop. Unfortunately, np.linalg.lstsq doesn't work for stacked arrays, does it? In myexpm is used np.apply_along_axis for a another problem:
def myexpm(A):
vals,vects = np.linalg.eig(A)
tmp = np.einsum('ijk,ikl->ijl', vects, np.apply_along_axis(np.diag, -1, np.exp(vals)))
return np.einsum('ijk,ikl->ijl', tmp, np.linalg.inv(vects))
However, that just works for 1D input data. Is there something similar that I can use with np.linalg.lstsq? The np.dot in bmcsim will be replaced with np.einsum like in myexpm I guess, or are there better ways?
Thanks for your help!
Update:
I just realized that I can replace np.linalg.lstsq(A,b) with np.linalg.solve(A.T.dot(A), A.T.dot(b)) and managed to get rid of the loop this way:
def bmcsim2(A, b, M0, timestep):
ex = myexpm(A*timestep)
b_stack = np.repeat(b[np.newaxis, :, :], offsets.size, axis=0)
tmp_left = np.einsum('kji,ikl->ijl', np.transpose(A), A)
tmp_right = np.einsum('kji,ikl->ijl', np.transpose(A), b_stack)
A_b_stack = np.linalg.solve(tmp_left , tmp_right )
return np.abs(np.real(np.einsum('ijk,ikl->ijl',ex, M0+A_b_stack ) - A_b_stack ))
This is about 3 times faster, but still a bit complicated. I hope there is a better (shorter/easier) way, that's maybe even faster?!

combining/merging multiple 2d arrays into single array by using python

I have four 2 dimensional np arrays. Shape of each array is (203 , 135). Now I want join all these arrays into one single array with respect to latitude and longitude.
I have used code below to read data
import pandas as pd
import numpy as np
import os
import glob
from pyhdf import SD
import datetime
import mpl_toolkits.basemap.pyproj as pyproj
DATA = ({})
files = glob.glob('MOD04*')
files.sort()
for n, f in enumerate(files):
SDS_NAME='Deep_Blue_Aerosol_Optical_Depth_550_Land'
hdf=SD.SD(f)
lat = hdf.select('Latitude')
latitude = lat[:]
min_lat=latitude.min()
max_lat=latitude.max()
lon = hdf.select('Longitude')
longitude = lon[:]
min_lon=longitude.min()
max_lon=longitude.max()
sds=hdf.select(SDS_NAME)
data=sds.get()
p = pyproj.Proj(proj='utm', zone=45, ellps='WGS84')
x,y = p(longitude, latitude)
def set_element(elements, x, y, data):
# Set element with two coordinates.
elements[x + (y * 10)] = data
elements = []
set_element(elements,x,y,data)
But I got error: only integer arrays with one element can be converted to an index
you can find the data: https://drive.google.com/open?id=0B2rkXkOkG7ExMElPRDd5YkNEeDQ
I have created toy datasets for this problem as per requested.
what I want is to get one single array from four (a,b,c,d) arrays. whose dimension should be something like (406, 270)
a = (np.random.rand(27405)).reshape(203,135)
b = (np.random.rand(27405)).reshape(203,135)
c = (np.random.rand(27405)).reshape(203,135)
d = (np.random.rand(27405)).reshape(203,135)
a_x = (np.random.uniform(10,145,27405)).reshape(203,135)
a_y = (np.random.uniform(204,407,27405)).reshape(203,135)
d_x = (np.random.uniform(150,280,27405)).reshape(203,135)
d_y = (np.random.uniform(204,407,27405)).reshape(203,135)
b_x = (np.random.uniform(150,280,27405)).reshape(203,135)
b_y = (np.random.uniform(0,202,27405)).reshape(203,135)
c_x = (np.random.uniform(10,145,27405)).reshape(203,135)
c_y = (np.random.uniform(0,202,27405)).reshape(203,135)
any help?
This should be a comment, yet the comment space is not enough for these questions. Therefore I am posting here:
You say that you have 4 input arrays (a,b,c,d) which are somehow to be intergrated into an output array. As far as is understood, two of these arrays contain positional information (x,y) such as longitude and latitude. The only line in your code, where you combine several input arrays is here:
def set_element(elements, x, y, data):
# Set element with two coordinates.
elements[x + (y * 10)] = data
Here you have four input variables (elements, x, y, data) which I assume to be your input arrays (a,b,c,d). In this operation yet you do not combine them, but you overwrite an element of elements (index: x + 10y) with a new value (data).
Therefore, I do not understand your target output.
When I was asking for toy data, I had something like this in mind:
a = [[1,2]]
b = [[3,4]]
c = [[5,6]]
d = [[7,8]]
This would be such an easy example that you could easily say:
What I want is this:
res = [[[1,2],[3,4]],[[5,6],[7,8]]]
Then we could help you to find an answer.
Please, thus, provide more information about the operation that you want to conduct either mathematically notated ( such as x = a +b*c +d) or with toy data so that we can deduce the function you ask for.

Integrated for loop to calculate values over a grid/mesh

I am fairly new to python, and I am trying to plot a contour plot of water surface over a 2d mesh.
At the moment the code is running but I am not getting the right solution. I have checked the formula carefully and I am fairly confident that the issue is with my loops.
I want the code to run for each point on my mesh based on their x and y coordinates.
The mesh is 100 x 100 resulting in 10000 nodes. I have posted my code below, I believe the problem is with the integrated for loops. Any advice on what I might be able to try would be great.
Apologies for the length of code...
import numpy as np
import matplotlib.pyplot as plt
import math
import sys
from math import sqrt
import decimal
t=0
n=5
l=100000
d=100
g=9.81
nx, ny = (100,100)
x5 = np.linspace(-100000,100000,nx)
y5 = np.linspace(-100000,100000,ny)
xv,yv = np.meshgrid(x5,y5)
x = np.arange(-100000,100000,2000)
y = np.arange(-100000,100000,2000)
c=np.arange(len(x))
x2=np.arange(len(x))
y2=np.arange(len(x))
t59=np.arange (1,10001,1)
h=np.arange(len(t59))
om2=1.458*(10**-4.0)
phi=52
phirad=phi*(math.pi/180)
f=om2*math.sin(phirad)
A=(((d+n)**2.0)-(d**2.0))/(((d+n)**2.0)+(d**2.0))
w=(((8*g*d)/(l**2))+(f**2))**0.5
a=((1-(A**2.0))**0.5)/(1-(A*math.cos(w*t)))
b=(((1-(A**2.0))/(1-(A*math.cos(w*t)))**2.0)-1)
l2=l**2.0
for i in range (len(x)):
for j in range (len(y)):
h[i]=d*(a-1-((((x[i]**2.0)+(y[j]**2.0))/l2)*b))
h5=np.reshape(h,(100,100))
plt.figure(1)
plt.contourf(x5,y5,h5)
plt.colorbar()
plt.show()
Ok apologies I didn't make myself very clear. So I'm hoping to achieve a parabolic basin output with h values varying between roughly -10 and 10. Instead I am getting enormous values and the completely wrong shape. I thought the for loop needed to be more like:
for i in range (len(x)):
for j in range (len(y)):
h[i][j]=d*(a-1-((((x[i][j]**2.0)+(y[i][j]**2.0))/l2)*b))
Is that clearer? Let me know if not.
The first thing is that the complete loop is not necessary.
h = d * (a - 1 - (x[None,:]**2 + y[:,None]**2) / 12 * b)
Here the magic comes with the None in indexing. x[None, :] means "x as a row vector copied to as many rows as needed and y[:, None] means "y as a column vector copied to as many columns as needed`.
This might be easiest to understand with an example:
import numpy as np
x = np.arange(5)
y = np.arange(0,50,10)
print x, y, x[None,:] + y[:, None]
The one-liner above gives:
Some manual calculations show this should be rather ok.
d = 100
a = 1.05
b = 0.1025
For a corner point at (1e5, 1e5), we have 2e10 in the addition, so the values do not look badly off.

Categories