I am a bit confused, I was successful in making my code returns what I think it should, but I don’t understand how/why.

At some point I do:

# Define ME function space
el = FiniteElement("CG", mesh.ufl_cell(), 1)
mel = MixedElement([el, el])
ME = FunctionSpace(mesh, mel)
u, v = TestFunction(ME)
TempVolt = Function(ME)
temp, volt = split(TempVolt)

And then I involve “temp” and “volt” in the weak form, i.e. I solve for temp and volt (I get the temperature distribution as well as the voltage one). So far so good.

However, I cannot write these solutions into files as I used to:

with io.XDMFFile(mesh.comm, "solution/voltage.xdmf", "w") as xdmf:
xdmf.write_mesh(mesh)
xdmf.write_function(volt)

would fail returning an error, complaining about the type of functions xdmf.write() can accept.

I fixed my problem by replacing “volt” by with “TempVolt.sub(1)”, and it seems to work well. But I do not understand why this works. As far as I understand, I solve for temp and volt. And I always used to save these solutions in files. Why would I need to invoke “TempVolt.sub(1)”? Why am I not solving for “TempVolt.sub(1)” in the weak form?

In [1]: import dolfin
dolfinx.
In [2]: dolfin.split??
In [3]: dolfin.split?
Signature: dolfin.split(v)
Docstring:
UFL operator: If v is a Coefficient or Argument in a mixed space, returns
a tuple with the function components corresponding to the subelements.
File: /usr/lib/python3/dist-packages/ufl/split_functions.py
Type: function

This is to be used in variational forms.

dolfin.split

In [4]: dolfin.Function.split?
Signature: dolfin.Function.split(self, deepcopy=False)
Docstring:
Extract any sub functions.
A sub function can be extracted from a discrete function that
is in a mixed, vector, or tensor FunctionSpace. The sub
function resides in the subspace of the mixed space.
*Arguments*
deepcopy
Copy sub function vector instead of sharing
File: /usr/lib/python3/dist-packages/dolfin/function/function.py
Type: function

which has the source code:

num_sub_spaces = self.num_sub_spaces()
if num_sub_spaces == 1:
raise RuntimeError("No subfunctions to extract")
return tuple(self.sub(i, deepcopy) for i in range(num_sub_spaces))

which in turn calls:

In [5]: dolfin.Function.sub?
Signature: dolfin.Function.sub(self, i, deepcopy=False)
Docstring:
Return a sub function.
The sub functions are numbered from i = 0..N-1, where N is the
total number of sub spaces.
*Arguments*
i : int
The number of the sub function
File: /usr/lib/python3/dist-packages/dolfin/function/function.py
Type: function