Exemplo n.º 1
0
def generateUnaryLinearizedCode(predefined,
                                testFunctions,
                                trialFunctions,
                                tensorMap,
                                tempVars=True):
    var = Variable('std::tuple< RangeType, JacobianRangeType >', 'phi')
    if tensorMap is None:
        values = []
        for phi in testFunctions:
            value = tensors.fill(phi.ufl_shape, None)
            value = tensors.apply(lambda v: makeExpression(0), phi.ufl_shape,
                                  value)
            values += [
                tensors.reformat(lambda row: InitializerList(*row),
                                 phi.ufl_shape, value)
            ]
        return [return_(lambda_(args=['const DomainValueType &phi'],\
                  code=return_(construct('RangeValueType',*values,
                    brace=True)) ))]

    preamble, values = generateLinearizedCode(predefined,
                                              testFunctions,
                                              {var: trialFunctions},
                                              tensorMap,
                                              tempVars=tempVars)
    capture = extractVariablesFromExpressions(values[var]) - {var}
    return preamble + [
        return_(
            lambda_(capture=capture,
                    args=['const DomainValueType &phi'],
                    code=return_(
                        construct('RangeValueType', *values[var],
                                  brace=True))))
    ]
Exemplo n.º 2
0
def generateMethod(struct,expr, cppType, name,
        returnResult=True,
        defaultReturn='0',
        targs=None, args=None, static=False, const=False, volatile=False,
        inline=False,
        evalSwitch=True,
        predefined=None):
    if predefined is None:
        predefined = {}
    if not returnResult:
        args = args + [cppType + ' &result']
        returnType = 'void'
    else:
        returnType = cppType

    if isinstance(expr,dict):
        if evalSwitch:
            bndId = Variable('const int', 'bndId')
            code = SwitchStatement(bndId, default=return_(False))
            for id, e in expr.items():
                code.append(id,
                        [generateMethodBody('RangeType', e, False, defaultReturn,
                            predefined), return_(True)])
        else:
            code = UnformattedBlock()
        code = [code]
    else:
        code = generateMethodBody(cppType, expr, returnResult, defaultReturn, predefined)

    meth = clsMethod(returnType, name,
            code=code,
            args=args,
            targs=targs, static=static, const=const, volatile=volatile, inline=inline)
    struct.append(meth)
Exemplo n.º 3
0
def generateUnaryCode(predefined, testFunctions, tensorMap, tempVars=True):
    preamble, values = generateCode(predefined,
                                    testFunctions,
                                    tensorMap,
                                    tempVars=tempVars)
    return preamble + [
        return_(construct('RangeValueType', *values, brace=True))
    ]
Exemplo n.º 4
0
def generateMethodBody(cppType, expr, returnResult, default, predefined):
    if expr is not None and not expr == [None]:
        try:
            dimR = expr.ufl_shape[0]
        except:
            if isinstance(expr,list) or isinstance(expr,tuple):
                expr = as_vector(expr)
            else:
                expr = as_vector([expr])
            dimR = expr.ufl_shape[0]

        _, coeff = extract_arguments_and_coefficients(expr)
        coeff = {c : c.toVectorCoefficient()[0] for c in coeff if len(c.ufl_shape) == 0 and not c.is_cellwise_constant()}
        expr = replace(expr, coeff)

        t = ExprTensor(expr.ufl_shape) # , exprTensorApply(lambda u: u, expr.ufl_shape, expr))
        expression = [expr[i] for i in t.keys()]
        u = extract_arguments_and_coefficients(expr)[0]
        if u != []:
            u = u[0]
            du = Grad(u)
            d2u = Grad(du)
            arg_u = Variable("const RangeType &", "u")
            arg_du = Variable("const JacobianRangeType &", "du")
            arg_d2u = Variable("const HessianRangeType &", "d2u")
            predefined.update( {u: arg_u, du: arg_du, d2u: arg_d2u} )
        code, results = generateCode(predefined, expression, tempVars=False)
        result = Variable(cppType, 'result')
        if cppType == 'double':
            code = code + [assign(result, results[0])]
        else:
            code = code + [assign(result[i], r) for i, r in zip(t.keys(), results)]
        if returnResult:
            code = [Declaration(result)] + code + [return_(result)]
    else:
        result = Variable(cppType, 'result')
        code = [assign(result, construct(cppType,default) )]
        if returnResult:
            code = [Declaration(result)] + code + [return_(result)]
    return code
Exemplo n.º 5
0
def generateBinaryLinearizedCode(predefined,
                                 testFunctions,
                                 trialFunctions,
                                 tensorMap,
                                 tempVars=True):
    restrictedTestFunctions = [phi('+') for phi in testFunctions
                               ] + [phi('-') for phi in testFunctions]

    trialFunctionsIn = [psi('+') for psi in trialFunctions]
    trialFunctionsOut = [psi('-') for psi in trialFunctions]

    if tensorMap is None:
        value = construct('RangeValueType',
                          *[0 for i in range(len(testFunctions))],
                          brace=True)
        tensorIn = lambda_(args=['const DomainValueType &phiIn'],
                           code=return_(make_pair(value, value)))
        tensorOut = lambda_(args=['const DomainValueType &phiOut'],
                            code=return_(make_pair(value, value)))
        return [return_(make_pair(tensorIn, tensorOut))]

    varIn = Variable('std::tuple< RangeType, JacobianRangeType >', 'phiIn')
    varOut = Variable('std::tuple< RangeType, JacobianRangeType >', 'phiOut')
    preamble, values = generateLinearizedCode(predefined,
                                              restrictedTestFunctions, {
                                                  varIn: trialFunctionsIn,
                                                  varOut: trialFunctionsOut
                                              },
                                              tensorMap,
                                              tempVars=tempVars)

    captureIn = extractVariablesFromExpressions(values[varIn]) - {varIn}
    captureOut = extractVariablesFromExpressions(values[varOut]) - {varOut}

    tensorIn = lambda_(capture=captureIn,
                       args=['const DomainValueType &phiIn'],
                       code=return_(
                           make_pair(
                               construct('RangeValueType',
                                         *values[varIn][:len(testFunctions)],
                                         brace=True),
                               construct('RangeValueType',
                                         *values[varIn][len(testFunctions):],
                                         brace=True))))
    tensorOut = lambda_(capture=captureOut,
                        args=['const DomainValueType &phiOut'],
                        code=return_(
                            make_pair(
                                construct('RangeValueType',
                                          *values[varOut][:len(testFunctions)],
                                          brace=True),
                                construct('RangeValueType',
                                          *values[varOut][len(testFunctions):],
                                          brace=True))))

    return preamble + [return_(make_pair(tensorIn, tensorOut))]
Exemplo n.º 6
0
    def __init__(self, dimDomain, dimRange, u, signature):
        assert isInteger(dimRange)
        self.dimDomain = dimDomain
        self.dimRange = dimRange
        self.trialFunction = u
        self.init = []
        self.vars = None
        self.signature = signature + ConservationLawModel.version
        self.field = "double"

        self._constants = []
        self._constantNames = {}
        self._parameterNames = {}
        self._coefficients = []

        self.arg_r = Variable("RRangeType &", "result")
        self.arg_dr = Variable("RJacobianRangeType &", "result")

        self.arg_x = Variable("const Point &", "x")
        self.arg_u = Variable("const DRangeType &", "u")
        self.arg_du = Variable("const DJacobianRangeType &", "du")
        self.arg_d2u = Variable("const DHessianRangeType &", "d2u")
        self.arg_ubar = Variable("const DRangeType &", "ubar")
        self.arg_dubar = Variable("const DJacobianRangeType &", "dubar")
        self.arg_d2ubar = Variable("const DHessianRangeType &", "d2ubar")

        self.arg_i = Variable("const IntersectionType &", "intersection")
        self.arg_bndId = Variable("int", "bndId")

        self.source = [assign(self.arg_r, construct("RRangeType", 0))]
        self.linSource = [assign(self.arg_r, construct("RRangeType", 0))]
        self.flux = [assign(self.arg_dr, construct("RJacobianRangeType", 0))]
        self.linFlux = [
            assign(self.arg_dr, construct("RJacobianRangeType", 0))
        ]
        self.fluxDivergence = [assign(self.arg_r, construct("RRangeType", 0))]
        self.alpha = [assign(self.arg_r, construct("RRangeType", 0))]
        self.linAlpha = [assign(self.arg_r, construct("RRangeType", 0))]

        self.hasDirichletBoundary = False
        self.hasNeumanBoundary = False
        self.isDirichletIntersection = [return_(False)]
        self.dirichlet = [assign(self.arg_r, construct("RRangeType", 0))]
        self.symmetric = False

        self.baseName = "conservationlaw"
        self.modelWrapper = "ConservationLawModelWrapper< Model >"
Exemplo n.º 7
0
def generateBinaryCode(predefined, testFunctions, tensorMap, tempVars=True):
    restrictedTestFunctions = [phi('+') for phi in testFunctions
                               ] + [phi('-') for phi in testFunctions]
    preamble, values = generateCode(predefined,
                                    restrictedTestFunctions,
                                    tensorMap,
                                    tempVars=tempVars)
    return preamble + [
        return_(
            make_pair(
                construct('RangeValueType',
                          *values[:len(testFunctions)],
                          brace=True),
                construct('RangeValueType',
                          *values[len(testFunctions):],
                          brace=True)))
    ]
Exemplo n.º 8
0
 def coefficient(self, idx, x):
     coefficient = []
     for t, n in (('RangeType', 'evaluate'),
                  ('JacobianRangeType', 'jacobian'), ('HessianRangeType',
                                                      'hessian')):
         result = Variable(
             'typename std::tuple_element_t< ' + str(idx) +
             ', CoefficientFunctionSpaceTupleType >::' + t, 'result')
         code = [
             Declaration(result),
             UnformattedExpression('void',
                                   'std::get< ' + str(idx) +
                                   ' >( coefficients_ ).' + n + '( x, ' +
                                   result.name + ' )',
                                   uses=[result]),
             return_(result)
         ]
         coefficient += [
             lambda_(capture=[this], args=['auto x'], code=code)(x)
         ]
     return coefficient
Exemplo n.º 9
0
    def code(self, name=None, targs=None):
        # self.name = "Integrands"
        # self.targs = ['class GridPart']
        # self.gridPartType = TypeAlias("GridPartType", "GridPart")
        # self.ctor_args = []
        # self.ctor_init = []
        # self.skeleton (None is no intersecton terms are needed)
        # self.init (code to be added to init(Entity) method
        # self.vars (further class variables)
        # self.methods(code)

        if name is not None:
            self.name = name
        if targs is not None:
            self.targs = targs
        code = Struct(self.className,
                      targs=(self.targs + ['class ' + n for n in self.coefficientTypes]),
                      bases=self.bases)

        code.append(self.gridPartType)
        code.append(TypeAlias("GridView", "typename GridPartType::GridViewType"))
        if self.bindable:
            code.append(TypeAlias("FunctionSpaceType", "Dune::Fem::GridFunctionSpace<GridPartType,Dune::Dim<"+str(self.dimRange)+">>"))

        code.append(TypeAlias("EntityType", "typename GridPartType::template Codim< 0 >::EntityType"))
        code.append(TypeAlias("IntersectionType", "typename GridPartType::IntersectionType"))

        code.append(TypeAlias("GlobalCoordinateType", "typename EntityType::Geometry::GlobalCoordinate"))

        code.append(TypeAlias("Side","Dune::Fem::IntersectionSide"))

        for type, alias in zip(self._constants, self.constantTypes):
            code.append(TypeAlias(alias, type))
        constants = ["std::shared_ptr< " + c + " >" for c in self.constantTypes]
        if constants:
            code.append(TypeAlias("ConstantTupleType", "std::tuple< " + ", ".join(constants) + " >"))
            code.append(TypeAlias("ConstantsRangeType", "typename std::tuple_element_t< i, ConstantTupleType >::element_type", targs=["std::size_t i"]))
        else:
            code.append(TypeAlias("ConstantTupleType", "std::tuple<>"))

        if self._coefficients:
            coefficientSpaces = [('Dune::Fem::GridFunctionSpace< GridPartType, ' + c + ' >') for c in self._coefficients]
            code.append(TypeAlias("CoefficientFunctionSpaceTupleType", "std::tuple< " +", ".join(coefficientSpaces) + " >"))
            code.append(TypeAlias('CoefficientTupleType', 'std::tuple< ' + ', '.join(self.coefficientTypes) + ' >'))

            code.append(TypeAlias("CoefficientFunctionSpaceType", "std::tuple_element_t< i, CoefficientFunctionSpaceTupleType >", targs=["std::size_t i"]))
            for s in ["RangeType", "JacobianRangeType"]:
                code.append(TypeAlias("Coefficient" + s, "typename CoefficientFunctionSpaceType< i >::" + s, targs=["std::size_t i"]))
            code.append(Declaration(Variable("bool", "gridPartValid"),
                initializer=UnformattedExpression("bool"," && ".join(["Dune::Fem::checkGridPartValid<GridPartType,"+
                             "Dune::Fem::ConstLocalFunction<"+c+">>()"
                        for c in self.coefficientTypes])),
                        static=True, constexpr=True))
        else:
            code.append(TypeAlias("CoefficientTupleType", "std::tuple<>"))
            code.append(Declaration(Variable("bool", "gridPartValid"),
                        initializer="true",
                        static=True, constexpr=True))

        code.append(TypeAlias('CoefficientType', 'std::tuple_element_t< i, CoefficientTupleType >', targs=['std::size_t i']))
        code.append(TypeAlias('ConstantType', 'typename std::tuple_element_t< i, ConstantTupleType >::element_type', targs=['std::size_t i']))

        # if self.skeleton is not None:
        #     code.append(EnumClass('Side', ['in = 0u', 'out = 1u'], 'std::size_t'))
        #     inside = '[ static_cast< std::size_t >( Side::in ) ]'
        # else:
        #     inside = ''

        if not self.bindable:
            if self.skeleton is None:
                entity_ = Variable('EntityType', 'entity_')
                insideEntity = entity_
            else:
                entity_ = Variable('std::array< EntityType, 2 >', 'entity_')
                insideEntity = entity_[UnformattedExpression('std::size_t', 'static_cast< std::size_t >( Side::in )')]
                outsideEntity = entity_[UnformattedExpression('std::size_t', 'static_cast< std::size_t >( Side::out )')]
            intersection_ = Variable('IntersectionType', 'intersection_')
        else:
            code.append(Using(self.bindableBase+'::entity'))

        constants_ = Variable("ConstantTupleType", "constants_")
        coefficientsTupleType = 'std::tuple< ' + ', '.join('Dune::Fem::ConstLocalFunction< ' + n + ' >' for n in self.coefficientTypes) + ' >'
        if self.skeleton is None:
            coefficients_ = Variable(coefficientsTupleType, 'coefficients_')
        else:
            coefficients_ = Variable('std::array< ' + coefficientsTupleType + ', 2 >', 'coefficients_')

        # generate code for constructor
        arg_param = Variable('const Dune::Fem::ParameterReader &', 'parameter')
        if self.bindable:
            args = [
                    Variable('const GridPartType &','gridPart'),
                    Variable('const std::string &','name'),
                    Variable('int','order')
                   ]
        else:
            args = []
        args += self.ctor_args + [Variable('const ' + t + ' &', n) for t, n in zip(self.coefficientTypes, self.coefficientNames)]
        if self.bindable:
            init = [self.bindableBase+'(gridPart,name,order)']
        else:
            init = []
        if self._coefficients:
            coeffInit = ['Dune::Fem::ConstLocalFunction< ' + n + ' >( ' + p + ' )' for n, p in zip(self.coefficientTypes, self.coefficientNames)]
            if self.skeleton is None:
                init += ["coefficients_( " + ", ".join(coeffInit) + " )"]
            else:
                init += ['coefficients_{{ ' + coefficientsTupleType + '( ' + ', '.join(coeffInit) + ' ), ' + coefficientsTupleType + '( ' + ', '.join(coeffInit) + ' ) }}']
        init = self.ctor_init + init
        args.append(Declaration(arg_param, initializer=UnformattedExpression('const ParameterReader &', 'Dune::Fem::Parameter::container()')))
        constructor = Constructor(args=args, init=init)
        for idx, (cppType, value) in enumerate(zip(self.constantTypes, self.constantValues)):
            constructor.append(assign(get(idx)(constants_),
                make_shared(cppType)(cppType+"(0)")))
        for idx, (name, cppType) in enumerate(zip(self._parameterNames, self.constantTypes)):
            if name is not None:
                constructor.append(assign(dereference(get(idx)(constants_)), UnformattedExpression('auto', arg_param.name + '.getValue< ' + cppType + ' >( "' + name + '" )', uses=[arg_param])))
        code.append(constructor)

        entity = Variable('const EntityType &', 'entity')
        intersection = Variable('const IntersectionType &', 'intersection')
        if self.bindable:
            initEntity = Method('void', 'bind', args=[entity])
            initEntity.append(self.bindableBase+'::bind(entity);')
            uninitEntity = Method('void', 'unbind')
            uninitEntity.append(self.bindableBase+'::unbind();')
            initIntersection = Method('void', 'bind', args=[intersection, Variable('Side', 'side')])
            initIntersection.append(self.bindableBase+'::bind(intersection,side);')
            code.append(initIntersection)
        else:
            initEntity = Method('bool', 'init', args=[entity])
            initEntity.append(assign(insideEntity, entity))
            uninitEntity = Method('void', 'unbind')
        if self.skeleton is None:
            for i, c in enumerate(self._coefficients):
                initEntity.append(UnformattedExpression('void', 'std::get< ' + str(i) + ' >( ' + coefficients_.name + ' ).bind( entity )', uses=[entity, coefficients_]))
                uninitEntity.append(UnformattedExpression('void', 'std::get< ' + str(i) + ' >( ' + coefficients_.name + ').unbind( )', uses=[coefficients_]))
        else:
            for i, c in enumerate(self._coefficients):
                initEntity.append(UnformattedExpression('void', 'std::get< ' + str(i) + ' >( ' + coefficients_.name + '[ static_cast< std::size_t >( Side::in ) ] ).bind( entity )', uses=[entity, coefficients_]))
                initEntity.append(UnformattedExpression('void', 'std::get< ' + str(i) + ' >( ' + coefficients_.name + '[ static_cast< std::size_t >( Side::out ) ] ).bind( entity )', uses=[entity, coefficients_]))
                uninitEntity.append(UnformattedExpression('void', 'std::get< ' + str(i) + ' >( ' + coefficients_.name + '[ static_cast< std::size_t >( Side::in ) ] ).unbind( )', uses=[coefficients_]))
                uninitEntity.append(UnformattedExpression('void', 'std::get< ' + str(i) + ' >( ' + coefficients_.name + '[ static_cast< std::size_t >( Side::out ) ] ).unbind( )', uses=[coefficients_]))
        initEntity.append(self.init)
        if not self.bindable:
            initEntity.append(return_(True))
        code.append(initEntity)
        code.append(uninitEntity)

        if not self.bindable:
            initIntersection = Method('bool', 'init', args=[intersection])
            initIntersection.append(assign(intersection_, intersection))
            if self.skeleton is None:
                initIntersection.append(return_('(intersection.boundary() && init( intersection.inside() ))'))
            else:
                initIntersection.append(assign(insideEntity, UnformattedExpression('EntityType', 'intersection.inside()')))
                for i, c in enumerate(self._coefficients):
                    # initIntersection.append(UnformattedExpression('void', 'std::get< ' + str(i) + ' >( ' + coefficients_.name + '[ static_cast< std::size_t >( Side::in ) ] ).bind( entity_[ static_cast< std::size_t >( Side::in ) ] )', uses=[coefficients_]))
                    initIntersection.append(UnformattedExpression('void', 'std::get< ' + str(i) + ' >( ' + coefficients_.name + '[ static_cast< std::size_t >( Side::in ) ] ).bind( intersection_, Side::in  )', uses=[coefficients_]))
                initIntersection.append('if( intersection.neighbor() )')
                initIntersection.append('{')
                initIntersection.append('  entity_[ static_cast< std::size_t >( Side::out ) ] = intersection.outside();')
                for i, c in enumerate(self._coefficients):
                    # initIntersection.append(UnformattedExpression('void', '  std::get< ' + str(i) + ' >( ' + coefficients_.name + '[ static_cast< std::size_t >( Side::out ) ] ).bind( entity_[ static_cast< std::size_t >( Side::out ) ] )', uses=[coefficients_]))
                    initIntersection.append(UnformattedExpression('void', '  std::get< ' + str(i) + ' >( ' + coefficients_.name + '[ static_cast< std::size_t >( Side::out ) ] ).bind( intersection_, Side::out )', uses=[coefficients_]))
                initIntersection.append('}')
                initIntersection.append(return_(True))
            code.append(initIntersection)

        ################################
        self.methods(code)
        ################################

        code.append(Method('const ConstantType< i > &', 'constant', targs=['std::size_t i'], code=return_(dereference(get('i')(constants_))), const=True))
        code.append(Method('ConstantType< i > &', 'constant', targs=['std::size_t i'], code=return_(dereference(get('i')(constants_)))))

        for i, (t, n) in enumerate(zip(self.constantTypes, self.constantNames)):
            code.append(Method('const ' + t + ' &', n, code=return_(dereference(get(i)(constants_))), const=True))
            code.append(Method(t + ' &', n, code=return_(dereference(get(i)(constants_)))))

        if not self.bindable:
            code.append(Method('const EntityType &', 'entity', const=True, code=return_(insideEntity)))

        code.append(AccessModifier('private'))

        if self._coefficients:
            for cppType, name in self._derivatives:
                var = Variable('typename CoefficientFunctionSpaceType< i >::' + cppType, 'result')
                if self.skeleton is None:
                    method = Method(var.cppType, name + 'Coefficient', targs=['std::size_t i', 'class Point'], args=['const Point &x'], const=True)
                    method.append(Declaration(var))
                    method.append(UnformattedExpression('void', 'std::get< i >( coefficients_ ).' + name + '( x, ' + var.name + ' );'))
                    method.append(return_(var))
                    code.append(method)
                else:
                    method = Method(var.cppType, name + 'Coefficient', targs=['std::size_t i', 'Side side', 'class Point'], args=['const Point &x'], const=True)
                    method.append(Declaration(var))
                    method.append(UnformattedExpression('void', 'std::get< i >( coefficients_[ static_cast< std::size_t >( side ) ] ).' + name + '( x, ' + var.name + ' )'))
                    method.append(return_(var))
                    code.append(method)

                    method = Method(var.cppType, name + 'Coefficient', targs=['std::size_t i', 'class Point'], args=['const Point &x'], const=True)
                    method.append(return_(UnformattedExpression(var.cppType, name + 'Coefficient< i, Side::in >( x )')))
                    code.append(method)

        if not self.bindable:
            code.append(Declaration(entity_), Declaration(intersection_))
        code.append(Declaration(constants_), Declaration(coefficients_))

        if self.vars is not None:
            code += self.vars

        return code
Exemplo n.º 10
0
    def code(self, name=None, targs=None, ellipticBndConditions=True):
        if targs is None:
            targs = []
        if name is None:
            name = 'Model'

        constants_ = Variable(
            'std::tuple< ' + ', '.join('std::shared_ptr< ' + c + ' >'
                                       for c in self._constants) + ' >',
            'constants_')
        # coefficients_ = Variable('std::tuple< ' + ', '.join(c['name'] if c['name'] is not None else 'Coefficient' + str(i) for i, c in enumerate(self._coefficients)) + ' >', 'coefficients_')
        coefficients_ = Variable('std::tuple< ' + ', '.join(\
                'Dune::Fem::ConstLocalFunction<' + self.cppTypeIdentifier(c['name'],"coefficient",i) + '> ' for i, c in enumerate(self._coefficients)) + ' >', 'coefficients_')
        entity_ = Variable('const EntityType *', 'entity_')

        # code = Struct(name, targs=(['class GridPart'] + ['class ' + c['name'] if c['name'] is not None else 'class Coefficient' + str(i) for i, c in enumerate(self._coefficients)] + targs))
        code = Struct(
            name,
            targs=(['class GridPart'] + [
                'class ' + self.cppTypeIdentifier(c['name'], "coefficient", i)
                for i, c in enumerate(self._coefficients)
            ] + targs))

        code.append(TypeAlias("GridPartType", "GridPart"))
        code.append(
            TypeAlias("EntityType",
                      "typename GridPart::template Codim< 0 >::EntityType"))
        code.append(
            TypeAlias("IntersectionType",
                      "typename GridPart::IntersectionType"))

        code.append(
            declareFunctionSpace("typename GridPartType::ctype",
                                 SourceWriter.cpp_fields(self.field),
                                 UnformattedExpression(
                                     "int", "GridPartType::dimensionworld"),
                                 self.dimDomain,
                                 name="DFunctionSpaceType",
                                 prefix="D",
                                 dimDomainName="dimDomain",
                                 dimRangeName="dimD"))
        code.append(
            declareFunctionSpace("typename GridPartType::ctype",
                                 SourceWriter.cpp_fields(self.field),
                                 UnformattedExpression(
                                     "int", "GridPartType::dimensionworld"),
                                 self.dimRange,
                                 name="RFunctionSpaceType",
                                 prefix="R",
                                 dimDomainName=None,
                                 dimRangeName="dimR"))
        code.append(
            Declaration(Variable("const int", "dimLocal"),
                        initializer=UnformattedExpression(
                            "int", "GridPartType::dimension"),
                        static=True))

        if self.hasConstants:
            code.append(
                TypeAlias("ConstantType",
                          "typename std::tuple_element_t< i, " +
                          constants_.cppType + " >::element_type",
                          targs=["std::size_t i"]))
            code.append(
                Declaration(Variable("const std::size_t", "numConstants"),
                            initializer=len(self._constants),
                            static=True))

        if self.hasCoefficients:
            code.append(
                TypeAlias('CoefficientType',
                          'std::tuple_element_t< i, ' + coefficients_.cppType +
                          ' >',
                          targs=['std::size_t i']))
            # coefficientSpaces = ["Dune::Fem::FunctionSpace< DomainFieldType, " + SourceWriter.cpp_fields(c['field']) + ", dimDomain, " + str(c['dimRange']) + " >" for c in self._coefficients]
            coefficientSpaces = [
                "typename CoefficientType<" + str(i) + ">::FunctionSpaceType"
                for i, c in enumerate(self._coefficients)
            ]
            code.append(
                TypeAlias("CoefficientFunctionSpaceTupleType", "std::tuple< " +
                          ", ".join(coefficientSpaces) + " >"))

        arg_param = Variable("const Dune::Fem::ParameterReader &", "parameter")
        args = [
            Declaration(arg_param,
                        initializer=UnformattedExpression(
                            'const ParameterReader &',
                            'Dune::Fem::Parameter::container()'))
        ]
        init = None
        if self.hasCoefficients:
            # args = [Variable("const " + c['name'] if c['name'] is not None else "const Coefficient" + str(i) + " &", "coefficient" + str(i)) for i, c in enumerate(self._coefficients)] + args
            args = [
                Variable(
                    "const " +
                    self.cppTypeIdentifier(c['name'], "coefficient", i) + " &",
                    "coefficient" + str(i))
                for i, c in enumerate(self._coefficients)
            ] + args
            init = ["coefficients_(" + ",".\
                  join("CoefficientType<"+str(i)+">"\
                        +"(coefficient" + str(i)+")" for i, c in enumerate(self._coefficients)) + " )"]
        constructor = Constructor(args=args, init=init)
        constructor.append([
            assign(get(str(i))(constants_),
                   make_shared(c)()) for i, c in enumerate(self._constants)
        ])
        for name, idx in self._parameterNames.items():
            constructor.append(
                assign(
                    dereference(get(idx)(constants_)),
                    UnformattedExpression("auto",
                                          arg_param.name + '.getValue< ' +
                                          self._constants[idx] + ' >( "' +
                                          name + '" )',
                                          uses=[arg_param])))
        code.append(constructor)

        init = ['entity_ = &entity;']
        init += [
            'std::get< ' + str(i) + ' >( ' + coefficients_.name +
            ').bind( entity );' for i, c in enumerate(self._coefficients)
        ]
        init = [UnformattedBlock(init)] + self.init + [return_(True)]
        code.append(
            Method('bool',
                   'init',
                   args=['const EntityType &entity'],
                   code=init,
                   const=True))
        uninit = ['entity_ = nullptr;']
        uninit += [
            'std::get< ' + str(i) + ' >( ' + coefficients_.name +
            ').unbind( );' for i, c in enumerate(self._coefficients)
        ]
        uninit = [UnformattedBlock(uninit)]
        code.append(Method('void', 'unbind', code=uninit, const=True))

        code.append(
            Method('const EntityType &',
                   'entity',
                   code=return_(dereference(entity_)),
                   const=True))
        code.append(
            Method('std::string',
                   'name',
                   const=True,
                   code=return_(
                       UnformattedExpression('const char *',
                                             '"' + name + '"'))))

        code.append(
            TypeAlias(
                "BoundaryIdProviderType",
                "Dune::Fem::BoundaryIdProvider< typename GridPartType::GridType >"
            ))
        code.append(
            Declaration(Variable("const bool", "symmetric"),
                        initializer=self.symmetric,
                        static=True))

        code.append(
            Method('void',
                   'source',
                   targs=['class Point'],
                   args=[self.arg_x, self.arg_u, self.arg_du, self.arg_r],
                   code=self.source,
                   const=True))
        code.append(
            Method('void',
                   'linSource',
                   targs=['class Point'],
                   args=[
                       self.arg_ubar, self.arg_dubar, self.arg_x, self.arg_u,
                       self.arg_du, self.arg_r
                   ],
                   code=self.linSource,
                   const=True))

        code.append(
            Method('void',
                   'flux',
                   targs=['class Point'],
                   args=[self.arg_x, self.arg_u, self.arg_du, self.arg_dr],
                   code=self.flux,
                   const=True))
        code.append(
            Method('void',
                   'linFlux',
                   targs=['class Point'],
                   args=[
                       self.arg_ubar, self.arg_dubar, self.arg_x, self.arg_u,
                       self.arg_du, self.arg_dr
                   ],
                   code=self.linFlux,
                   const=True))
        code.append(
            Method('void',
                   'fluxDivergence',
                   targs=['class Point'],
                   args=[
                       self.arg_x, self.arg_u, self.arg_du, self.arg_d2u,
                       self.arg_r
                   ],
                   code=self.fluxDivergence,
                   const=True))

        # deprecated methods
        code.append(
            Method('[[deprecated]] void',
                   'diffusiveFlux',
                   targs=['class Point'],
                   args=[self.arg_x, self.arg_u, self.arg_du, self.arg_dr],
                   code='flux(x, u, du, result );',
                   const=True))
        code.append(
            Method('[[deprecated]] void',
                   'linDiffusiveFlux',
                   targs=['class Point'],
                   args=[
                       self.arg_ubar, self.arg_dubar, self.arg_x, self.arg_u,
                       self.arg_du, self.arg_dr
                   ],
                   code='linFlux( ubar, dubar, x, u, du, result );',
                   const=True))

        # if model is femDG model, then skip alpha and Neumann/Dirichlet boundary methods
        if ellipticBndConditions:
            code.append(
                Method('void',
                       'alpha',
                       targs=['class Point'],
                       args=[self.arg_x, self.arg_u, self.arg_r],
                       code=self.alpha,
                       const=True))
            code.append(
                Method(
                    'void',
                    'linAlpha',
                    targs=['class Point'],
                    args=[self.arg_ubar, self.arg_x, self.arg_u, self.arg_r],
                    code=self.linAlpha,
                    const=True))

            code.append(
                Method('bool',
                       'hasNeumanBoundary',
                       const=True,
                       code=return_(self.hasNeumanBoundary)))

            code.append(
                TypeAlias("DirichletComponentType",
                          "std::array<int," + str(self.dimRange) + ">"))
            code.append(
                Method('bool',
                       'hasDirichletBoundary',
                       const=True,
                       code=return_(self.hasDirichletBoundary)))
            code.append(
                Method('bool',
                       'isDirichletIntersection',
                       args=[
                           self.arg_i,
                           'DirichletComponentType &dirichletComponent'
                       ],
                       code=self.isDirichletIntersection,
                       const=True))
            code.append(
                Method('void',
                       'dirichlet',
                       targs=['class Point'],
                       args=[self.arg_bndId, self.arg_x, self.arg_r],
                       code=self.dirichlet,
                       const=True))
        ### end boundary conditions for elliptic operators ####

        if self.hasConstants:
            code.append(
                Method("const ConstantType< i > &",
                       "constant",
                       targs=["std::size_t i"],
                       code=return_(dereference(get("i")(constants_))),
                       const=True))
            code.append(
                Method("ConstantType< i > &",
                       "constant",
                       targs=["std::size_t i"],
                       code=return_(dereference(get("i")(constants_)))))

        if self.hasCoefficients:
            code.append(
                Method("const CoefficientType< i > &",
                       "coefficient",
                       targs=["std::size_t i"],
                       code=return_(get("i")(coefficients_)),
                       const=True))
            code.append(
                Method("CoefficientType< i > &",
                       "coefficient",
                       targs=["std::size_t i"],
                       code=return_(get("i")(coefficients_))))

        for n, i in self._constantNames.items():
            t = self._constants[i]
            code.append(
                Method('const ' + t + ' &',
                       n,
                       code=return_(dereference(get(i)(constants_))),
                       const=True))
            code.append(
                Method(t + ' &',
                       n,
                       code=return_(dereference(get(i)(constants_)))))

        code.append(AccessModifier("private"))
        code.append(Declaration(entity_, nullptr, mutable=True))
        if self.hasConstants:
            code.append(Declaration(constants_, mutable=True))
        if self.hasCoefficients:
            code.append(Declaration(coefficients_, mutable=True))
        return code
Exemplo n.º 11
0
def compileUFL(form, patch, *args, **kwargs):
    if isinstance(form, Equation):
        form = form.lhs - form.rhs
    if not isinstance(form, Form):
        raise Exception("ufl.Form expected.")
    if len(form.arguments()) < 2:
        raise Exception("ConservationLaw model requires form with at least two arguments.")

    phi_, u_ = form.arguments()

    if phi_.ufl_function_space().scalar:
        phi = TestFunction(phi_.ufl_function_space().toVectorSpace())
        form = replace(form,{phi_:phi[0]})
    else:
        phi = phi_
    if u_.ufl_function_space().scalar:
        u = TrialFunction(u_.ufl_function_space().toVectorSpace())
        form = replace(form,{u_:u[0]})
    else:
        u = u_
    _, coeff_ = extract_arguments_and_coefficients(form)
    coeff_ = set(coeff_)

    # added for dirichlet treatment same as conservationlaw model
    dirichletBCs = [arg for arg in args if isinstance(arg, DirichletBC)]
    # remove the dirichletBCs
    arg = [arg for arg in args if not isinstance(arg, DirichletBC)]
    for dBC in dirichletBCs:
        _, coeff__ = extract_arguments_and_coefficients(dBC.ufl_value)
        coeff_ |= set(coeff__)
    if patch is not None:
        for a in patch:
            try:
                _, coeff__ = extract_arguments_and_coefficients(a)
                coeff_ |= set(coeff__)
            except:
                pass # a might be a float/int and not a ufl expression

    coeff = {c : c.toVectorCoefficient()[0] for c in coeff_ if len(c.ufl_shape) == 0 and not c.is_cellwise_constant()}
    form = replace(form,coeff)
    for bc in dirichletBCs:
        bc.ufl_value = replace(bc.ufl_value, coeff)
    if patch is not None:
        patch = [a if not isinstance(a, Expr) else replace(a,coeff) for a in patch]

    phi = form.arguments()[0]
    dimRange = phi.ufl_shape[0]

    u = form.arguments()[1]
    du = Grad(u)
    d2u = Grad(du)
    ubar = Coefficient(u.ufl_function_space())
    dubar = Grad(ubar)
    d2ubar = Grad(dubar)
    dimDomain = u.ufl_shape[0]

    x = SpatialCoordinate(form.ufl_cell())

    try:
        field = u.ufl_function_space().field
    except AttributeError:
        field = "double"

    # if exact solution is passed in subtract a(u,.) from the form
    if "exact" in kwargs:
        b = replace(form, {u: as_vector(kwargs["exact"])} )
        form = form - b

    dform = apply_derivatives(derivative(action(form, ubar), ubar, u))

    source, flux, boundarySource = splitUFLForm(form)
    linSource, linFlux, linBoundarySource = splitUFLForm(dform)
    fluxDivergence, _, _ = splitUFLForm(inner(source.as_ufl() - div(flux.as_ufl()), phi) * dx(0))

    # split linNVSource off linSource
    # linSources = splitUFL2(u, du, d2u, linSource)
    # linNVSource = linSources[2]
    # linSource = linSources[0] + linSources[1]

    if patch is not None:
        model = ConservationLawModel(dimDomain, dimRange, u, modelSignature(form,*patch,*args))
    else:
        model = ConservationLawModel(dimDomain, dimRange, u, modelSignature(form,None,*args))
    model._replaceCoeff = coeff

    model.hasNeumanBoundary = not boundarySource.is_zero()

    #expandform = expand_indices(expand_derivatives(expand_compounds(equation.lhs)))
    #if expandform == adjoint(expandform):
    #    model.symmetric = 'true'
    model.field = field

    dirichletBCs = [arg for arg in args if isinstance(arg, DirichletBC)]
    # deprecated
    # if "dirichlet" in kwargs:
    #     dirichletBCs += [DirichletBC(u.ufl_function_space(), as_vector(value), bndId) for bndId, value in kwargs["dirichlet"].items()]

    uflCoefficients = set(form.coefficients())
    for bc in dirichletBCs:
        _, c = extract_arguments_and_coefficients(bc.ufl_value)
        uflCoefficients |= set(c)
    if patch is not None:
        for a in patch:
            if isinstance(a, Expr):
                _, c = extract_arguments_and_coefficients(a)
                uflCoefficients |= set(c)

    constants = dict()
    coefficients = dict()

    for coefficient in uflCoefficients:
        try:
            name = getattr(coefficient, "name")
        except AttributeError:
            name = str(coefficient)
        if coefficient.is_cellwise_constant():
            try:
                parameter = getattr(coefficient, "parameter")
            except AttributeError:
                parameter = None
            if len(coefficient.ufl_shape) == 0:
                constants[coefficient] = model.addConstant('double', name=name, parameter=parameter)
            elif len(coefficient.ufl_shape) == 1:
                constants[coefficient] = model.addConstant('Dune::FieldVector< double, ' + str(coefficient.ufl_shape[0]) + ' >', name=name, parameter=parameter)
            else:
                Exception('Currently, only scalars and vectors are supported as constants')
        else:
            shape = coefficient.ufl_shape[0]
            try:
                coefficients[coefficient] = model.addCoefficient(
                        shape,
                        coefficient.cppTypeName,
                        name=name,
                        field=coefficient.ufl_function_space().field)
            except AttributeError:
                coefficients[coefficient] = model.addCoefficient(
                        shape,
                        coefficient.cppTypeName,
                        name=name)

    model.coefficients = coefficients
    model.constants = constants

    tempVars = kwargs.get("tempVars", True)

    predefined = {u: model.arg_u, du: model.arg_du, d2u: model.arg_d2u}
    predefined[x] = UnformattedExpression('auto', 'entity().geometry().global( Dune::Fem::coordinate( ' + model.arg_x.name + ' ) )')
    model.predefineCoefficients(predefined,'x')
    model.source = generateCode(predefined, source, tempVars=tempVars)
    model.flux = generateCode(predefined, flux, tempVars=tempVars)
    predefined.update({ubar: model.arg_ubar, dubar: model.arg_dubar, d2ubar: model.arg_d2ubar})
    model.linSource = generateCode(predefined, linSource, tempVars=tempVars)
    model.linFlux = generateCode(predefined, linFlux, tempVars=tempVars)

    # model.linNVSource = generateCode({u: arg, du: darg, d2u: d2arg, ubar: argbar, dubar: dargbar, d2ubar: d2argbar}, linNVSource, model.coefficients, tempVars)

    predefined = {u: model.arg_u}
    predefined[x] = UnformattedExpression('auto', 'entity().geometry().global( Dune::Fem::coordinate( ' + model.arg_x.name + ' ) )')
    model.predefineCoefficients(predefined,'x')
    model.alpha = generateCode(predefined, boundarySource, tempVars=tempVars)
    predefined.update({ubar: model.arg_ubar})
    model.linAlpha = generateCode(predefined, linBoundarySource, tempVars=tempVars)

    predefined = {u: model.arg_u, du: model.arg_du, d2u: model.arg_d2u}
    predefined[x] = UnformattedExpression('auto', 'entity().geometry().global( Dune::Fem::coordinate( ' + model.arg_x.name + ' ) )')
    model.predefineCoefficients(predefined,'x')
    model.fluxDivergence = generateCode(predefined, fluxDivergence, tempVars=tempVars)

    if dirichletBCs:
        model.hasDirichletBoundary = True

        predefined = {}
        predefined[x] = UnformattedExpression('auto', 'entity().geometry().global( Dune::Fem::coordinate( ' + model.arg_x.name + ' ) )')
        model.predefineCoefficients(predefined,'x')

        maxId = 0
        codeDomains = []
        bySubDomain = dict()
        neuman = []
        for bc in dirichletBCs:
            if bc.subDomain in bySubDomain:
                raise Exception('Multiply defined Dirichlet boundary for subdomain ' + str(bc.subDomain))
            if not isinstance(bc.functionSpace, (FunctionSpace, FiniteElementBase)):
                raise Exception('Function space must either be a ufl.FunctionSpace or a ufl.FiniteElement')
            if isinstance(bc.functionSpace, FunctionSpace) and (bc.functionSpace != u.ufl_function_space()):
                raise Exception('Space of trial function and dirichlet boundary function must be the same - note that boundary conditions on subspaces are not available, yet')
            if isinstance(bc.functionSpace, FiniteElementBase) and (bc.functionSpace != u.ufl_element()):
                raise Exception('Cannot handle boundary conditions on subspaces, yet')

            if isinstance(bc.value, list):
                neuman = [i for i, x in enumerate(bc.value) if x == None]
            else:
                neuman = []

            value = ExprTensor(u.ufl_shape)
            for key in value.keys():
                value[key] = Indexed(bc.ufl_value, MultiIndex(tuple(FixedIndex(k) for k in key)))
            if isinstance(bc.subDomain,int):
                bySubDomain[bc.subDomain] = value,neuman
                maxId = max(maxId, bc.subDomain)
            else:
                domain = ExprTensor(())
                for key in domain.keys():
                    domain[key] = Indexed(bc.subDomain, MultiIndex(tuple(FixedIndex(k) for k in key)))
                codeDomains.append( (value,neuman,domain) )
        defaultCode = []
        defaultCode.append(Declaration(Variable('int', 'domainId')))
        defaultCode.append(Declaration(Variable('auto', 'tmp0'),
            initializer=UnformattedExpression('auto','intersection.geometry().center()')))
        for i,v in enumerate(codeDomains):
            block = Block()
            defaultCode.append(
                    generateDirichletDomainCode(predefined, v[2], tempVars=tempVars))
            defaultCode.append('if (domainId)')
            block = UnformattedBlock()
            block.append('std::fill( dirichletComponent.begin(), dirichletComponent.end(), ' + str(maxId+i+1) + ' );')
            if len(v[1])>0:
                [block.append('dirichletComponent[' + str(c) + '] = 0;') for c in v[1]]
            block.append('return true;')
            defaultCode.append(block)
        defaultCode.append(return_(False))

        bndId = Variable('const int', 'bndId')
        getBndId = UnformattedExpression('int', 'BoundaryIdProviderType::boundaryId( ' + model.arg_i.name + ' )')
        switch = SwitchStatement(bndId, default=defaultCode)
        for i,v in bySubDomain.items():
            code = []
            if len(v[1])>0:
                [code.append('dirichletComponent[' + str(c) + '] = 0;') for c in v[1]]
            code.append(return_(True))
            switch.append(i, code)
        model.isDirichletIntersection = [Declaration(bndId, initializer=getBndId),
                                         UnformattedBlock('std::fill( dirichletComponent.begin(), dirichletComponent.end(), ' + bndId.name + ' );'),
                                         switch
                                        ]

        switch = SwitchStatement(model.arg_bndId, default=assign(model.arg_r, construct("RRangeType", 0)))
        for i, v in bySubDomain.items():
            switch.append(i, generateDirichletCode(predefined, v[0], tempVars=tempVars))
        for i,v in enumerate(codeDomains):
            switch.append(i+maxId+1, generateDirichletCode(predefined, v[0], tempVars=tempVars))
        model.dirichlet = [switch]

    return model
Exemplo n.º 12
0
def _compileUFL(integrands, form, *args, tempVars=True):
    if isinstance(form, Equation):
        form = form.lhs - form.rhs
    if not isinstance(form, Form):
        raise ValueError("ufl.Form or ufl.Equation expected.")

    # added for dirichlet treatment same as conservationlaw model
    dirichletBCs = [arg for arg in args if isinstance(arg, DirichletBC)]

    uflExpr = [form] + [bc.ufl_value for bc in dirichletBCs]
    if len(form.arguments()) < 2:
        raise ValueError(
            "Integrands model requires form with at least two arguments.")

    x = SpatialCoordinate(form.ufl_cell())
    n = FacetNormal(form.ufl_cell())

    cellVolume = CellVolume(form.ufl_cell())
    maxCellEdgeLength = MaxCellEdgeLength(form.ufl_cell())
    minCellEdgeLength = MinCellEdgeLength(form.ufl_cell())

    facetArea = FacetArea(form.ufl_cell())
    maxFacetEdgeLength = MaxFacetEdgeLength(form.ufl_cell())
    minFacetEdgeLength = MinFacetEdgeLength(form.ufl_cell())

    phi, u = form.arguments()
    ubar = Coefficient(u.ufl_function_space())

    derivatives = gatherDerivatives(form, [phi, u])

    derivatives_phi = derivatives[0]
    derivatives_u = derivatives[1]
    derivatives_ubar = map_expr_dags(Replacer({u: ubar}), derivatives_u)

    try:
        integrands.field = u.ufl_function_space().field
    except AttributeError:
        pass

    integrals = splitForm(form, [phi])

    dform = apply_derivatives(derivative(action(form, ubar), ubar, u))
    linearizedIntegrals = splitForm(dform, [phi, u])

    if not set(
            integrals.keys()) <= {'cell', 'exterior_facet', 'interior_facet'}:
        raise Exception('unknown integral encountered in ' +
                        str(set(integrals.keys())) + '.')

    if 'cell' in integrals.keys():
        arg = Variable(integrands.domainValueTuple, 'u')

        predefined = {
            derivatives_u[i]: arg[i]
            for i in range(len(derivatives_u))
        }
        predefined[x] = integrands.spatialCoordinate('x')
        predefined[cellVolume] = integrands.cellVolume()
        predefined[maxCellEdgeLength] = maxEdgeLength(
            integrands.cellGeometry())
        predefined[minCellEdgeLength] = minEdgeLength(
            integrands.cellGeometry())
        integrands.predefineCoefficients(predefined, False)
        integrands.interior = generateUnaryCode(predefined,
                                                derivatives_phi,
                                                integrals['cell'],
                                                tempVars=tempVars)

        predefined = {
            derivatives_ubar[i]: arg[i]
            for i in range(len(derivatives_u))
        }
        predefined[x] = integrands.spatialCoordinate('x')
        predefined[cellVolume] = integrands.cellVolume()
        predefined[maxCellEdgeLength] = maxEdgeLength(
            integrands.cellGeometry())
        predefined[minCellEdgeLength] = minEdgeLength(
            integrands.cellGeometry())
        integrands.predefineCoefficients(predefined, False)
        integrands.linearizedInterior = generateUnaryLinearizedCode(
            predefined,
            derivatives_phi,
            derivatives_u,
            linearizedIntegrals.get('cell'),
            tempVars=tempVars)

    if 'exterior_facet' in integrals.keys():
        arg = Variable(integrands.domainValueTuple, 'u')

        predefined = {
            derivatives_u[i]: arg[i]
            for i in range(len(derivatives_u))
        }
        predefined[x] = integrands.spatialCoordinate('x')
        predefined[n] = integrands.facetNormal('x')
        predefined[cellVolume] = integrands.cellVolume()
        predefined[maxCellEdgeLength] = maxEdgeLength(
            integrands.cellGeometry())
        predefined[minCellEdgeLength] = minEdgeLength(
            integrands.cellGeometry())
        predefined[facetArea] = integrands.facetArea()
        predefined[maxFacetEdgeLength] = maxEdgeLength(
            integrands.facetGeometry())
        predefined[minFacetEdgeLength] = minEdgeLength(
            integrands.facetGeometry())
        integrands.predefineCoefficients(predefined, False)
        integrands.boundary = generateUnaryCode(predefined,
                                                derivatives_phi,
                                                integrals['exterior_facet'],
                                                tempVars=tempVars)

        predefined = {
            derivatives_ubar[i]: arg[i]
            for i in range(len(derivatives_u))
        }
        predefined[x] = integrands.spatialCoordinate('x')
        predefined[n] = integrands.facetNormal('x')
        predefined[cellVolume] = integrands.cellVolume()
        predefined[maxCellEdgeLength] = maxEdgeLength(
            integrands.cellGeometry())
        predefined[minCellEdgeLength] = minEdgeLength(
            integrands.cellGeometry())
        predefined[facetArea] = integrands.facetArea()
        predefined[maxFacetEdgeLength] = maxEdgeLength(
            integrands.facetGeometry())
        predefined[minFacetEdgeLength] = minEdgeLength(
            integrands.facetGeometry())
        integrands.predefineCoefficients(predefined, False)
        integrands.linearizedBoundary = generateUnaryLinearizedCode(
            predefined,
            derivatives_phi,
            derivatives_u,
            linearizedIntegrals.get('exterior_facet'),
            tempVars=tempVars)

    if 'interior_facet' in integrals.keys():
        argIn = Variable(integrands.domainValueTuple, 'uIn')
        argOut = Variable(integrands.domainValueTuple, 'uOut')

        predefined = {
            derivatives_u[i](s): arg[i]
            for i in range(len(derivatives_u))
            for s, arg in (('+', argIn), ('-', argOut))
        }
        predefined[x] = integrands.spatialCoordinate('xIn')
        predefined[n('+')] = integrands.facetNormal('xIn')
        predefined[cellVolume('+')] = integrands.cellVolume('Side::in')
        predefined[cellVolume('-')] = integrands.cellVolume('Side::out')
        predefined[maxCellEdgeLength('+')] = maxEdgeLength(
            integrands.cellGeometry('Side::in'))
        predefined[maxCellEdgeLength('-')] = maxEdgeLength(
            integrands.cellGeometry('Side::out'))
        predefined[minCellEdgeLength('+')] = minEdgeLength(
            integrands.cellGeometry('Side::in'))
        predefined[minCellEdgeLength('-')] = minEdgeLength(
            integrands.cellGeometry('Side::out'))
        predefined[facetArea] = integrands.facetArea()
        predefined[maxFacetEdgeLength] = maxEdgeLength(
            integrands.facetGeometry())
        predefined[minFacetEdgeLength] = minEdgeLength(
            integrands.facetGeometry())
        integrands.predefineCoefficients(predefined, True)
        integrands.skeleton = generateBinaryCode(predefined,
                                                 derivatives_phi,
                                                 integrals['interior_facet'],
                                                 tempVars=tempVars)

        predefined = {
            derivatives_ubar[i](s): arg[i]
            for i in range(len(derivatives_u))
            for s, arg in (('+', argIn), ('-', argOut))
        }
        predefined[x] = integrands.spatialCoordinate('xIn')
        predefined[n('+')] = integrands.facetNormal('xIn')
        predefined[cellVolume('+')] = integrands.cellVolume('Side::in')
        predefined[cellVolume('-')] = integrands.cellVolume('Side::out')
        predefined[maxCellEdgeLength('+')] = maxEdgeLength(
            integrands.cellGeometry('Side::in'))
        predefined[maxCellEdgeLength('-')] = maxEdgeLength(
            integrands.cellGeometry('Side::out'))
        predefined[minCellEdgeLength('+')] = minEdgeLength(
            integrands.cellGeometry('Side::in'))
        predefined[minCellEdgeLength('-')] = minEdgeLength(
            integrands.cellGeometry('Side::out'))
        predefined[facetArea] = integrands.facetArea()
        predefined[maxFacetEdgeLength] = maxEdgeLength(
            integrands.facetGeometry())
        predefined[minFacetEdgeLength] = minEdgeLength(
            integrands.facetGeometry())
        integrands.predefineCoefficients(predefined, True)
        integrands.linearizedSkeleton = generateBinaryLinearizedCode(
            predefined,
            derivatives_phi,
            derivatives_u,
            linearizedIntegrals.get('interior_facet'),
            tempVars=tempVars)

    if dirichletBCs:
        integrands.hasDirichletBoundary = True

        predefined = {}
        # predefined[x] = UnformattedExpression('auto', 'entity().geometry().global( Dune::Fem::coordinate( ' + integrands.arg_x.name + ' ) )')
        predefined[x] = UnformattedExpression(
            'auto', 'intersection.geometry().center( )')
        integrands.predefineCoefficients(predefined, False)

        maxId = 0
        codeDomains = []
        bySubDomain = dict()
        neuman = []
        wholeDomain = None
        for bc in dirichletBCs:
            if bc.subDomain in bySubDomain:
                raise Exception(
                    'Multiply defined Dirichlet boundary for subdomain ' +
                    str(bc.subDomain))
            if not isinstance(bc.functionSpace,
                              (FunctionSpace, FiniteElementBase)):
                raise Exception(
                    'Function space must either be a ufl.FunctionSpace or a ufl.FiniteElement'
                )
            if isinstance(bc.functionSpace, FunctionSpace) and (
                    bc.functionSpace != u.ufl_function_space()):
                raise Exception(
                    'Space of trial function and dirichlet boundary function must be the same - note that boundary conditions on subspaces are not available, yet'
                )
            if isinstance(bc.functionSpace, FiniteElementBase) and (
                    bc.functionSpace != u.ufl_element()):
                raise Exception(
                    'Cannot handle boundary conditions on subspaces, yet')

            if isinstance(bc.value, list):
                neuman = [i for i, x in enumerate(bc.value) if x == None]
            else:
                neuman = []

            value = ExprTensor(u.ufl_shape)
            for key in value.keys():
                value[key] = Indexed(
                    bc.ufl_value,
                    MultiIndex(tuple(FixedIndex(k) for k in key)))
            if bc.subDomain is None:
                wholeDomain = value, neuman
            elif isinstance(bc.subDomain, int):
                bySubDomain[bc.subDomain] = value, neuman
                maxId = max(maxId, bc.subDomain)
            else:
                domain = ExprTensor(())
                for key in domain.keys():
                    domain[key] = Indexed(
                        bc.subDomain,
                        MultiIndex(tuple(FixedIndex(k) for k in key)))
                codeDomains.append((value, neuman, domain))
        defaultCode = []
        if len(codeDomains) > 0:
            defaultCode.append(Declaration(Variable('int', 'domainId')))
        # defaultCode.append(Declaration(Variable('auto', 'x'),
        #     initializer=UnformattedExpression('auto','intersection.geometry().center()')))
        for i, v in enumerate(codeDomains):
            block = Block()
            block.append(
                generateDirichletDomainCode(predefined,
                                            v[2],
                                            tempVars=tempVars))
            block.append('if (domainId)')
            ifBlock = UnformattedBlock()
            ifBlock.append(
                'std::fill( dirichletComponent.begin(), dirichletComponent.end(), '
                + str(maxId + i + 2) + ' );')
            if len(v[1]) > 0:
                [
                    ifBlock.append('dirichletComponent[' + str(c) + '] = 0;')
                    for c in v[1]
                ]
            ifBlock.append('return true;')
            block.append(ifBlock)
            defaultCode.append(block)
        if wholeDomain is not None:
            block = UnformattedBlock()
            block.append(
                'std::fill( dirichletComponent.begin(), dirichletComponent.end(), '
                + str(maxId + 1) + ' );')
            if len(wholeDomain[1]) > 0:
                [
                    block.append('dirichletComponent[' + str(c) + '] = 0;')
                    for c in wholeDomain[1]
                ]
            block.append('return true;')
            defaultCode.append(block)
        defaultCode.append(return_(False))

        bndId = Variable('const int', 'bndId')
        getBndId = UnformattedExpression(
            'int', 'BoundaryIdProviderType::boundaryId( ' +
            integrands.arg_i.name + ' )')
        # getBndId = UnformattedExpression('int', 'boundaryIdGetter_.boundaryId( ' + integrands.arg_i.name + ' )')
        switch = SwitchStatement(bndId, default=defaultCode)
        for i, v in bySubDomain.items():
            code = []
            if len(v[1]) > 0:
                [
                    code.append('dirichletComponent[' + str(c) + '] = 0;')
                    for c in v[1]
                ]
            code.append(return_(True))
            switch.append(i, code)
        integrands.isDirichletIntersection = [
            Declaration(bndId, initializer=getBndId),
            UnformattedBlock(
                'std::fill( dirichletComponent.begin(), dirichletComponent.end(), '
                + bndId.name + ' );'), switch
        ]

        predefined[x] = UnformattedExpression(
            'auto', 'entity().geometry().global( Dune::Fem::coordinate( ' +
            integrands.arg_x.name + ' ) )')
        if wholeDomain is None:
            defaultCode = assign(integrands.arg_r, construct("RRangeType", 0))
        else:
            defaultCode = generateDirichletCode(predefined,
                                                wholeDomain[0],
                                                tempVars=tempVars)
        switch = SwitchStatement(integrands.arg_bndId, default=defaultCode)
        for i, v in bySubDomain.items():
            switch.append(
                i, generateDirichletCode(predefined, v[0], tempVars=tempVars))
        for i, v in enumerate(codeDomains):
            switch.append(
                i + maxId + 2,
                generateDirichletCode(predefined, v[0], tempVars=tempVars))
        integrands.dirichlet = [switch]

    return integrands
Exemplo n.º 13
0
    def methods(self, code):
        code.append(TypeAlias("DomainValueType", self.domainValueTuple))
        code.append(TypeAlias("RangeValueType", self.rangeValueTuple))

        if self.interior is not None:
            code.append(
                Method('RangeValueType',
                       'interior',
                       targs=['class Point'],
                       args=['const Point &x', 'const DomainValueType &u'],
                       code=self.interior,
                       const=True))
            code.append(
                Method('auto',
                       'linearizedInterior',
                       targs=['class Point'],
                       args=['const Point &x', 'const DomainValueType &u'],
                       code=self.linearizedInterior,
                       const=True))

        if self.boundary is not None:
            code.append(
                Method('RangeValueType',
                       'boundary',
                       targs=['class Point'],
                       args=['const Point &x', 'const DomainValueType &u'],
                       code=self.boundary,
                       const=True))
            code.append(
                Method('auto',
                       'linearizedBoundary',
                       targs=['class Point'],
                       args=['const Point &x', 'const DomainValueType &u'],
                       code=self.linearizedBoundary,
                       const=True))

        if self.skeleton is not None:
            code.append(
                Method('std::pair< RangeValueType, RangeValueType >',
                       'skeleton',
                       targs=['class Point'],
                       args=[
                           'const Point &xIn', 'const DomainValueType &uIn',
                           'const Point &xOut', 'const DomainValueType &uOut'
                       ],
                       code=self.skeleton,
                       const=True))
            code.append(
                Method('auto',
                       'linearizedSkeleton',
                       targs=['class Point'],
                       args=[
                           'const Point &xIn', 'const DomainValueType &uIn',
                           'const Point &xOut', 'const DomainValueType &uOut'
                       ],
                       code=self.linearizedSkeleton,
                       const=True))

        # added for dirichlet treatment - same as conservationlaw model
        if self.hasDirichletBoundary is not None:
            code.append(
                TypeAlias(
                    "RRangeType", 'Dune::FieldVector< double, ' +
                    str(self.dimRange) + ' > '))
            code.append(
                TypeAlias(
                    "BoundaryIdProviderType",
                    "Dune::Fem::BoundaryIdProvider< typename GridPartType::GridType >"
                ))
            # code.append(TypeAlias("BoundaryIdProviderType",\ "Dune::Fem::BoundaryIdGetter< typename GridPartType::GridType >"))
            # idGetter = Variable('BoundaryIdProviderType', "boundaryIdGetter_")
            # code.append(Declaration(idGetter))
            code.append(
                TypeAlias("DirichletComponentType",
                          "std::array<int," + str(self.dimRange) + ">"))
            code.append(
                Method('bool',
                       'hasDirichletBoundary',
                       const=True,
                       code=return_(self.hasDirichletBoundary)))
            code.append(Method('bool', 'isDirichletIntersection', args=[self.arg_i, 'DirichletComponentType &dirichletComponent'],
                code=self.isDirichletIntersection\
                          if self.isDirichletIntersection is not None else\
                     [return_(False)],
                const=True))
            code.append(
                Method('void',
                       'dirichlet',
                       targs=['class Point'],
                       args=[self.arg_bndId, self.arg_x, self.arg_r],
                       code=self.dirichlet,
                       const=True))