Hi,
I am interested in the eigen-Problem for the Laplacian with boundary conditions which are not the homogene Dirichlet condition. In particular I tried to modify the Poisson example and got it to work with the Dirichlet boundary condition:
import numpy as np
import ufl
from dolfinx import fem, mesh, plot
from ufl import grad, dx, dot, inner
from mpi4py import MPI
from slepc4py import SLEPc
from petsc4py.PETSc import ScalarType
import matplotlib.pyplot as plt
import pyvista
msh = mesh.create_rectangle(comm=MPI.COMM_WORLD,
points=((0.0, 0.0), (2.0, 1.0)), n=(32, 16),
cell_type=mesh.CellType.triangle,)
V = fem.FunctionSpace(msh, ("Lagrange", 1))
facets = mesh.locate_entities_boundary(msh, dim=1,
marker=lambda x: np.logical_or(np.logical_or(np.isclose(x[0], 0.0),
np.isclose(x[0], 2.0)),np.logical_or(np.isclose(x[1], 0.0),
np.isclose(x[1], 1.0))))
dofs = fem.locate_dofs_topological(V=V, entity_dim=1, entities=facets)
bc = fem.dirichletbc(value=ScalarType(0), dofs=dofs, V=V)
u = ufl.TrialFunction(V)
v = ufl.TestFunction(V)
a = dot(grad(u), grad(v))*dx
L = inner(u, v) * dx
A = fem.petsc.assemble_matrix(fem.form(a), bcs=[bc])
A.assemble()
B = fem.petsc.assemble_matrix(fem.form(L), bcs=[bc])
B.assemble()
eigensolver = SLEPc.EPS().create(MPI.COMM_WORLD)
eigensolver.setOperators(A,B)
eigensolver.setType(SLEPc.EPS.Type.JD)
eigensolver.setWhichEigenpairs(eigensolver.Which.SMALLEST_REAL)
eigensolver.setDimensions(10)
eigensolver.solve()
vr, vi = A.getVecs()
uh = fem.Function(V)
cells, types, x = plot.create_vtk_mesh(V)
grid = pyvista.UnstructuredGrid(cells, types, x)
for i in range(4,eigensolver.getConverged()):
lmbda = eigensolver.getEigenpair(i, vr, vi)
print(lmbda/np.pi)
uh.vector.setArray(vr.array)
grid.point_data["u"] = uh.x.array.real
grid.set_active_scalars("u")
plotter = pyvista.Plotter()
plotter.add_mesh(grid, show_edges=True)
warped = grid.warp_by_scalar()
plotter.add_mesh(warped)
plotter.show()
Now if I change my boundary bc
to fem.dirichletbc(value=ScalarType(1), dofs=dofs, V=V)
I get the same result, the boundary condition seems to be ignored. I read up a bit, and saw that it might make sense to write u=u_0+u_g, where u_0 is equal to zero on the boundary and \forall x\in\partial \Omega : u_g(x)=g(x).
So my first question would be what do I have to do, to get a u which respects my boundary condition?
My second question would be quite similar: I wanted to solve the same problem, but with the same boundary condition as in the Poisson example. My naive approach would have been to start from the Poisson code and modifiy L=inner(f, v) * dx + inner(g, v) * ds
and then add the code to solve the eigen problem right after:
import numpy as np
import ufl
from dolfinx import fem, io, mesh, plot
from ufl import ds, dx, grad, inner
from mpi4py import MPI
from petsc4py.PETSc import ScalarType
from slepc4py import SLEPc
msh = mesh.create_rectangle(comm=MPI.COMM_WORLD,
points=((0.0, 0.0), (2.0, 1.0)), n=(32, 16),
cell_type=mesh.CellType.triangle,)
V = fem.FunctionSpace(msh, ("Lagrange", 1))
facets = mesh.locate_entities_boundary(msh, dim=1,
marker=lambda x: np.logical_or(np.isclose(x[0], 0.0),
np.isclose(x[0], 2.0)))
dofs = fem.locate_dofs_topological(V=V, entity_dim=1, entities=facets)
bc = fem.dirichletbc(value=ScalarType(0), dofs=dofs, V=V)
u = ufl.TrialFunction(V)
v = ufl.TestFunction(V)
x = ufl.SpatialCoordinate(msh)
f = 10 * ufl.exp(-((x[0] - 0.5) ** 2 + (x[1] - 0.5) ** 2) / 0.02)
g = ufl.sin(5 * x[0])
a = inner(grad(u), grad(v)) * dx
L = inner(u, v) * dx + inner(g, v) * ds
A = fem.petsc.assemble_matrix(fem.form(a), bcs=[bc])
A.assemble()
B = fem.petsc.assemble_matrix(fem.form(L), bcs=[bc])
B.assemble()
eigensolver = SLEPc.EPS().create(MPI.COMM_WORLD)
eigensolver.setOperators(A,B)
eigensolver.setType(SLEPc.EPS.Type.JD)
eigensolver.setWhichEigenpairs(eigensolver.Which.SMALLEST_REAL)
eigensolver.setDimensions(10)
eigensolver.solve()
vr, vi = A.getVecs()
uh = fem.Function(V)
cells, types, x = plot.create_vtk_mesh(V)
grid = pyvista.UnstructuredGrid(cells, types, x)
for i in range(9,eigensolver.getConverged()):
lmbda = eigensolver.getEigenpair(i, vr, vi)
print(lmbda/(np.pi))
uh.vector.setArray(vr.array)
grid.point_data["u"] = uh.x.array.real
grid.set_active_scalars("u")
plotter = pyvista.Plotter()
plotter.add_mesh(grid, show_edges=True)
warped = grid.warp_by_scalar()
plotter.add_mesh(warped)
plotter.show()
But I get an error while creating B:
File "[...]/src/eigenfunctions_laplace2.py", line 38, in <module>
B = fem.petsc.assemble_matrix(fem.form(L), bcs=[bc])
File "[...]/anaconda3/envs/fenicsx050/lib/python3.10/site-packages/dolfinx/fem/forms.py", line 166, in form
return _create_form(form)
...
ufl.algorithms.check_arities.ArityMismatch: Integrand arguments (Argument(FunctionSpace(Mesh(VectorElement(FiniteElement('Lagrange', triangle, 1), dim=2), 0), FiniteElement('Lagrange', triangle, 1)), 0, None),) differ from form arguments (Argument(FunctionSpace(Mesh(VectorElement(FiniteElement('Lagrange', triangle, 1), dim=2), 0), FiniteElement('Lagrange', triangle, 1)), 0, None), Argument(FunctionSpace(Mesh(VectorElement(FiniteElement('Lagrange', triangle, 1), dim=2), 0), FiniteElement('Lagrange', triangle, 1)), 1, None)).
How can I apply the same / similar boundary conditions to my eigen problem?