我在Ubuntu 18.04上使用fenics。
我正在尝试调整此处描述的内容:https://fenicsproject.org/pub/tutorial/sphinx1/._ftut1005.html#setting-multiple-dirichlet-neumann-and-robin-conditions
我成功地在矩形区域中做到了这一点,并获得了纽曼条件$ \ frac {\ left {\ partial u \ right}} {\ partial n} = h $ 在顶部,而Dirichlet在边界的其余部分以$ u = g $为条件。
现在我正在尝试使用相同的矩形域,顶部使用相同的Newmann条件,而其余部分使用Robin的条件:$ \ alpha u + \ beta \ frac {\ partial u} {\ partial n} = h $
首先,我尝试使用$ g = h = 0 $ 0和f dirac的增量。但是出现了这个错误:
/usr/local/lib/python3.6/dist-packages/matplotlib/colors.py:504: RuntimeWarning: invalid value encountered in less
xa[xa < 0] = -1
这是我的代码:
from fenics import *
from dolfin import *
import matplotlib.pyplot as plt
# plot = lambda *args, **kwargs: None
import numpy as np
#parameters
x0 = 0.0#Constant(0)
xN = 8.0#Constant(8)
y0 = -4.0#Constant(-4)
yM = 0.0#Constant(0)
nx = 50#Constant(10)
ny = 15#Constant(10)
hx = (xN-x0)/(nx-1)
hy = (yM-y0)/(ny-1)
# fuente y salida
in_x = 4.0
in_y = 0.0
out_x = 7.0
out_y = 0.0
d=1
#mesh
mesh = RectangleMesh(Point(x0,y0), Point(xN,yM), nx, ny, "right")
boundary_markers = MeshFunction('size_t', mesh, mesh.topology().dim()-1)
V = FunctionSpace(mesh, 'Lagrange', d)
#boundaries
class BoundaryX0(SubDomain):
tol = 1E-14
def inside(self, x, on_boundary):
return on_boundary and near(x[0], x0, self.tol)
class BoundaryXN(SubDomain):
tol = 1E-14
def inside(self, x, on_boundary):
return on_boundary and near(x[0], xN, self.tol)
class BoundaryY0(SubDomain):
tol = 1E-14
def inside(self, x, on_boundary):
return on_boundary and near(x[1], y0, self.tol)
class BoundaryYM(SubDomain):
tol = 1E-14
def inside(self, x, on_boundary):
return on_boundary and near(x[1], yM, self.tol)
bx0 = BoundaryX0()
bx0.mark(boundary_markers, 4)
bx1 = BoundaryXN()
bx1.mark(boundary_markers, 1)
by0 = BoundaryY0()
by0.mark(boundary_markers, 2)
byM = BoundaryYM()
byM.mark(boundary_markers, 3)
# dirichlet
h = Constant(0) #Expression("100*cos(x[0]*x[1])", degree=d) #Constant(0)
# newmann
g = Constant(0) #Expression("cos(x[0])", degree=1) #Constant(0)
boundary_conditions = {4: {'Robin': h},
1: {'Robin': h},
2: {'Robin': h},
3: {'Neumann': g}}
ds = Measure('ds', domain=mesh, subdomain_data=boundary_markers)
# Define variational problem
u = TrialFunction(V)
v = TestFunction(V)
p = Expression("0.015+0.005*cos(3.5+x[1])", degree=d) #Constant(0.01) # #
I = 1.0
DV = hx*hy
M = I/DV
alpha = Expression("x[0]/(x[0]*x[0]+x[1]*x[1])", degree=d)
beta = Constant(1.0)
# source
f = Constant(0) #Expression("cos(x[0]+x[1])", degree=d) #Constant(0) #source term
integrals_R_L = []
integrals_R_a = []
for i in boundary_conditions:
if 'Robin' in boundary_conditions[i]:
if boundary_conditions[i]['Robin'] != 0:
hi = boundary_conditions[i]['Robin']
integrals_R_L.append((p*hi*v/beta)*ds(i))
integrals_R_a.append((alpha*p*u*v/beta)*ds(i))
a = p*inner(nabla_grad(u), nabla_grad(v))*dx + sum(integrals_R_a)
L = f*v*dx + p*g*v*ds(3) + sum(integrals_R_L)
# Compute solution
A, b = assemble_system(a, L)
# Add delta
delta1 = PointSource(V, Point(in_x, in_y), M)
delta1.apply(b)
# delta2 = PointSource(V, Point(out_x, out_y), -M)
# delta2.apply(b)
u = Function(V)
solve(A, u.vector(), b)
#plot y=k
y = 0.0
meshx = IntervalMesh(nx, x0, xN)
W = FunctionSpace(meshx,"Lagrange",d)
w = Function(W)
coor = meshx.coordinates()
w_array = w.vector()#.array()
if meshx.num_vertices() == len(w_array):
for i in range(meshx.num_vertices()):
w_array[i] = u(coor[i][0],y)
w.vector().set_local(w_array)
# plots
plt.subplot(2,3,1)
plot(f, mesh=mesh, title = "f: source term")
# plt.savefig('vc_poisson/f.png')
plt.subplot(2,3,2)
plot(h, mesh=mesh, title = "h: Dirichlet boundary condition")
plt.subplot(2,3,3)
plot(g, mesh=mesh, title = "g: Newmman boundary condition")
# plt.savefig('vc_poisson/g.png')
plt.subplot(2,3,4)
plot(p, mesh=mesh, title = "\sigma: resistivity distribution")
# plt.savefig('vc_poisson/g.png')
plt.subplot(2,3,5)
plot(u, title = "numerical solution")
# plt.savefig('vc_poisson/sol.png')
# plt.subplot(2,3,5)
# plot(mesh)
# plot(u, interactive=True, title = "numerical solution + mesh")
plt.subplot(2,3,6)
plot(w, title="numerical solution u(x,0)")
plt.savefig('vc_poisson/solution.png')
plt.figure()
plot(u.root_node(), mode='warp', title="numerical solution surface")
plt.savefig('vc_poisson/solution_surface.png')
# Save solution to file in VTK format
vtkfile = File('vc_poisson/solution.pvd')
vtkfile << u
plt.show()
错误似乎出在运算符a
的罗宾边界sum(integrals_R_a)
上的积分上。如果我对此发表评论,那么代码会运行,但显然解决方案不是我期望的。我必须补充说,我已经2周大了。
那么,我在做什么错了?