Exemple #1
0
def expression_to_subdomain(cpparg, classname):
    """
    Generate code for a :py:class:`SubDomain <dolfin.cpp.SubDomain>`
    subclass for a single expression.
    """

    # Assure we have a simple string expression
    assert isinstance(cpparg, string_types)

    # Extract code fragments from the expr and defaults
    fragments, members = expression_to_code_fragments(\
        [cpparg], ["x", "on_boundary", "DOLFIN_EPS"])

    # Generate code for inside()
    insidecode = "  return %s;" % cpparg

    # Generate code for map()
    #mapcode = "..."

    # Connect the code fragments using the function template code
    fragments["inside"] = insidecode
    fragments["classname"] = classname
    #fragments["map"]       = mapcode
    code = _subdomain_template % fragments
    return code, members
Exemple #2
0
def expression_to_subdomain(cpparg, classname):
    """
    Generate code for a :py:class:`SubDomain <dolfin.cpp.SubDomain>`
    subclass for a single expression.
    """

    # Assure we have a simple string expression
    assert isinstance(cpparg, str)

    # Extract code fragments from the expr and defaults
    fragments, members = expression_to_code_fragments(\
        [cpparg], ["x", "on_boundary", "DOLFIN_EPS"])
    
    # Generate code for inside()
    insidecode = "  return %s;" % cpparg
    
    # Generate code for map()
    #mapcode = "..."

    # Connect the code fragments using the function template code
    fragments["inside"]    = insidecode
    fragments["classname"] = classname
    #fragments["map"]       = mapcode
    code = _subdomain_template % fragments
    return code, members
Exemple #3
0
def expression_to_dolfin_expression(expr, constant_members):
    "Generates code for a dolfin::Expression subclass for a single expression."

    # Check and flattern provided expression
    expr, shape = flatten_and_check_expression(expr)

    # Extract code fragments from the expr
    fragments, members = expression_to_code_fragments(\
        expr, ["v","x"], constant_members)

    # Generate code for value_rank
    value_shape_code = ["    _value_shape.push_back(%d);" % value_dim \
                        for value_dim in shape]

    evalcode = []

    # Generate code for constant members
    evalcode.extend("    const double %s = *shared_%s;" % (name, name) \
                     for name in constant_members)

    # Generate code for the actual expression evaluation
    evalcode.extend("    values[%d] = %s;" % (i, c) for (i,c) in enumerate(expr))

    # Connect the code fragments using the expression template code
    fragments["evalcode"]  = "\n".join(evalcode)
    fragments["value_shape"] = "\n".join(value_shape_code)

    # Assign classname
    classname = "Expression_" + hashlib.md5(fragments["evalcode"]).hexdigest()
    fragments["classname"] = classname

    # Produce the C++ code for the expression class
    code = _expression_template % fragments
    return classname, code, members
Exemple #4
0
def expression_to_dolfin_expression(expr, generic_function_members):
    "Generates code for a dolfin::Expression subclass for a single expression."

    # Check and flattern provided expression
    expr, shape = flatten_and_check_expression(expr)

    # Extract code fragments from the expr
    fragments, members = expression_to_code_fragments(
        expr, ["values", "x"], generic_function_members)

    # Generate code for value_rank
    value_shape_code = [
        "    _value_shape.push_back(%d);" % value_dim for value_dim in shape
    ]

    evalcode = []

    # Generate code for constant members
    for name in generic_function_members:
        evalcode.append("    if (shared_%s->value_size()!=1)" % name)
        evalcode.append("      dolfin_error(\"generated code\",")
        evalcode.append("                   \"calling eval\", ")
        evalcode.append(
            "                   \"Parameter \\'%s\\' is not scalar valued\");"
            % name)
        evalcode.append("    if (shared_%s.get()==this)" % name)
        evalcode.append("      dolfin_error(\"generated code\",")
        evalcode.append("                   \"calling eval\",")
        evalcode.append(
            "                   \"Circular eval call detected. Cannot use itself as parameter \\'%s\\' within eval\");"
            % name)
        evalcode.append("    Array<double> %s__array_(1);" % name)
        evalcode.append("    shared_%s->eval(%s__array_, x);" % (name, name))
        evalcode.append("    const double %s = %s__array_[0];" % (name, name))

    # Generate code for the actual expression evaluation
    evalcode.extend("    values[%d] = %s;" % (i, c)
                    for (i, c) in enumerate(expr))

    # Connect the code fragments using the expression template code
    fragments["evalcode"] = "\n".join(evalcode)
    fragments["evalcode_cell"] = fragments["evalcode"].replace(
        "__array_, x", "__array_, x, cell")
    fragments["value_shape"] = "\n".join(value_shape_code)

    # Assign classname
    classname = "Expression_" + hashlib.sha1(
        fragments["evalcode"].encode("utf-8")).hexdigest()
    fragments["classname"] = classname

    # Produce the C++ code for the expression class
    code = _expression_template % fragments
    return classname, code, members
Exemple #5
0
def expression_to_dolfin_expression(expr, generic_function_members):
    "Generates code for a dolfin::Expression subclass for a single expression."

    # Check and flattern provided expression
    expr, shape = flatten_and_check_expression(expr)

    # Extract code fragments from the expr
    fragments, members = expression_to_code_fragments(\
        expr, ["values","x"], generic_function_members)

    # Generate code for value_rank
    value_shape_code = ["    _value_shape.push_back(%d);" % value_dim \
                        for value_dim in shape]

    evalcode = []

    # Generate code for constant members
    for name in generic_function_members:
        evalcode.append("    if (shared_%s->value_size()!=1)" % name)
        evalcode.append("      dolfin_error(\"generated code\",")
        evalcode.append("                   \"calling eval\", ")
        evalcode.append("                   \"Parameter \\'%s\\' is not scalar valued\");" % name)
        evalcode.append("    if (shared_%s.get()==this)" % name)
        evalcode.append("      dolfin_error(\"generated code\",")
        evalcode.append("                   \"calling eval\",")
        evalcode.append("                   \"Circular eval call detected. Cannot use itself as parameter \\'%s\\' within eval\");" % name)
        evalcode.append("    Array<double> %s__array_(1);" % name)
        evalcode.append("    shared_%s->eval(%s__array_, x);" % (name, name))
        evalcode.append("    const double %s = %s__array_[0];" % (name, name))

    # Generate code for the actual expression evaluation
    evalcode.extend("    values[%d] = %s;" % (i, c) for (i,c) in enumerate(expr))

    # Connect the code fragments using the expression template code
    fragments["evalcode"]  = "\n".join(evalcode)
    fragments["evalcode_cell"]  = fragments["evalcode"].replace(\
        "__array_, x", "__array_, x, cell")
    fragments["value_shape"] = "\n".join(value_shape_code)

    # Assign classname
    classname = "Expression_" + hashlib.sha1(fragments["evalcode"].\
                                             encode("utf-8")).hexdigest()
    fragments["classname"] = classname

    # Produce the C++ code for the expression class
    code = _expression_template % fragments
    return classname, code, members
Exemple #6
0
def expression_to_dolfin_expression(expr, generic_function_members,
                                    mesh_function_members):
    "Generates code for a dolfin::Expression subclass for a single expression."

    # TODO: Make this configurable through global dolfin 'debug mode' parameter?
    add_runtime_checks = True

    # Check and flattern provided expression
    expr, expr_shape = flatten_and_check_expression(expr)

    # Extract code fragments from the expr
    generic_function_member_names = [
        item[0] for item in generic_function_members
    ]
    fragments, members = expression_to_code_fragments(
        expr, ["values", "x"], generic_function_member_names,
        mesh_function_members)

    # Generate code for value_rank
    value_shape_code = [
        "    _value_shape.push_back(%d);" % value_dim
        for value_dim in expr_shape
    ]

    evalcode = []

    # Runtime checks (TODO: Better to check these when updating the value instead...)
    if add_runtime_checks:
        for name, shape in generic_function_members:
            dim = product(shape)
            evalcode.append("    if (shared_%s->value_size() != %d)" %
                            (name, dim))
            evalcode.append("      dolfin_error(\"generated code\",")
            evalcode.append("                   \"calling eval\", ")
            evalcode.append(
                "                   \"Expecting value size %d for parameter \\'%s\\'\");"
                % (dim, name))
            evalcode.append("    if (shared_%s.get() == this)" % name)
            evalcode.append("      dolfin_error(\"generated code\",")
            evalcode.append("                   \"calling eval\",")
            evalcode.append(
                "                   \"Circular eval call detected. Cannot use itself as parameter \\'%s\\' within eval\");"
                % name)
            evalcode.append("")

    # Generate code for evaluating genericfunction members
    for name, shape in generic_function_members:
        dim = product(shape)

        # Setup output array and call eval
        evalcode.append("    double %s__data_[%d];" % (name, dim))
        evalcode.append("    Array<double> %s__array_(%d, %s__data_);" %
                        (name, dim, name))
        evalcode.append("    shared_%s->eval(%s__array_, x);" % (name, name))

        # Ensure const access through userdefined name
        if shape:
            # Vector valued result
            evalcode.append("    const Array<double> & %s = %s__array_;" %
                            (name, name))
        else:
            # Scalar valued result
            evalcode.append("    const double %s = %s__array_[0];" %
                            (name, name))
        evalcode.append("")

    # Lookup in MeshFunction<typename>(mesh, tdim)
    for name, typename in mesh_function_members:
        evalcode.append("    const %s %s = (*shared_%s)[cell.index];" %
                        (typename, name, name))

    # Generate code for the actual expression evaluation
    evalcode.extend("    values[%d] = %s;" % (i, c)
                    for i, c in enumerate(expr))

    # Adapt evalcode to with/without cell argument if possible
    evalcode = "\n".join(evalcode)
    evalcode_cell = evalcode.replace("__array_, x", "__array_, x, cell")
    if mesh_function_members:
        # TODO: Reuse code in Function::eval(values, x) which looks up cell from x?
        evalcode = []
        evalcode.append("      dolfin_error(\"generated code\",")
        evalcode.append("                   \"calling eval\", ")
        evalcode.append(
            "                   \"Need cell to evaluate this Expression\");")
        evalcode = "\n".join(evalcode)

    # Connect the code fragments using the expression template code
    fragments["evalcode"] = evalcode
    fragments["evalcode_cell"] = evalcode_cell
    fragments["value_shape"] = "\n".join(value_shape_code)

    # Assign classname
    classname = "Expression_" + hashlib.sha1(
        fragments["evalcode"].encode("utf-8")).hexdigest()
    fragments["classname"] = classname

    # Produce the C++ code for the expression class
    code = _expression_template % fragments
    return classname, code, members