As a starting experiment in FEniCS I am trying to solve the 1D wave equation \frac{\partial^2 u}{\partial t^2} = c^2\frac{\partial^2 u}{\partial x^2} with fixed boundary conditions on the unit interval. As initial conditions I choose u_0(x)=x(1-x).
For solving the time dependence I want to use the Crank Nicolson method, i.e. u_{n+1}=u_n + \Delta t (\frac{1}{2}\frac{du}{dt}(u_{n+1}) + \frac{1}{2}\frac{du}{dt}(u_n)).
Since there is a second time derivative in the wave equation I want to use a 2D function space to solve the resulting equation system. So far my code for solving the first time step is
from fenics import *
T = 1
nt = 100
dt = T / nt
c = 1
mesh = UnitIntervalMesh(100)
V1 = FiniteElement('Lagrange', mesh.ufl_cell(), 1)
V2 = FiniteElement('Lagrange', mesh.ufl_cell(), 1)
element = MixedElement([V1, V2])
V = FunctionSpace(mesh, element)
def boundary(x, on_boundary):
return on_boundary
bc1 = DirichletBC(V.sub(0), Constant(0), boundary)
bc2 = DirichletBC(V.sub(0), Constant(0), boundary)
class InitialConditions(UserExpression):
def __init__(self, **kwargs):
super().__init__(**kwargs)
def eval(self, values, x):
values[0] = x[0] * (1 - x[0])
values[1] = 0.0
def value_shape(self):
return (2,)
un = Function(V)
u0 = InitialConditions(degree=2)
un.interpolate(u0)
un1, un2 = split(un)
u1, u2 = TrialFunctions(V)
v1, v2 = TestFunctions(V)
a1 = u1 * v1 * dx - Constant(0.5 * dt) * u2 * v1 * dx
L1 = un1 * v1 * dx + Constant(0.5 * dt) * un2 * v1 * dx
a2 = u2 * v2 * dx + Constant(0.5 * c**2 * dt) * inner(grad(u1), grad(v2)) * dx
L2 = un2 * v2 * dx - Constant(0.5 * c**2 * dt) * inner(grad(u2), grad(v2)) * dx
a = a1 + a2
L = L1 + L2
uh = Function(V)
solve(a==L, uh, [bc1, bc2])
When I run this I get an error message about an ArityMismatch
which I cannot make sense of
ArityMismatch Traceback (most recent call last)
<ipython-input-9-f0f502a6e073> in <module>()
1 uh = Function(V)
----> 2 solve(a==L, uh, [bc1, bc2])
/usr/local/lib/python3.6/dist-packages/dolfin/fem/solving.py in solve(*args, **kwargs)
218 # tolerance)
219 elif isinstance(args[0], ufl.classes.Equation):
--> 220 _solve_varproblem(*args, **kwargs)
221
222 # Default case, just call the wrapped C++ solve function
/usr/local/lib/python3.6/dist-packages/dolfin/fem/solving.py in _solve_varproblem(*args, **kwargs)
240 # Create problem
241 problem = LinearVariationalProblem(eq.lhs, eq.rhs, u, bcs,
--> 242 form_compiler_parameters=form_compiler_parameters)
243
244 # Create solver and call solve
/usr/local/lib/python3.6/dist-packages/dolfin/fem/problem.py in __init__(self, a, L, u, bcs, form_compiler_parameters)
53 L = cpp.fem.Form(1, 0)
54 else:
---> 55 L = Form(L, form_compiler_parameters=form_compiler_parameters)
56 a = Form(a, form_compiler_parameters=form_compiler_parameters)
57
/usr/local/lib/python3.6/dist-packages/dolfin/fem/form.py in __init__(self, form, **kwargs)
43
44 ufc_form = ffc_jit(form, form_compiler_parameters=form_compiler_parameters,
---> 45 mpi_comm=mesh.mpi_comm())
46 ufc_form = cpp.fem.make_ufc_form(ufc_form[0])
47
/usr/local/lib/python3.6/dist-packages/dolfin/jit/jit.py in mpi_jit(*args, **kwargs)
45 # Just call JIT compiler when running in serial
46 if MPI.size(mpi_comm) == 1:
---> 47 return local_jit(*args, **kwargs)
48
49 # Default status (0 == ok, 1 == fail)
/usr/local/lib/python3.6/dist-packages/dolfin/jit/jit.py in ffc_jit(ufl_form, form_compiler_parameters)
95 p.update(dict(parameters["form_compiler"]))
96 p.update(form_compiler_parameters or {})
---> 97 return ffc.jit(ufl_form, parameters=p)
98
99
/usr/local/lib/python3.6/dist-packages/ffc/jitcompiler.py in jit(ufl_object, parameters, indirect)
215
216 # Inspect cache and generate+build if necessary
--> 217 module = jit_build(ufl_object, module_name, parameters)
218
219 # Raise exception on failure to build or import module
/usr/local/lib/python3.6/dist-packages/ffc/jitcompiler.py in jit_build(ufl_object, module_name, parameters)
131 name=module_name,
132 params=params,
--> 133 generate=jit_generate)
134 return module
135
/usr/local/lib/python3.6/dist-packages/dijitso/jit.py in jit(jitable, name, params, generate, send, receive, wait)
163 elif generate:
164 # 1) Generate source code
--> 165 header, source, dependencies = generate(jitable, name, signature, params["generator"])
166 # Ensure we got unicode from generate
167 header = as_unicode(header)
/usr/local/lib/python3.6/dist-packages/ffc/jitcompiler.py in jit_generate(ufl_object, module_name, signature, parameters)
64
65 code_h, code_c, dependent_ufl_objects = compile_object(ufl_object,
---> 66 prefix=module_name, parameters=parameters, jit=True)
67
68 # Jit compile dependent objects separately,
/usr/local/lib/python3.6/dist-packages/ffc/compiler.py in compile_form(forms, object_names, prefix, parameters, jit)
141 """This function generates UFC code for a given UFL form or list of UFL forms."""
142 return compile_ufl_objects(forms, "form", object_names,
--> 143 prefix, parameters, jit)
144
145
/usr/local/lib/python3.6/dist-packages/ffc/compiler.py in compile_ufl_objects(ufl_objects, kind, object_names, prefix, parameters, jit)
183 # Stage 1: analysis
184 cpu_time = time()
--> 185 analysis = analyze_ufl_objects(ufl_objects, kind, parameters)
186 _print_timing(1, time() - cpu_time)
187
/usr/local/lib/python3.6/dist-packages/ffc/analysis.py in analyze_ufl_objects(ufl_objects, kind, parameters)
88 # Analyze forms
89 form_datas = tuple(_analyze_form(form, parameters)
---> 90 for form in forms)
91
92 # Extract unique elements accross all forms
/usr/local/lib/python3.6/dist-packages/ffc/analysis.py in <genexpr>(.0)
88 # Analyze forms
89 form_datas = tuple(_analyze_form(form, parameters)
---> 90 for form in forms)
91
92 # Extract unique elements accross all forms
/usr/local/lib/python3.6/dist-packages/ffc/analysis.py in _analyze_form(form, parameters)
172 do_apply_geometry_lowering=True,
173 preserve_geometry_types=(Jacobian,),
--> 174 do_apply_restrictions=True)
175 elif r == "tsfc":
176 try:
/usr/local/lib/python3.6/dist-packages/ufl/algorithms/compute_form_data.py in compute_form_data(form, do_apply_function_pullbacks, do_apply_integral_scaling, do_apply_geometry_lowering, preserve_geometry_types, do_apply_default_restrictions, do_apply_restrictions, do_estimate_degrees)
392 # faster!
393 preprocessed_form = reconstruct_form_from_integral_data(self.integral_data)
--> 394 check_form_arity(preprocessed_form, self.original_form.arguments()) # Currently testing how fast this is
395
396 # TODO: This member is used by unit tests, change the tests to
/usr/local/lib/python3.6/dist-packages/ufl/algorithms/check_arities.py in check_form_arity(form, arguments)
150 def check_form_arity(form, arguments):
151 for itg in form.integrals():
--> 152 check_integrand_arity(itg.integrand(), arguments)
/usr/local/lib/python3.6/dist-packages/ufl/algorithms/check_arities.py in check_integrand_arity(expr, arguments)
143 key=lambda x: (x.number(), x.part())))
144 rules = ArityChecker(arguments)
--> 145 args = map_expr_dag(rules, expr, compress=False)
146 if args != arguments:
147 raise ArityMismatch("Integrand arguments {0} differ from form arguments {1}.".format(args, arguments))
/usr/local/lib/python3.6/dist-packages/ufl/corealg/map_dag.py in map_expr_dag(function, expression, compress)
35 Return the result of the final function call.
36 """
---> 37 result, = map_expr_dags(function, [expression], compress=compress)
38 return result
39
/usr/local/lib/python3.6/dist-packages/ufl/corealg/map_dag.py in map_expr_dags(function, expressions, compress)
84 r = handlers[v._ufl_typecode_](v)
85 else:
---> 86 r = handlers[v._ufl_typecode_](v, *[vcache[u] for u in v.ufl_operands])
87
88 # Optionally check if r is in rcache, a memory optimization
/usr/local/lib/python3.6/dist-packages/ufl/algorithms/check_arities.py in sum(self, o, a, b)
40 def sum(self, o, a, b):
41 if a != b:
---> 42 raise ArityMismatch("Adding expressions with non-matching form arguments {0} vs {1}.".format(a, b))
43 return a
44
ArityMismatch: Adding expressions with non-matching form arguments (Argument(FunctionSpace(Mesh(VectorElement(FiniteElement('Lagrange', interval, 1), dim=1), 5), MixedElement(FiniteElement('Lagrange', interval, 1), FiniteElement('Lagrange', interval, 1))), 0, None),) vs (Argument(FunctionSpace(Mesh(VectorElement(FiniteElement('Lagrange', interval, 1), dim=1), 5), MixedElement(FiniteElement('Lagrange', interval, 1), FiniteElement('Lagrange', interval, 1))), 0, None), Argument(FunctionSpace(Mesh(VectorElement(FiniteElement('Lagrange', interval, 1), dim=1), 5), MixedElement(FiniteElement('Lagrange', interval, 1), FiniteElement('Lagrange', interval, 1))), 1, None)).
I assume that some definitions for the forms are not compatible with each other. Can someone help me with this issue? I am using the FEniCS 2019.1 in a Docker container on Windows 10