My solution is complex and I cant figure out why!

Hi reader,

In one of my previous questions I posted the following code.
Now I found out, that for some strange reason, the solution has type np.complex128 with the imaginary part being 0. This makes me wonder, because I put quite the efford into making sure each matrix or vector is set to the correct datatype. Can someone help me, what I missed?
Thanks in advance!

What installation of PETSc are you using?
How did you install DOLFINx?

I use the docker image: dolfinx/lab:stable.

! pip show fenics-dolfinx

returned:

Name: fenics-dolfinx
Version: 0.6.0
Summary: DOLFINx Python interface
Home-page: UNKNOWN
Author: FEniCS Project
Author-email: 
License: UNKNOWN
Location: /usr/local/dolfinx-complex/lib/python3.10/dist-packages
Requires: cffi, fenics-ffcx, fenics-ufl, mpi4py, numpy, petsc4py
Required-by: 

and

! pip show petsc4py

returned:

Name: petsc4py
Version: 3.17.5
Summary: PETSc for Python
Home-page: https://gitlab.com/petsc/petsc
Author: Lisandro Dalcin
Author-email: dalcinl@gmail.com
License: BSD
Location: /usr/local/lib/python3.10/dist-packages
Requires: numpy
Required-by: fenics-dolfinx, slepc4py

Call source dolfinx-real-mode in your terminal, as explained in GitHub - FEniCS/dolfinx: Next generation FEniCS problem solving environment

I restarting the kernel, run the command in the shell, rerun the notebook and everything is still the same. Did I miss something?

I mean:

uh.dtype

returns
dtype('complex128')

Mabye I should add that my assumption is , that the problem actually arises in:

import ufl
import dolfinx
import numpy as np
from petsc4py.PETSc import ScalarType


material_tags = np.unique(cell_markers.values)
T = dolfinx.fem.TensorFunctionSpace(mesh, ("DG", 0), shape=(6, 6))
stiffness = dolfinx.fem.Function(T, dtype=ScalarType)

def tensor(x, tens):
    tens_reshaped = tens.reshape((6 * 6, 1))
    return np.broadcast_to(tens_reshaped, (6 * 6, x.shape[1]))

for tag in material_tags:
    domain = cell_markers.find(tag)
    if tag < len(stack):
        material = stack[tag]
        stiffness.interpolate(lambda x: tensor(x, material["stiff_tens"].astype(ScalarType)), domain)

with:

stiffness.dtype

being complex128 already

replacing ScalarTypewith np.float32 in the code segment above changed this.
But later I get an error:

from dolfinx.fem.petsc import LinearProblem


problem = LinearProblem(a, L, bcs=[bc], petsc_options={"ksp_type": "preonly", "pc_type": "lu"})
uh = problem.solve()

throws:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[10], line 4
      1 from dolfinx.fem.petsc import LinearProblem
----> 4 problem = LinearProblem(a, L, bcs=[bc], petsc_options={"ksp_type": "preonly", "pc_type": "lu"})
      5 uh = problem.solve()

File /usr/local/dolfinx-complex/lib/python3.10/dist-packages/dolfinx/fem/petsc.py:566, in LinearProblem.__init__(self, a, L, bcs, u, petsc_options, form_compiler_options, jit_options)
    538 def __init__(self, a: ufl.Form, L: ufl.Form, bcs: typing.List[DirichletBCMetaClass] = [],
    539              u: typing.Optional[_Function] = None, petsc_options={}, form_compiler_options={}, jit_options={}):
    540     """Initialize solver for a linear variational problem.
    541 
    542     Args:
   (...)
    564                                                "pc_factor_mat_solver_type": "mumps"})
    565     """
--> 566     self._a = _create_form(a, form_compiler_options=form_compiler_options, jit_options=jit_options)
    567     self._A = create_matrix(self._a)
    569     self._L = _create_form(L, form_compiler_options=form_compiler_options, jit_options=jit_options)

File /usr/local/dolfinx-complex/lib/python3.10/dist-packages/dolfinx/fem/forms.py:176, in form(form, dtype, form_compiler_options, jit_options)
    173         return list(map(lambda sub_form: _create_form(sub_form), form))
    174     return form
--> 176 return _create_form(form)
...
TypeError: __init__(): incompatible constructor arguments. The following argument types are supported:
    1. dolfinx.cpp.fem.Form_complex128(spaces: List[dolfinx::fem::FunctionSpace], integrals: Dict[dolfinx::fem::IntegralType, Tuple[List[Tuple[int, object]], dolfinx.cpp.mesh.MeshTags_int32]], coefficients: List[dolfinx.cpp.fem.Function_complex128], constants: List[dolfinx.cpp.fem.Constant_complex128], need_permutation_data: bool, mesh: dolfinx.cpp.mesh.Mesh = None)
    2. dolfinx.cpp.fem.Form_complex128(form: int, spaces: List[dolfinx::fem::FunctionSpace], coefficients: List[dolfinx.cpp.fem.Function_complex128], constants: List[dolfinx.cpp.fem.Constant_complex128], subdomains: Dict[dolfinx::fem::IntegralType, dolfinx.cpp.mesh.MeshTags_int32], mesh: dolfinx.cpp.mesh.Mesh)

Invoked with: , [, ], [], [], {: None, : None, : None, : None}, 

In a notebook, you would have to change the python kernel to the one that does not have complex in the name.

1 Like

Ok, sorry. I see my mistake.
But is there even an option for the jupyter notebook?
I mean if I select a kernel I only see dolfinx with complex.
Additionally, I checked the fencisx and docker documentation and did not find any hint how to change this.
I mean there was this section but this does not work for the jupyter-notebook?

Yes, in the top menu of jupyter lab there is an option Kernel, which you then can press Change kernel
image
and change to Python 3 (ipykernel)

image

2 Likes

Thank you.
I did not even think that (ipykernel) would work, because the tutorial said:

 Once connected, select the option Python 3 (DOLFINx complex) in the dropdown.

Thank you so much!