Hi all,
Background
I want to perform a coordinate transform of my PDE, the Helmholtz equation. This coordinate transform is prescribed by another PDE which I solve in disjoint regions. Because this is solved in disjoint regions it is not continuously differentiable. To finally transform the Helmholtz equation I introduce, among other terms, a discontinuous Jacobian.
To be able to use the calculated transformation in the weak formulation of the Helmholtz equation, I have to map the values of the computed coordinate transformation onto a function that is defined on the mesh of the complete space.
To obtain the values at the vertices of the mesh of the solution x_transform
I can do
values_x_transform = x_transform.x.array
However, I cannot do the same to get the values at the vertices of the derivative of x_transform
, Dx(x_transform, 0)
. I would like to do something like
x_transform_derivative = Dx(x_transform, 0)
values_x_transform_derivative = x_transform_derivative.x.array
But this is not possible. I currently do this by solving an auxillary equation:
u = TrialFunction(V)
v = TestFunction(V)
a = inner(u, v) * dx
L = inner(x_transform_derivative, v) * dx
uh = Function(V)
problem = fem.LinearProblem(a, L, u=uh, petsc_options={"ksp_type": "preonly", "pc_type": "lu"})
problem.solve()
values = uh.x.array # Extract sought vector
but this sounds rather wasteful on the computer resource front because a complete system has to be solved for this.
Question
Can I evaluate an UFL expression g
at the mesh points of the underlying mesh? I have tried g(mesh.geometry.x)
but this results in an infinite recursion loop.
A minimal working example (MWE) would be
import dolfinx
from dolfinx import FunctionSpace, Function, fem
from mpi4py import MPI
from dolfinx.generation import UnitSquareMesh
from ufl import TrialFunction, TestFunction, inner, dx, Dx
mesh = UnitSquareMesh(MPI.COMM_WORLD, 8, 8, dolfinx.cpp.mesh.CellType.quadrilateral)
V = FunctionSpace(mesh, ("CG", 1))
f = Function(V)
f.interpolate(lambda x: (x[0] ** 2) * (1 + 1j)) # An interesting nonzero example
g = Dx(f, 0) # Some ufl expression we want to evaluate
g(mesh.geometry.x) # Segfault due to infinite recursion:
'''
Infinite recursion encountered:
(...)
File "/../ufl/core/expr.py", line 318 in __float__
File "/../ufl/core/terminal.py", line 50 in evaluate
File "/../ufl/exproperators.py", line 320 in _eval
File "/../ufl/exproperators.py", line 330 in _call
File "/../ufl/core/expr.py", line 313 in _ufl_evaluate_scalar_
File "/../ufl/core/expr.py", line 318 in __float__
File "/../ufl/core/terminal.py", line 50 in evaluate
File "/../ufl/exproperators.py", line 320 in _eval
File "/../ufl/exproperators.py", line 330 in _call
File "/../ufl/core/expr.py", line 313 in _ufl_evaluate_scalar_
(...)
'''
# ---- Known solution, presumably rather slow because a full linear system needs to be solved ---- #
u = TrialFunction(V)
v = TestFunction(V)
a = inner(u, v) * dx
L = inner(g, v) * dx
uh = Function(V)
problem = fem.LinearProblem(a, L, u=uh, petsc_options={"ksp_type": "preonly", "pc_type": "lu"})
problem.solve()
values = uh.x.array # Extract sought vector
Can I extract the values of the UFL expression at the mesh points without solving an auxillary problem as I have done above?
More information:
I use the Docker image build from the 0.3.0 release with complex mode enabled.
Many thanks in advance!
-Wouter