This is a read only copy of the old FEniCS QA forum. Please visit the new QA forum to ask questions

Create generic nonlinear operator in UFL

0 votes

Hi,

I'd like to create a generic UFL operator by inheriting from ufl.MathFunction. It's an approach I've used before and it works.

The problem here is in the format function that I use to generate c++ code for that operator. I'd like to be able to call the "map_function" which is a python object into the code generate by ffc.

How to generate the right call_to_map_function string below? Is it even possible?

def nonlinear_function_evaluate(map_function,n, x):
    return map_function(x,n)

class NonlinearFunction(MathFunction):

    def __new__(cls, map_function, n, argument):
        if isinstance(argument, (ScalarValue, Zero)):
            return FloatValue(nonlinear_function_evaluate(map_function,
                                                      n,
                                                      float(argument)
                                                      )
                          )
        return MathFunction.__new__(cls)


    def evaluate(self, x, mapping, component, index_values, derivatives=()):
        #print x, mapping, component, index_values    
        a = self._argument.evaluate(x, mapping, component, index_values)
        map_function = self._map_function
        n = self._n
        return nonlinear_function_evaluate(map_function, n, a)


    def __init__(self, map_function, n, argument):

        self._map_function = map_function;
        self._n = n

        MathFunction.__init__(self, map_function.name()+'eval_derivatives_'+str(n),
                              argument)

        self._argument = argument


    def _ufl_expr_reconstruct_(self, argument):
        "Return a new object of the same type with new operands."
        return self.__class__(self._map_function, self._n , argument)

    def derivative(self, ):
        """Used in ufl.algorithms.forward_ad"""
        return self.__class__(self._map_function, self._n+1, self._argument)

    def format(self,v):
        map_function = self._map_function.name()

        return "call_to_map_function("+v+")"
asked May 5, 2016 by chaffra FEniCS User (1,830 points)
edited May 5, 2016 by chaffra
...