Invalid Syntax error on addition when running FEniCS in Windows subsystem - python

I am currently working on a project where we are solving a system of PDE's in FEniCs. I have created the following code in order to solve the system but I get an invalid syntax error on
a = a0 + a1
I am not that good in Python and I have never used FEniCS before. I am also using a windows subsystem in order to run it which makes it extra complicated for me to understand any error that I might have made. I appreciate any suggestions you may have and I apologize in advance if I ask obvious questions!
from fenics import *
# Create mesh and define function space
mesh = Mesh (" circle.xml ")
# Construct the finite element space
V = VectorFunctionSpace (mesh , 'P', 1)
# Define parameters :
T = 150
dt = 0.5
alpha = 0.4
beta = 2
gamma = 0.8
delta = 1
# Class representing the intial conditions
class InitialConditions ( UserExpression ):
def eval (self , values , x):
values [0] = Expression(("(4/25)-2*pow(10,-7)*(x[0]-0.1*x[1]-225)*(x[0]-0.1*x[1]-675)"),degree=2)
values [1] = Expression(("(22/45)-3*pow(10,-5)*(x[0]-450)-1.2*pow(10,-4)*(x[1]-150)"),degree=2)
def value_shape ( self ):
return (2 ,)
# Define initial condition
indata = InitialConditions(degree =2)
u0 = Function (V)
u0 = interpolate (indata,V)
# Test and trial functions
u,v = TrialFunction(V), TestFunction(V)
# Create bilinear and linear forms
a0 = (u[0]*v[0]*dx) + (0.5*delta*dt*inner(grad(u[0]),grad(v[0]))*dx)
a1 = (u[1]*v[1]*dx) + (0.5*delta*dt*inner(grad(u[1]),grad(v[1]))*dx)
L0 = (u0[0]*v[0]*dx) - (0.5*delta*dt*inner(grad(u0[0]),grad(v[0]))*dx) - (dt*u0[0]*v[0]*dx*(((u0[0]*u0[1])/(u0[0]+alpha))-u0[0]*(1-u0[0]))*dx)
L1 = (u0[1]*v[1]*dx) - (0.5*delta*dt*inner(grad(u0[1]),grad(v[1]))*dx) - (dt*u0[1]*v[1]*dx*(-beta*((u0[0]*u0[1])/(u0[0]+alpha))-gamma*u0[1]*dx)
a = a0 + a1
L = L0 + L1
#Set up boundary condition
g = Constant([0.0,0.0])
bc = DirichletBC(V,u_initial,DirichletBoundary())
bc = [] #NEUMANN
#Assemble matrix
A = assemble(a)
# Set an output file
out_file = File("Results.pvd","compressed")
# Set initial condition
u = Function(V)
u.assign(u0)
t = 0.0
out_file << (u,t)
u_initial = Function(V)
u_initial.assign(u0)
t_save = 0
num_samples = 20
# Time - stepping
while t < T:
# assign u0
u0.assign(u)
#Assemble vector and apply boundary conditions
A = assemble(a)
b = asseble(L)
t_save += dt
if t_save > T/ num_samples or t >= T-dt:
print("Saving!")
#Save the solution to file
out_file << (uv,t)
t_save = 0
#Move to next interval and adjust boundary condition
t += dt

There's a typo in your line b = asseble(L) --> b=assemble(L)
Perhaps this tiny error is giving you the issue? Although I'd imagine the error message would be more descriptive.

Related

Turning points in a squared first order ODE using Scipy.integrate

I am trying to code a radius function based on the Schwarzchild solution to a black hole given the expression:
(dr/dtau)^2= Emu^2- Veff^2
As it is a square the sign in front of the root will depend on the turning points that I have manually found and labeled tp1 and tp2. However, even though I am changing the functions sign depending on its position it behaves relatively well until it hits these turning points.
Here is the code I have so far:
(P.S: I hope this is the correct formatting and way to present a question although i have been a reader for a few years this is actually my first post).
import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import ode
tp1 = 1.08329*10**11
tp2 = 4.13115*10**11
#arbitrary initial radius
r_start = 3e11
#constants:
M = 4*10**6*(1.9891*10**30) # SMBH mass in kg
G = 6.67408*10**(-11) # Gravitational constant in N kg^-2 m^2
c = 299792458
Emu2 = 0.88*10**17
Lmu = 10**19
def odes(tau,rs):
Vef = (1-(((2*G*M)/c**2)/rs))*((c**2)+(Lmu/rs)**2)
sign = (Emu2)-Vef
signcount = 1
if sign <= 0:
if rs <= tp1:
rs = tp1+5
Vef = (1-(((2*G*M)/c**2)/rs))*((c**2)+(Lmu/rs)**2)
sign = (Emu2)-Vef
drdTau = np.sqrt(Emu2 - Vef)
signcount = 1
if rs >= tp2:
rs = tp2-5
Vef = (1-(((2*G*M)/c**2)/rs))*((c**2)+(Lmu/rs)**2)
sign = (Emu2)-Vef
drdTau = (-1)*np.sqrt((Emu2) - Vef)
signcount = 2
return [drdTau]
if sign > 0 :
if signcount == 1:
Vef = (1-(((2*G*M)/c**2)/rs))*((c**2)+(Lmu/rs)**2)
sign = (Emu2)-Vef
drdTau = np.sqrt(Emu2 - Vef)
if signcount == 2:
Vef = (1-(((2*G*M)/c**2)/rs))*((c**2)+(Lmu/rs)**2)
sign = (Emu2)-Vef
drdTau = (-1)*np.sqrt(Emu2 - Vef)
return [drdTau]
if __name__ == '__main__':
r0 = [r_start]
tspan = 5*3.154e7
# timestep
dtau = 1000
# total number of steps
n_steps = int(np.ceil(tspan/dtau))
#Initialise arrays
t = np.zeros((n_steps,1))
rs = np.zeros((n_steps,1))
ts = np.zeros((n_steps,1))
step = 1
r0 = [r_start]
t0 = [0]
t[0] = np.array(t0)
rs[0] = np.array(r0)
# initiate solver
solver = ode(odes)
solver.set_integrator('DOP83')
solver.set_initial_value(r0,0)
#propagate orbit
while solver.successful() and step<n_steps:
solver.integrate(solver.t+dtau)
ts[step] = solver.t
rs[step] = solver.y
step += 1
plt.plot(ts,rs,'s',color='#0066FF')
# axes labels
plt.xlabel('$x$')
plt.ylabel('$y$')
plt.legend('pos')
# check for and set axes limits
max_yval = np.amax(rs)
max_xval = np.amax(ts)
plt.xlim(0,max_xval)
plt.ylim(tp1 - 300000,max_yval)
plt.show()
print(rs)
I have solved it by changing the function it is integrating once it reaches tp1 and tp2 I am hoping to add a root solver to automate the turning point solving but for now a rough tratment is what I have. I'll put up the code for anyone working on this area that has come across this issue once i have refined it, but essentially instead of modifying the function I added a second one called odes2with a negative sign and solved for that once the turning points were reached.
solver = ode(odes)
solver.set_integrator('lsoda')
solver.set_initial_value(r0,0)
#propagate orbit
while solver.successful() and step<n_steps:
solver.integrate(solver.t+dtau)
ts[step] = solver.t
rs[step] = solver.y
if rs[step]>tp2:
rs[step] = tp2
solver = ode(odes2)
solver.set_initial_value(rs[step],ts[step])
if rs[step]<tp1:
rs[step] = tp1
solver = ode(odes)
solver.set_initial_value(rs[step],ts[step])
step += 1
Not perfect, but using the second order dynamic really avoids a lot of overhead
def Veff(rs): return (1-(((2*G*M)/c**2)/rs))*((c**2)+(Lmu/rs)**2)
def grad_Veff(rs):
rp=rs*(1+1e-5)-1e-5; rm = rs*(1+1e-5)+1e-5
return (Veff(rp)-Veff(rm))/(rp-rm);
def ode(t,y): return [y[1], -grad_Veff(y[0])]
t = np.arange(0, tspan, dtau)
vstart = (Emu2 - Veff(rstart))**0.5
res = solve_ivp(ode, (0,tspan), [rstart, vstart], t_eval=t, atol=1e2, rtol=1e-8)
This should integrate through the turning points, to find the turning points search for sign changes or roots in the second component. One could also define an event for this so that the solver automatically registers the turning points.

How to save value of variable from one function call and use it to the next function call?

I am implementing a cartesian control of a robotic manipulator and below you can see the function which produces the joint velocities in order to perform the control:
def cartesian_control(joint_transforms, b_T_ee_current, b_T_ee_desired,
red_control, q_current, q0_desired):
num_joints = len(joint_transforms)
dq = numpy.zeros(num_joints)
ee_current_T_b = tf.transformations.inverse_matrix(b_T_ee_current)
current_T_desired = numpy.dot(ee_current_T_b, b_T_ee_desired)
current_P_desired = tf.transformations.translation_from_matrix(current_T_desired)
current_R_desired = current_T_desired[:3,:3]
angle, axis = rotation_from_matrix(current_T_desired)
rot_movement = numpy.dot(angle,axis)
desired_R_current = tf.transformations.inverse_matrix(current_R_desired)
delta_X = numpy.append(current_P_desired, rot_movement)
# Proportional - Derivative Controller
Kp = 5 # Proportional Gain
Kd = 1 # Derivative Gain
delta_delta_X = (delta_X - delta_X_prev)/0.01
x_dot = Kp*delta_X + Kd*delta_delta_X
# Scale translational and angular velocities for smoothness
for i in range(3):
if x_dot[i] > 1:
x_dot[i] = 1
for i in range(3,1,5):
if x_dot[i] > 0.1:
x_dot[i] = 0.1
J = numpy.empty((6,0))
V = numpy.zeros((6,6))
for i in range(num_joints):
b_T_joint = joint_transforms[i]
ee_T_joint = numpy.dot(ee_current_T_b, b_T_joint)
joint_T_ee = tf.transformations.inverse_matrix(ee_T_joint)
ee_R_joint = rotation_matrix(ee_T_joint)
joint_P_ee = tf.transformations.translation_from_matrix(joint_T_ee)
joint_skew_matrix = S_matrix(joint_P_ee)
V[:3,:3] = ee_R_joint
V[3:6,3:6] = ee_R_joint
V[:3, 3:6] = numpy.dot(-ee_R_joint, joint_skew_matrix)
J = numpy.column_stack((J, V[:,5]))
J_pseudoinv = numpy.linalg.pinv(J, rcond=0.01)
dq = numpy.dot(J_pseudoinv, x_dot)
# Scale joint velocities
for i in range(len(dq)):
if dq[i] > 0.1:
dq[i] = 0.1
return dq
The above function works perfectly in case I implement just a proportional controller, which means that in case of x_dot = Kp*delta_X + Kd*delta_delta_X1 I have only x_dot = Kp*delta_X. However, I would like also to implement a proportional derivative controller but my problem is how to obtain the delta_X_prev variable. This means that I need to find a way of saving the value of the variable delta_X of one function call and use it at the function call. Did some search and I found that the multiprocessing python module would help but really haven't understood the whole concept of it. Is there any other simpler way it order to do that?

How to create multiple files using a nested loop

I hope everybody is well, safe, and healthy during this time.
I'm currently working on a python assignment. Using the following code, I need to run through each value of beta, and for each value of beta, I need to run through each value of reduction)factor to run through the following steps.
Then for each iteration of reductiom_factor for each value of beta I need to save the data in a file with the titles in listofsolutions. Two things I'm not sure how to do: is how to export data with a file with a name in list of solutions (which are in order for each value of beta and reduction_factor), and how to use np.savez to save the data to the files I have just created.
This is my amended code
b = [1/4, 0]
beta = np.asarray(b)
gamma = 0.5
listofsolutions = ['Q2_AA_0.1','Q2_AA_0.9','Q2_AA_0.99', 'Q2_AA_1', 'Q2_AA_1.1', 'Q2_AA_2','Q2_CD_0.1','Q2_CD_0.9','Q2_CD_0.99', 'Q2_CD_1', 'Q2_CD_1.1', 'Q2_CD_2']
consistent = True # use a consistent mass matrix
for bb in itertools.zip_longest(beta):
c = np.sqrt(E / rho_tilde) # wave speed
T = 0.016 # total time
# compute the critical time-step
# note: uncondionally stable AA scheme will return 1.0
delta_t_crit = fe.get_delta_t_crit(le = le, gamma = gamma, beta = bb, consistent = consistent, c = c)
# actual times-step used is a factor of the critical time-step
reduction_factor = [0.1, 0.9, 0.99, 1, 1.1, 2]
for rf in reduction_factor:
delta_t = rf * delta_t_crit
# selected output data is stored to a file with the name given below
# use this to save the results from the different runs
# change the name to match the data you want to store
for i in b and r in reduction_factor:
outfile[i] = listofsolutions[i]
n_t_steps = int(np.ceil(T / delta_t)); # number of time step
# initialise the time domain, K and M
t = np.linspace(0, T, n_t_steps)
K = np.zeros((n_dof, n_dof))
M = np.zeros((n_dof, n_dof))
# assemble K and M
for ee in range(n_el):
dof_index = fe.get_dof_index(ee)
M[np.ix_(dof_index, dof_index)] += fe.get_Me(le = le, Ae = Ae, rho_tilde_e = rho_tilde, consistent = consistent)
# damping matrix
C = np.zeros((n_dof, n_dof))
# assemble the system matrix A
A_matrix = M + (gamma * delta_t) * C + (beta * delta_t**2)*K
# define the free dofs
free_dof = np.arange(1,n_dof)
# initial conditions
d = np.zeros((n_dof, 1))
v = np.zeros((n_dof, 1))
F = np.zeros((n_dof, 1))
# compute the initial acceleration
a = np.linalg.solve(M, F - C.dot(v) - K.dot(d))
# store the history data
# rows -> each node
# columns -> each time step including initial at 0
d_his = np.zeros((n_dof, n_t_steps))
v_his = np.zeros((n_dof, n_t_steps))
a_his = np.zeros((n_dof, n_t_steps))
d_his[:,0] = d[:,0]
v_his[:,0] = v[:,0]
a_his[:,0] = a[:,0]
# loop over the time domain and solve the problem at each step
for n in range(1,n_t_steps):
# data at beginning of the time-step n
a_n = a
v_n = v
d_n = d
# applied loading
t_current = n * delta_t # current time
if t_current<0.001:
F[-1] = A_bar * Ae * np.sin(1000 * t_current * np.pi)
else:
F[-1]=0.
# define predictors
d_tilde = d_n + delta_t*v_n + ((delta_t**2)/2.) * (1 - 2*beta) * a_n
v_tilde = v_n + (1 - gamma) * delta_t * a_n
# assemble the right-hand side from the known data
R = F - C.dot(v_tilde) - K.dot(d_tilde)
# impose essential boundary condition and solve A a = RHS
A_free = A_matrix[np.ix_(free_dof, free_dof)]
R_free = R[np.ix_(free_dof)]
# solve for the accelerations at the free nodes
a_free = np.linalg.solve(A_free, R_free)
a = np.zeros((n_dof, 1))
a[1:] = a_free
# update displacement and vecloity predictors using the acceleration
d = d_tilde + (beta * delta_t**2) * a
v = v_tilde + (gamma * delta_t) * a
# store solutions
d_his[:,n] = d[:,0]
v_his[:,n] = v[:,0]
a_his[:,n] = a[:,0]
# post-processing
mid_node = int(np.ceil(n_dof / 2)) # mid node
# compute the stress in each element
# assuming constant E
stress = (E / le) * np.diff(d_his, axis=0)
# here we save the stress data for the middle element
np.savez(outfile, t, stress[mid_node,:]
I'm not sure how to specify to the program to save the result for each value of reduction_factor within gamma. In addition, for the last line of the code, I'm not sure how to save each iteration to the list of file names I have created.
I tried to do this using the statement"
for i in b` and r in reduction_factor:
outfile[i] = listofsolutions[i]"`
but I don't think this makes sense.
I am a total newbie at python so I am not familiar how to save files within nested loops.. I apologize if any of my questions are rudimentary.
for i in b and r in reduction_factor:
outfile[i] = listofsolutions[i]
It is not correct. Possible solution:
for i in b: # variable 'i' will take every value of list b
for r in reduction_factor: # 'r' will iterate through reduction_factor
outfile[i] = listofsolutions[i] # outfile must be declared until it
Still, there is no logic. In that way, you can create a dictionary.
If you really want to create the file - read about "with open(filename, 'w'):" construction and nested loops or list comprehension.

Have I implemented Milstein's method/Euler-Maruyama correctly?

I have an stochastic differential equation (SDE) that I am trying to solve using Milsteins method but am getting results that disagree with experiment.
The SDE is
which I have broken up into 2 first order equations:
eq1:
eq2:
Then I have used the Ito form:
So that for eq1:
and for eq2:
My python code used to attempt to solve this is like so:
# set constants from real data
Gamma0 = 4000 # defines enviromental damping
Omega0 = 75e3*2*np.pi # defines the angular frequency of the motion
eta = 0 # set eta 0 => no effect from non-linear p*q**2 term
T_0 = 300 # temperature of enviroment
k_b = scipy.constants.Boltzmann
m = 3.1e-19 # mass of oscillator
# set a and b functions for these 2 equations
def a_p(t, p, q):
return -(Gamma0 - Omega0*eta*q**2)*p
def b_p(t, p, q):
return np.sqrt(2*Gamma0*k_b*T_0/m)
def a_q(t, p, q):
return p
# generate time data
dt = 10e-11
tArray = np.arange(0, 200e-6, dt)
# initialise q and p arrays and set initial conditions to 0, 0
q0 = 0
p0 = 0
q = np.zeros_like(tArray)
p = np.zeros_like(tArray)
q[0] = q0
p[0] = p0
# generate normally distributed random numbers
dwArray = np.random.normal(0, np.sqrt(dt), len(tArray)) # independent and identically distributed normal random variables with expected value 0 and variance dt
# iterate through implementing Milstein's method (technically Euler-Maruyama since b' = 0
for n, t in enumerate(tArray[:-1]):
dw = dwArray[n]
p[n+1] = p[n] + a_p(t, p[n], q[n])*dt + b_p(t, p[n], q[n])*dw + 0
q[n+1] = q[n] + a_q(t, p[n], q[n])*dt + 0
Where in this case p is velocity and q is position.
I then get the following plots of q and p:
I expected the resulting plot of position to look something like the following, which I get from experimental data (from which the constants used in the model are determined):
Have I implemented Milstein's method correctly?
If I have, what else might be wrong my process of solving the SDE that'd causing this disagreement with the experiment?
You missed a term in the drift coefficient, note that to the right of dp there are two dt terms. Thus
def a_p(t, p, q):
return -(Gamma0 - Omega0*eta*q**2)*p - Omega0**2*q
which is actually the part that makes the oscillator into an oscillator. With that corrected the solution looks like
And no, you did not implement the Milstein method as there are no derivatives of b_p which are what distinguishes Milstein from Euler-Maruyama, the missing term is +0.5*b'(X)*b(X)*(dW**2-dt).
There is also a derivative-free version of Milsteins method as a two-stage kind-of Runge-Kutta method, documented in wikipedia or the original in arxiv.org (PDF).
The step there is (vector based, duplicate into X=[p,q], K1=[k1_p,k1_q] etc. to be close to your conventions)
S = random_choice_of ([-1,1])
K1 = a(X )*dt + b(X )*(dW - S*sqrt(dt))
Xh = X + K1
K2 = a(Xh)*dt + b(Xh)*(dW + S*sqrt(dt))
X = X + 0.5 * (K1+K2)

Make a standard deviation always positive in Metropolis-Hastings

I am trying Bayesian regression using Metropolis-Hastings. The test data is generated as follows (Python code, I didn't copy the entire code):
trueA = 5 ; trueB = 7 ;trueSD = 10 ; sample_size = 261
x = np.arange(-sample_size/8, sample_size/8, (sample_size*2/8)/sample_size)
y = trueA *x + trueB + npr.normal(loc=0, scale=trueSD, size=sample_size)
I defined log likelihood as follows:
def likelihood(param):
a = param[0][0] ; b = param[0][1] ; sd = param[0][2] ; pred = a*x + b
sumSqError = np.power((y - pred), 2).sum()
likelihoodsum = ((sample_size/2)*(np.log(1)-np.log(np.power(sd,2)))) + (- 1/(2*np.power(sd,2)) * sumSqError)
return likelihoodsum
To make next points, I prepared the following function:
def next_param(param, param_index):
a_next = param[0][0] ; b_next = param[0][1] ; sd_next = param[0][2]
if param_index == 0:
a_next = param[0][0] + npr.normal(0, 0.1)
elif param_index == 1:
b_next = param[0][1] + npr.normal(0, 0.1)
elif param_index == 2:
sd_next = param[0][2] + npr.normal(0, 0.1)
return np.array([[a_next, b_next, sd_next]])
This code works well (acceptance rate is high enough and I can estimate the parameters), though I know sd_next can go negative in the above code, which is weird.
So, I decided to use log for sd_next:
elif param_index == 2:
sd_next = np.log(param[0][2]) + npr.normal(0, 0.1)
return np.array([[a_next, b_next, np.exp(sd_next)]])
However, the estimated parameters are far from the true values. How can I make a standard deviation always positive in Metropolis-Hastings?
JFI, here is MCMC part:
num_sampling = 1000
chain = np.zeros((num_sampling, 1, 3))
chain[0][0][0] = 20 # starting value for a
chain[0][0][1] = 15 # starting value for b
chain[0][0][2] = 15 # starting value for sd
num_accepted = 0
for i in range(num_sampling-1):
chain_previous = chain[i][:]
chain_new = np.zeros((1, 1, 3))
for p in range(3):
proposal = next_param(chain_previous, p)
probab = likelihood(proposal) - likelihood(chain_previous)
if 0 < probab:
chain_new[0][0][p] = proposal[0][p]
num_accepted += 1
else:
chain_new[0][0][p] = chain[i][0][p]
chain[i+1] = chain_new[0][:]
It is not weird at all that you get a negative standard deviation $\sigma$ when your proposal is a Normal distribution, with support $(-\infty,+\infty)$.
And the Metropolis-Hastings accept-reject step should also include the prior distribution on the three parameters. Including the Jacobian when the proposal is on $\log\sigma$.
As written the Metropolis-Hastings accept-reject step is incorrect!
if 0 < probab:
is not the right condition for accepting a move to the proposed value: one should compared the (log-)probability with a (log-)uniform. In the current format, you converge to a maximum of the likelihood.

Categories

Resources