Hi, I’m trying to convert my FEniCS code to FEniCSx. In particular I’m trying to implement a mixed formulation (strain/displacement) using stabilization terms in order to use the same interpolation in both fields (P1/P1). This wasn’t a problem in FEniCS using project()
in the variational form, but in FEniCSx I’m getting the following error:
Info : Reading 'mesh/cooks_membrane_2.msh'...
Info : 9 nodes
Info : 12 elements
Info : Done reading 'mesh/cooks_membrane_2.msh'
Traceback (most recent call last):
File "/home/batipc/fenicsx/1-TEST_linear/sample.py", line 121, in <module>
FF = -tau_eps(W)*(as_tensor(gamma[i,j]*C0[i,j,k,l]*Orth_proj(W_eps,sym(nabla_grad(u)),sym(nabla_grad(uk)))[k,l]))*dx \
File "/home/batipc/fenicsx/1-TEST_linear/sample.py", line 84, in Orth_proj
proj = (res - proj2space(res_k, W))
File "/home/batipc/fenicsx/1-TEST_linear/sample.py", line 46, in proj2space
L = form(inner(v, w) * dx)
File "/home/batipc/anaconda3/envs/fenicsx-env/lib/python3.10/site-packages/dolfinx/fem/forms.py", line 176, in form
return _create_form(form)
File "/home/batipc/anaconda3/envs/fenicsx-env/lib/python3.10/site-packages/dolfinx/fem/forms.py", line 171, in _create_form
return _form(form)
File "/home/batipc/anaconda3/envs/fenicsx-env/lib/python3.10/site-packages/dolfinx/fem/forms.py", line 145, in _form
ufcx_form, module, code = jit.ffcx_jit(mesh.comm, form,
File "/home/batipc/anaconda3/envs/fenicsx-env/lib/python3.10/site-packages/dolfinx/jit.py", line 56, in mpi_jit
return local_jit(*args, **kwargs)
File "/home/batipc/anaconda3/envs/fenicsx-env/lib/python3.10/site-packages/dolfinx/jit.py", line 204, in ffcx_jit
r = ffcx.codegeneration.jit.compile_forms([ufl_object], options=p_ffcx, **p_jit)
File "/home/batipc/anaconda3/envs/fenicsx-env/lib/python3.10/site-packages/ffcx/codegeneration/jit.py", line 186, in compile_forms
impl = _compile_objects(decl, forms, form_names, module_name, p, cache_dir,
File "/home/batipc/anaconda3/envs/fenicsx-env/lib/python3.10/site-packages/ffcx/codegeneration/jit.py", line 250, in _compile_objects
_, code_body = ffcx.compiler.compile_ufl_objects(ufl_objects, prefix=module_name, options=options)
File "/home/batipc/anaconda3/envs/fenicsx-env/lib/python3.10/site-packages/ffcx/compiler.py", line 102, in compile_ufl_objects
ir = compute_ir(analysis, object_names, prefix, options, visualise)
File "/home/batipc/anaconda3/envs/fenicsx-env/lib/python3.10/site-packages/ffcx/ir/representation.py", line 200, in compute_ir
irs = [
File "/home/batipc/anaconda3/envs/fenicsx-env/lib/python3.10/site-packages/ffcx/ir/representation.py", line 201, in <listcomp>
_compute_integral_ir(fd, i, analysis.element_numbers, integral_names, finite_element_names,
File "/home/batipc/anaconda3/envs/fenicsx-env/lib/python3.10/site-packages/ffcx/ir/representation.py", line 485, in _compute_integral_ir
integral_ir = compute_integral_ir(itg_data.domain.ufl_cell(), itg_data.integral_type,
File "/home/batipc/anaconda3/envs/fenicsx-env/lib/python3.10/site-packages/ffcx/ir/integral.py", line 72, in compute_integral_ir
S = build_scalar_graph(expression)
File "/home/batipc/anaconda3/envs/fenicsx-env/lib/python3.10/site-packages/ffcx/ir/analysis/graph.py", line 80, in build_scalar_graph
scalar_expressions = rebuild_with_scalar_subexpressions(G)
File "/home/batipc/anaconda3/envs/fenicsx-env/lib/python3.10/site-packages/ffcx/ir/analysis/graph.py", line 125, in rebuild_with_scalar_subexpressions
V_symbols = value_numberer.compute_symbols()
File "/home/batipc/anaconda3/envs/fenicsx-env/lib/python3.10/site-packages/ffcx/ir/analysis/valuenumbering.py", line 68, in compute_symbols
symbol = f(expr)
File "/home/batipc/anaconda3/envs/fenicsx-env/lib/python3.10/site-packages/ffcx/ir/analysis/valuenumbering.py", line 184, in _modified_terminal
raise RuntimeError("Internal error in value numbering.")
RuntimeError: Internal error in value numbering.
In this case, I’m using a projection similar to the one used in dolfiny here https://github.com/michalhabera/dolfiny/blob/master/dolfiny/projection.py. Here’s my minimal example and geometry for the msh file (here I’m using only the stabilization term to reproduce the error):
$MeshFormat
2.2 0 8
$EndMeshFormat
$PhysicalNames
3
1 1 "izq"
1 2 "der"
2 1 "surface"
$EndPhysicalNames
$Nodes
9
1 0 0 0
2 0 44 0
3 48 60 0
4 48 44 0
5 0 22 0
6 23.99999999999994 51.99999999999998 0
7 48 52 0
8 23.99999999999996 21.99999999999996 0
9 23.99999999999995 36.99999999999997 0
$EndNodes
$Elements
12
1 1 2 1 1 1 5
2 1 2 1 1 5 2
3 1 2 2 3 3 7
4 1 2 2 3 7 4
5 2 2 1 6 1 5 8
6 2 2 1 6 8 5 9
7 2 2 1 6 8 9 4
8 2 2 1 6 4 9 7
9 2 2 1 6 5 2 9
10 2 2 1 6 9 2 6
11 2 2 1 6 9 6 7
12 2 2 1 6 7 6 3
$EndElements
import os
import numpy as np
from ufl import (FiniteElement,VectorElement, TensorElement, MixedElement, Measure, TestFunction, TrialFunction,
split, as_tensor, dot, inner, nabla_grad, sym, indices, derivative, CellDiameter, dx, ds)
from mpi4py import MPI
from petsc4py import PETSc
from dolfinx.fem import (Constant, Function, FunctionSpace, VectorFunctionSpace, TensorFunctionSpace,
assemble_scalar, dirichletbc, form, locate_dofs_topological, set_bc,assemble,Expression)
from dolfinx.fem.petsc import (apply_lifting, assemble_matrix, assemble_vector,
create_vector, create_matrix, set_bc)
from dolfinx.io import (XDMFFile, gmshio)
## ***************** Functions *****************
def build_space(_name,_comm,_gdim):
#Import mesh
mesh, _, facets= gmshio.read_from_msh(_name, _comm, gdim=_gdim)
# Build mixed function space
P1 = VectorElement("CG",mesh.ufl_cell(),1) # displacement
P2 = TensorElement("CG",mesh.ufl_cell(),1,symmetry = True) # strain
MX = MixedElement([P1,P2])
W = FunctionSpace(mesh,MX)
# Dirichlet boundary conditions
fdim = mesh.topology.dim - 1
dofs_i0 = locate_dofs_topological(W.sub(0).sub(0), fdim, facets.find(1))
dofs_i1 = locate_dofs_topological(W.sub(0).sub(1), fdim, facets.find(1))
bcs = []
bc_izq1 = dirichletbc(PETSc.ScalarType((0.0)), dofs_i0, W.sub(0).sub(0)) # clamped side (left) -> Ux(0)=0
bc_izq2 = dirichletbc(PETSc.ScalarType((0.0)), dofs_i1, W.sub(0).sub(1)) # clamped side (left) -> Uy(0)=0
bcs.append(bc_izq1);bcs.append(bc_izq2)
return W,bcs,mesh,facets
def proj2space(v, V, bcs=[]):
metad = {"quadrature_degree": 2}
dx = Measure('dx', domain=mesh, metadata=metad)
# Define variational problem for projection
w = TestFunction(V)
Pv = TrialFunction(V)
a = form(inner(Pv, w) * dx)
L = form(inner(v, w) * dx)
# Assemble linear system
A = assemble_matrix(a, bcs)
A.assemble()
b = assemble_vector(L)
apply_lifting(b, [a], [bcs])
b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE)
set_bc(b, bcs)
# Solve linear system
solver = PETSc.KSP().create(A.getComm())
solver.setOperators(A)
uh = Function(V)
solver.solve(b, u.vector)
return uh
#%% Define constitutive tensor (list)
def VoigtTo4Tensor_2d(A):
A11, A12, A13 = A[0,0], A[0,1], A[0,2]
A22, A23 = A[1,1], A[1,2]
A33 = A[2,2]
A21 , A31 = A12 , A13
A32 = A23
return [ [ \
[ [ A11 , A13 ] , [ A13 , A12 ] ] , \
[ [ A31 , A33 ] , [ A33 , A32 ] ] , \
] , [ \
[ [ A31 , A33 ] , [ A33 , A32 ] ] , \
[ [ A21 , A23 ] , [ A23 , A22 ] ] ] ]
#%% Stabilization parameters
def tau_eps(W):
h = CellDiameter(W.mesh)
return ce*h/L0
#%% Orthogonal projection VMS
def Orth_proj(W,res,res_k):
proj = (res - proj2space(res_k, W))
return proj
#%% ***************** Main *************************
#import mesh
comm = MPI.COMM_WORLD
name = "mesh/cooks_membrane_2.msh"
gdim = 2
W,bcs,mesh,facets = build_space(name,comm,gdim) # Facets: 1->left, 2->right
# Scalar variables
E = Constant(mesh,PETSc.ScalarType(200e3)) # Young's Moduli [MPa]
nu = Constant(mesh,PETSc.ScalarType(0.3)) # Poisson Coefficient
L0 = Constant(mesh,PETSc.ScalarType(50.0)) # Characteristic lenght [mm]
ce = Constant(mesh,PETSc.ScalarType(1.0)) # Arbitrary constant for tau_eps
# Compute constitutive tensor for plain strain
C_voigt = E/(1+nu)/(1-2*nu)*np.array([ [1-nu, nu , 0],\
[ nu , 1-nu, 0],\
[ 0 , 0 , (1-2*nu)/2]])
C0 = as_tensor(VoigtTo4Tensor_2d(C_voigt)) # Constitutive tensor
#Functions over the mesh
w = Function(W) # mixed function (u,eps)
u,eps = split(w) # split mixed function
z = TestFunction(W) # test function (v,gamma)
v,gamma = split(z) # split test function
wk = Function(W) # mixed function (uk,epsk) at previous iteration
uk,epsk = split(wk) # split mixed function at previous iteration
# Defining variational problem
W_eps,_ = W.sub(1).collapse()
T = Constant(mesh, PETSc.ScalarType((0, 1000))) # Traction forces [N/mm]
i,j,k,l = indices(4)
# First error
ds = Measure('ds', domain=mesh, subdomain_data=facets)
FF = -tau_eps(W)*(as_tensor(gamma[i,j]*C0[i,j,k,l]*Orth_proj(W_eps,sym(nabla_grad(u)),sym(nabla_grad(uk)))[k,l]))*dx \
- dot(v,T)*ds(2) # Variational form
# Second error
# FF2 = -tau_eps(W)*(as_tensor(gamma[i,j]*C0[i,j,k,l]*sym(nabla_grad(u))[k,l]))*dx - dot(v,T)*ds(2) # Variational form
# JJ = derivative(FF2, w) # Jacobian
# residual = form(FF2)
# jacob = form(JJ)
# ... newton solver
I’m getting the same error when using instead a mixed variational form that doesn’t use a projection (FF2
). Seems like the error comes when using the function form()
with the mixed form. Is it not compatible? I’m interested in using this to use a custom newton solver like the one showed in this tutorial: Custom Newton solvers — FEniCSx tutorial. I’m using Dolfinx v0.6.0 in conda