Open RemDelaporteMathurin opened 1 month ago
A workaround for now is to do:
import festim as F
import sympy as sp
import numpy as np
my_model = F.Simulation()
my_model.mesh = F.MeshFromVertices(np.linspace(0, 1))
my_model.materials = F.Material(1, 1, 0)
log_bis = sp.Function("std::log")
my_model.T = F.Temperature(log_bis(F.t))
my_model.settings = F.Settings(1e10, 1e-10)
my_model.dt = F.Stepsize(1)
my_model.initialise()
Actually the code does not work:
import festim as F
import sympy as sp
import numpy as np
my_model = F.Simulation()
my_model.mesh = F.MeshFromVertices(np.linspace(0, 1))
my_model.materials = F.Material(1, 1, 0)
log_bis = sp.Function("std::log")
my_model.T = F.Temperature(log_bis(F.t))
my_model.settings = F.Settings(1e10, 1e-10, final_time=10)
my_model.dt = F.Stepsize(1)
my_model.initialise()
produces
Traceback (most recent call last):
File "/home/remidm/FESTIM-SurfaceKinetics-Validation/tmp_folder_not_working_cases/D_EUROFER/test.py", line 15, in <module>
my_model.initialise()
File "/home/remidm/miniconda3/envs/festim-surface-kinetics-vv-env/lib/python3.11/site-packages/festim/generic_simulation.py", line 297, in initialise
raise AttributeError(
AttributeError: final_time argument must be provided to settings in transient simulations
(festim-surface-kinetics-vv-env) remidm@lap-mathurin-01:~/FESTIM-SurfaceKinetics-Validation/tmp_folder_not_working_cases/D_EUROFER$ python test.py
Traceback (most recent call last):
File "/home/remidm/FESTIM-SurfaceKinetics-Validation/tmp_folder_not_working_cases/D_EUROFER/test.py", line 15, in <module>
my_model.initialise()
File "/home/remidm/miniconda3/envs/festim-surface-kinetics-vv-env/lib/python3.11/site-packages/festim/generic_simulation.py", line 330, in initialise
self.T.create_functions(self.mesh)
File "/home/remidm/miniconda3/envs/festim-surface-kinetics-vv-env/lib/python3.11/site-packages/festim/temperature/temperature.py", line 41, in create_functions
self.expression = f.Expression(sp.printing.ccode(self.value), t=0, degree=2)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/remidm/miniconda3/envs/festim-surface-kinetics-vv-env/lib/python3.11/site-packages/sympy/printing/codeprinter.py", line 752, in ccode
return c_code_printers[standard.lower()](settings).doprint(expr, assign_to)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/remidm/miniconda3/envs/festim-surface-kinetics-vv-env/lib/python3.11/site-packages/sympy/printing/codeprinter.py", line 172, in doprint
lines = self._print(expr).splitlines()
^^^^^^^^^^^^^^^^^
File "/home/remidm/miniconda3/envs/festim-surface-kinetics-vv-env/lib/python3.11/site-packages/sympy/printing/printer.py", line 331, in _print
return printmethod(expr, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/remidm/miniconda3/envs/festim-surface-kinetics-vv-env/lib/python3.11/site-packages/sympy/printing/codeprinter.py", line 461, in _print_Function
return self._print_not_supported(expr)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/remidm/miniconda3/envs/festim-surface-kinetics-vv-env/lib/python3.11/site-packages/sympy/printing/codeprinter.py", line 582, in _print_not_supported
raise PrintMethodNotImplementedError("Unsupported by %s: %s" % (str(type(self)), str(type(expr))) + \
sympy.printing.codeprinter.PrintMethodNotImplementedError: Unsupported by <class 'sympy.printing.c.C99CodePrinter'>: std::log
Set the printer option 'strict' to False in order to generate partially printed code.
The only way I found to circumvent this issue is by monkey patching the sympy C printer:
import festim as F
import sympy as sp
import numpy as np
my_model = F.Simulation()
my_model.mesh = F.MeshFromVertices(np.linspace(0, 1))
my_model.materials = F.Material(1, 1, 0)
log_bis = sp.Function("std::log")
# Monkey patch the C99CodePrinter class
from sympy.printing.c import C99CodePrinter
original_print_function = C99CodePrinter._print_Function
def _custom_print_Function(self, expr):
if expr.func == log_bis:
return f"std::log({self._print(expr.args[0])})"
return original_print_function(self, expr)
C99CodePrinter._print_Function = _custom_print_Function
my_model.T = F.Temperature(log_bis(F.t))
my_model.settings = F.Settings(1e10, 1e-10, final_time=10)
my_model.dt = F.Stepsize(1)
my_model.initialise()
A fix would be to replace this line: https://github.com/festim-dev/FESTIM/blob/47d7dc4831fe51b7bf2fe197e973d6ba5d4f6987/festim/temperature/temperature.py#L41
by
ccode = sp.printing.ccode(self.value).replace("log", "std::log")
self.expression = f.Expression(ccode , t=0, degree=2)
we'd have to propagate this fix in all the codebase where sp.printing.ccode
is used though.
Maybe we could make a festim.ccode
function to simplify things:
def ccode(string):
return sp.printing.ccode(self.value).replace("log", "std::log")
But maybe not really needed.
OR
Monkey patch sp.printing.ccode
to replace do the same thing.
Describe the bug
@KulaginVladimir and I recently noticed that we can't use natural log in expressions (probably temperature, sources, boundary conditions) due to this issue
To Reproduce Run
It produces
A solution is provided in the FEniCS discourse ticket, simply replace the string
"log"
by"std::log"
.