Hello Kostas.
I was wandering what is the difference between using add_macro() or asm_define_function() for applying functions in a FEM model.
Some time ago I was told that asm_define_function() is the correct way of defining functions from Python and that I should not use macros. Is this a Python requirement or is it also valid in C++? I would like to better understand this point and when choosing one of the other method.
By the way, is there any chance that GetFem can take pointers to external functions?
I was thinking of some very complex function with complex conditional operators, or taking values from external data tables, or neural networks, etc… etc…
Thank you.
Lorenzo
This is a very good question.
There are several differences between “asm_define_function” and “add_macro”, but they all boil down to the fact that “add_macro” is just a convenience feature to save you from writing long expressions. Apart from that, whether you use the “add_macro” or you substitute whatever the macro contains into your expression, the result is the same.
Having said that, there is nothing wrong with “add_macro” making it in general inferior to “asm_define_function”, but the latter has some additional possibilities but also limitations:
- “asm_define_function” is only for scalar functions of 1 or 2 scalar arguments called “t” and “u”
- “asm_define_function” allows you to define the derivatives of the functions yourself, if you do not do so, GetFEM will differentiate the function expression itself. Sometimes you want to define the derivative yourself because you want to apply simplifications that a simple computer algebra system like GetFEM cannot figure out.
- in C++ the corresponding function is called “ga_define_function” and accepts pointers to functions by means of the pointer types pscalar_func_onearg or pscalar_func_twoargs, this is the relevant interface:
typedef scalar_type (*pscalar_func_onearg)(scalar_type);
typedef scalar_type (*pscalar_func_twoargs)(scalar_type, scalar_type);
void ga_define_function(const std::string &name, pscalar_func_onearg f,
const std::string &der1="");
void ga_define_function(const std::string &name, pscalar_func_twoargs f2,
const std::string &der1="",
const std::string &der2="");
der1 and der2 are strings with names of functions (that you defined before) which correspond to the derivatives of the function with respect to the first and second argument.
So you need to go to C++ if you need this more advanced functionality.
Thank you Kostas for your reply.
Ok, so in C++ there’s the chance to use arbitrary external functions, this is very good.
Anyhow, since Python also manages pointers to functions:
- is there the chance to have this more advanced functionality available also in Python?
or,
- is it possible to mix somehow the codes (Python and C++) so that if I have a preexisting model made in Python I could include my complex function in the same model via C++ and after that continue to use Python?
Thank you.
Lorenzo
#1 is of course not too difficult, but not a very high priority. On the other side I am not a big fan of passing function pointers between languages.
#2 the easiest way is to add the functionality to your own built customized version of GetFEM. You can add your function in the “interface/src/gf_asm.cc” file
Look for example at the definition of a linear hardening function
sub_command
("define linear hardening function", 3, 4, 0, 0,
std::string name = in.pop().to_string();
const double sigma_y0 = in.pop().to_scalar();
const double H = in.pop().to_scalar();
bool frobenius(false);
if (in.remaining()) frobenius = (in.pop().to_integer() != 0);
getfem::ga_define_linear_hardening_function(name, sigma_y0, H, frobenius);
);
the actual definition is done inside the ga_define_linear_hardening_function C++ function, and this snippet just creates the Python interface for this function.
Hello Kostas.
I just come across a library named Numba-JIT that is used in the Python interface of some opensource libraries (also FEM ones) for the compilation of Python functions to C++, both at the first function execution or ahead of time (generating precompiled extension modules like my_module.so).
Is it possible to link such a precompiled function to the ga_define_function in C++ and then to the asm_define_function in Python?
Thank you,
Lorenzo