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
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
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
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
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
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