Hey there,
introducing a new variable as suggested by Christopher did the trick.
However, I used a mass-lumped integration rule rather than the dual basis you suggested.
For future reference I quickly describe the solution which worked for me,
in case somebody else runs into a similar problem.
Notation:
a x b denotes the cross-product of a and b.
<., .> denotes the L2-inner product;
<., .>_h denotes the mass-lumped inner-product (defined in the code below)
For given GridFunction eta in X, consider the problem of finding a GridFunction u (in X), such that
<u, phi> + <u, curl(I_h(phi x eta))> = <f, phi>
for all TestFunctions phi in X.
Introducing a new variable v = I_h(phi x eta) one arrives at a system on XX = FESpace([X, X]) :
Find (u, w) in XX, such that
<u, phi> - <eta x w, phi>_h = <f, phi>
<u, curl(v)> + <w, v>_h = 0
for all TestFunctions (phi, v) in XX.
Plugging in v = I_h(phi x eta), one sees that the original equation is satisfied.
The NGS-Python code snippet for defining the bilinear form looks like this
Code:
myCurl = lambda Df : (Df[2,1] - Df[1,2], Df[0,2] - Df[2,0], Df[1,0] - Df[0,1])
massLumping = IntegrationRule( points = [(0,0,0), (1,0,0), (0,1,0), (0,0,1)],
weights = [1/24, 1/24, 1/24, 1/24] )
X = VectorH1(mesh, order=1)
XX = FESpace([X, X])
u, w = XX.TrialFunction()
phi, v = XX.TestFunction()
A = BilinearForm(XX)
A += SymbolicBFI(u * phi)
A += SymbolicBFI(u * myCurl(v.Deriv()))
A += SymbolicBFI(-Cross(eta, w) * phi, intrule=massLumping)
A += SymbolicBFI(w * v, intrule=massLumping)
The resulting (larger) system, however, takes pretty long to be solved.
So make sure to additionally decouple the DOFs of the Lagrange multiplier w
by using XX = FESpace([X, Discontinuous(X)]) instead,
and static condensation as described at:
ngsolve.org/docu/latest/i-tutorials/unit...cond/staticcond.html
Thank you Joachim for your further help,
Best regards,
Carl