Hi Nate!
Yes, the standard Taylor-Hood pair works much better, although I have to increase the relative tolerance rather high (1e-02) for the model to converge in all cases. Not sure how normal this is.
I have also started adapting the stokes demo, first converting it to Navier-Stokes before trying to implement the MHD effects too however I’m having some issues.
I have the variational form as
a = form([[inner(grad(u), grad(v)) * dx, inner(dot(grad(u), u), v) * dx, inner(p, div(v)) * dx],
[inner(div(u), q) * dx, None]])
However, I think I have the form wrong as I’m getting errors.
Heres the code used and error message:
import numpy as np
import ufl
from dolfinx import cpp as _cpp
from dolfinx import fem
from dolfinx.fem import (Constant, Function, FunctionSpace, dirichletbc,
extract_function_spaces, form,
locate_dofs_geometrical, locate_dofs_topological)
from dolfinx.io import XDMFFile
from dolfinx.mesh import (CellType, GhostMode, create_rectangle,
locate_entities_boundary)
from ufl import div, dx, grad, inner, dot, nabla_grad
from mpi4py import MPI
from petsc4py import PETSc
# Create mesh
msh = create_rectangle(MPI.COMM_WORLD,
[np.array([0, 0]), np.array([1, 1])],
[100, 100],
CellType.triangle, GhostMode.none)
def noslip_boundary(x):
return np.logical_or(np.logical_or(np.isclose(x[0], 0.0),
np.isclose(x[0], 1.0)),
np.isclose(x[1], 0.0))
def lid(x):
return np.isclose(x[1], 1.0)
def lid_velocity_expression(x):
return np.stack((np.ones(x.shape[1]), np.zeros(x.shape[1])))
P2 = ufl.VectorElement("Lagrange", msh.ufl_cell(), 2)
P1 = ufl.FiniteElement("Lagrange", msh.ufl_cell(), 1)
V, Q = FunctionSpace(msh, P2), FunctionSpace(msh, P1)
# boundary conditions:
noslip = np.zeros(msh.geometry.dim, dtype=PETSc.ScalarType)
facets = locate_entities_boundary(msh, 1, noslip_boundary)
bc0 = dirichletbc(noslip, locate_dofs_topological(V, 1, facets), V)
lid_velocity = Function(V)
lid_velocity.interpolate(lid_velocity_expression)
facets = locate_entities_boundary(msh, 1, lid)
bc1 = dirichletbc(lid_velocity, locate_dofs_topological(V, 1, facets))
bcs = [bc0, bc1]
# Define variational problem
(u, p) = ufl.TrialFunction(V), ufl.TrialFunction(Q)
(v, q) = ufl.TestFunction(V), ufl.TestFunction(Q)
f = Constant(msh, (PETSc.ScalarType(0), PETSc.ScalarType(0)))
a = form([[inner(grad(u), grad(v)) * dx, inner(dot(grad(u), u), v) * dx, inner(p, div(v)) * dx],
[inner(div(u), q) * dx, None]])
L = form([inner(f, v) * dx, inner(Constant(msh, PETSc.ScalarType(0)), q) * dx])
# block-diagonal preconditioner:
a_p11 = form(inner(p, q) * dx)
a_p = [[a[0][0], None],
[None, a_p11]]
# ### Monolithic block iterative solver
A = fem.petsc.assemble_matrix_block(a, bcs=bcs)
A.assemble()
P = fem.petsc.assemble_matrix_block(a_p, bcs=bcs)
P.assemble()
b = fem.petsc.assemble_vector_block(L, a, bcs=bcs)
# Set near nullspace for pressure
null_vec = A.createVecLeft()
offset = V.dofmap.index_map.size_local * V.dofmap.index_map_bs
null_vec.array[offset:] = 1.0
null_vec.normalize()
nsp = PETSc.NullSpace().create(vectors=[null_vec])
assert nsp.test(A)
A.setNullSpace(nsp)
# Build IndexSets for each field (global dof indices for each field)
V_map = V.dofmap.index_map
Q_map = Q.dofmap.index_map
offset_u = V_map.local_range[0] * V.dofmap.index_map_bs + Q_map.local_range[0]
offset_p = offset_u + V_map.size_local * V.dofmap.index_map_bs
is_u = PETSc.IS().createStride(V_map.size_local * V.dofmap.index_map_bs, offset_u, 1, comm=PETSc.COMM_SELF)
is_p = PETSc.IS().createStride(Q_map.size_local, offset_p, 1, comm=PETSc.COMM_SELF)
# Create Krylov solver
ksp = PETSc.KSP().create(msh.comm)
ksp.setOperators(A, P)
ksp.setTolerances(rtol=1e-9)
ksp.setType("minres")
ksp.getPC().setType("fieldsplit")
ksp.getPC().setFieldSplitType(PETSc.PC.CompositeType.ADDITIVE)
ksp.getPC().setFieldSplitIS(
("u", is_u),
("p", is_p))
# Configure velocity and pressure sub KSPs
ksp_u, ksp_p = ksp.getPC().getFieldSplitSubKSP()
ksp_u.setType("preonly")
ksp_u.getPC().setType("gamg")
ksp_p.setType("preonly")
ksp_p.getPC().setType("jacobi")
# Monitor the convergence of the KSP
opts = PETSc.Options()
opts["ksp_monitor"] = None
opts["ksp_view"] = None
ksp.setFromOptions()
# Compute solution
x = A.createVecRight()
ksp.solve(b, x)
and error:
Traceback (most recent call last):
File "/home/fenics/shared/test.py", line 59, in <module>
a = form([[inner(grad(u), grad(v)) * dx, inner(dot(grad(u), u), v) * dx, inner(p, div(v)) * dx],
File "/usr/local/dolfinx-real/lib/python3.10/dist-packages/dolfinx/fem/forms.py", line 166, in form
return _create_form(form)
File "/usr/local/dolfinx-real/lib/python3.10/dist-packages/dolfinx/fem/forms.py", line 163, in _create_form
return list(map(lambda sub_form: _create_form(sub_form), form))
File "/usr/local/dolfinx-real/lib/python3.10/dist-packages/dolfinx/fem/forms.py", line 163, in <lambda>
return list(map(lambda sub_form: _create_form(sub_form), form))
File "/usr/local/dolfinx-real/lib/python3.10/dist-packages/dolfinx/fem/forms.py", line 163, in _create_form
return list(map(lambda sub_form: _create_form(sub_form), form))
File "/usr/local/dolfinx-real/lib/python3.10/dist-packages/dolfinx/fem/forms.py", line 163, in <lambda>
return list(map(lambda sub_form: _create_form(sub_form), form))
File "/usr/local/dolfinx-real/lib/python3.10/dist-packages/dolfinx/fem/forms.py", line 161, in _create_form
return _form(form)
File "/usr/local/dolfinx-real/lib/python3.10/dist-packages/dolfinx/fem/forms.py", line 135, in _form
ufcx_form, module, code = jit.ffcx_jit(mesh.comm, form,
File "/usr/local/dolfinx-real/lib/python3.10/dist-packages/dolfinx/jit.py", line 56, in mpi_jit
return local_jit(*args, **kwargs)
File "/usr/local/dolfinx-real/lib/python3.10/dist-packages/dolfinx/jit.py", line 204, in ffcx_jit
r = ffcx.codegeneration.jit.compile_forms([ufl_object], parameters=p_ffcx, **p_jit)
File "/usr/local/lib/python3.10/dist-packages/ffcx/codegeneration/jit.py", line 168, in compile_forms
impl = _compile_objects(decl, forms, form_names, module_name, p, cache_dir,
File "/usr/local/lib/python3.10/dist-packages/ffcx/codegeneration/jit.py", line 232, in _compile_objects
_, code_body = ffcx.compiler.compile_ufl_objects(ufl_objects, prefix=module_name, parameters=parameters)
File "/usr/local/lib/python3.10/dist-packages/ffcx/compiler.py", line 97, in compile_ufl_objects
analysis = analyze_ufl_objects(ufl_objects, parameters)
File "/usr/local/lib/python3.10/dist-packages/ffcx/analysis.py", line 85, in analyze_ufl_objects
form_data = tuple(_analyze_form(form, parameters) for form in forms)
File "/usr/local/lib/python3.10/dist-packages/ffcx/analysis.py", line 85, in <genexpr>
form_data = tuple(_analyze_form(form, parameters) for form in forms)
File "/usr/local/lib/python3.10/dist-packages/ffcx/analysis.py", line 168, in _analyze_form
form_data = ufl.algorithms.compute_form_data(
File "/usr/local/lib/python3.10/dist-packages/ufl/algorithms/compute_form_data.py", line 407, in compute_form_data
check_form_arity(preprocessed_form, self.original_form.arguments(), complex_mode) # Currently testing how fast this is
File "/usr/local/lib/python3.10/dist-packages/ufl/algorithms/check_arities.py", line 177, in check_form_arity
check_integrand_arity(itg.integrand(), arguments, complex_mode)
File "/usr/local/lib/python3.10/dist-packages/ufl/algorithms/check_arities.py", line 159, in check_integrand_arity
arg_tuples = map_expr_dag(rules, expr, compress=False)
File "/usr/local/lib/python3.10/dist-packages/ufl/corealg/map_dag.py", line 36, in map_expr_dag
result, = map_expr_dags(function, [expression], compress=compress,
File "/usr/local/lib/python3.10/dist-packages/ufl/corealg/map_dag.py", line 99, in map_expr_dags
r = handlers[v._ufl_typecode_](v, *[vcache[u] for u in v.ufl_operands])
File "/usr/local/lib/python3.10/dist-packages/ufl/algorithms/check_arities.py", line 63, in product
raise ArityMismatch("Multiplying expressions with overlapping form argument number {0}, argument is {1}.".format(x[0].number(), _afmt(x)))
File "/usr/local/lib/python3.10/dist-packages/ufl/algorithms/check_arities.py", line 19, in _afmt
return tuple("conj({0})".format(arg) if conj else str(arg)
File "/usr/local/lib/python3.10/dist-packages/ufl/algorithms/check_arities.py", line 20, in <genexpr>
for arg, conj in atuple)
TypeError: cannot unpack non-iterable bool object