You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

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测度)

其他必须修复的问题(否则语法过了也会运行报错)

  1. 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,)
  1. 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
  1. 拼写错误
    时间循环里的b = asseble(L)要改成b = assemble(L)(少写了一个s

  2. 未定义变量问题

  • 你写了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

火山引擎 最新活动