Dear Christopher, Thank you!
I rewrite the code, and now it can handle both the dirichelt and the neumann BCs! But when I plot the results, it seems like that gfu interpolate the value between [0, 0.1], Is it the right behavior of ngsolve? The problem is now -f’‘=2, f’(1)=-1, f(0)=1, and the ground truth is -x^2 + x + 1.
For example, in the following code, gfu(0.05) is 0.5474999999999999, which should be a value larger than f(0)
# https://ngsolve.org/forum/ngspy-forum/167-1-d-poisson-with-constant-forcing-function
import matplotlib.pyplot as plt
import ngsolve as ngs
from ngsolve import grad, dx, ds, BND
import netgen.meshing as ng
"""1. generate a 1D mesh"""
m = ng.Mesh()
m.dim = 1
nel = 10
pnums = []
# add nodes and ID
for i in range(nel+1):
node = ng.Pnt(i/nel, 0, 0)
m.Add(ng.MeshPoint(node))
pnums.append(i+1) # node index starts 1
# add elements
for i in range(nel):
m.Add(ng.Element1D([pnums[i], pnums[i+1]], index=1))
# set materials
m.SetMaterial(1, 'material')
# add BC points
m.Add(ng.Element0D(pnums[0], index=1))
m.Add(ng.Element0D(pnums[nel], index=2))
# set boundary condition names
m.SetBCName(0, 'left')
m.SetBCName(1, 'right')
print(pnums)
"""2. compute on this mesh"""
mesh = ngs.Mesh(m)
print(mesh.GetBoundaries())
# Specify Dirichlet boundary conditions
fes = ngs.H1(mesh, order=2, dirichlet='left')
# fes = ngs.H1(mesh, order=1, dirichlet=[1, 2])
print("ndof: ", fes.ndof)
print("freedofs: ", fes.FreeDofs())
u = fes.TrialFunction() # symbolic object
v = fes.TestFunction() # symbolic object
# coefficient/stiffness matrix
a = ngs.BilinearForm(fes)
a += grad(u) * grad(v) * dx
a.Assemble()
print("mat = \n", a.mat)
# theoretic solution
# source: -f''= 2
# neumann: f'(1) = -1
# dirichlet: f(0) = 1
# f = -x^2 + x + 1
# Source
f = ngs.LinearForm(fes)
source_b = 2
f += source_b * v * dx
# boundary conditions
# 1. f'(right)*n = b, Neumann boundary
neumann_b = -1
f += neumann_b * v * ds(definedon='right')
# form
f.Assemble()
print("rhs = \n", f.vec)
# solution
gfu = ngs.GridFunction(fes)
# 1. f(left) = a, dirichlet boundary
dirichlet_b = 1
# gfu.Set(dirichlet_b, BND)
gfu.Set(dirichlet_b, definedon=mesh.Boundaries("left"))
r = f.vec.CreateVector()
r.data = f.vec - a.mat * gfu.vec
# solve
gfu.vec.data = a.mat.Inverse(fes.FreeDofs()) * r
print ("sol = \n", gfu.vec)
"""3. plot"""
pnts = [i/100 for i in range(101)]
pnts_vals = [(x, gfu(x)) for x in pnts if mesh.Contains(x)]
fig, ax = plt.subplots()
pnts, vals = zip(*pnts_vals)
ax.plot(pnts, vals, "-b")
# ax.plot(gfu.vec, "-b")
plt.show()
# fig.savefig('ngsolve-2217.png')