Windows子系统运行FEniCS时加法语句遇无效语法错误求助
别担心,刚接触FEniCS和PDE求解遇到语法错误太正常了,我帮你一步步排查并修复问题:
首先解决直接导致a = a0 + a1语法错误的根源
你的L1定义里存在**括号不匹配+重复积分测度dx**的问题,这会让Python解析器在处理到a = a0 + a1之前就已经语法出错了。原代码的L1:
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)
修复后:
L1 = (u0[1]*v[1]*dx) - (0.5*delta*dt*inner(grad(u0[1]), grad(v[1]))*dx) - dt*u0[1]*v[1]*(-beta*((u0[0]*u0[1])/(u0[0]+alpha)) - gamma*u0[1])*dx
- 补上了缺失的闭合括号
- 去掉了重复的
dx(FEniCS中每个积分项只需要一个dx测度)
其他必须修复的问题(否则语法过了也会运行报错)
- InitialConditions类的eval方法错误
你不能直接把Expression对象赋值给values数组,eval方法需要计算具体的数值。可以直接用Python代码计算表达式值:
class InitialConditions(UserExpression): def eval(self, values, x): # 计算第一个分量 term1 = (4/25) - 2e-7 * (x[0] - 0.1*x[1] - 225) * (x[0] - 0.1*x[1] - 675) values[0] = term1 # 计算第二个分量 term2 = (22/45) - 3e-5*(x[0]-450) - 1.2e-4*(x[1]-150) values[1] = term2 def value_shape(self): return (2,)
- L0的重复dx问题
原L0最后一项重复写了dx,修复后:
L0 = (u0[0]*v[0]*dx) - (0.5*delta*dt*inner(grad(u0[0]), grad(v[0]))*dx) - dt*u0[0]*v[0]*(((u0[0]*u0[1])/(u0[0]+alpha)) - u0[0]*(1-u0[0]))*dx
拼写错误
时间循环里的b = asseble(L)要改成b = assemble(L)(少写了一个s)未定义变量问题
- 你写了
DirichletBoundary()但没定义这个类,既然你打算用Neumann边界(已经写了bc = []),直接删掉bc = DirichletBC(V,u_initial,DirichletBoundary())这行 - 保存结果时用了
uv,但你定义的变量是u,改成out_file << (u,t) u_initial在边界条件里被提前使用了,既然不用Dirichlet边界,这部分可以忽略
修复后的完整代码
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): # 计算第一个分量的值 term1 = (4/25) - 2e-7 * (x[0] - 0.1*x[1] - 225) * (x[0] - 0.1*x[1] - 675) values[0] = term1 # 计算第二个分量的值 term2 = (22/45) - 3e-5*(x[0]-450) - 1.2e-4*(x[1]-150) values[1] = term2 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]*(((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]*(-beta*((u0[0]*u0[1])/(u0[0]+alpha)) - gamma*u0[1])*dx a = a0 + a1 L = L0 + L1 #Set up boundary condition (Neumann) bc = [] #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 = assemble(L) # 添加求解步骤,否则不会更新u的值 solve(A, u.vector(), b, bc) t_save += dt if t_save > T/ num_samples or t >= T-dt: print("Saving!") #Save the solution to file out_file << (u,t) t_save = 0 #Move to next interval and adjust boundary condition t += dt
哦对了,我还加了你漏掉的求解步骤:solve(A, u.vector(), b, bc),不然组装完矩阵和向量也不会更新u的值。
内容的提问来源于stack exchange,提问作者Kate




