def generate_integral_code(ir, prefix, parameters): "Generate code for integral from intermediate representation." info("Generating code from ffc.uflacs representation") # FIXME: Is this the right precision value to use? Make it default to None or 0. precision = ir["integrals_metadata"]["precision"] # Create FFC C++ backend backend = FFCBackend(ir, parameters) # Configure kernel generator ig = IntegralGenerator(ir, backend, precision) # Generate code ast for the tabulate_tensor body parts = ig.generate() # Format code as string body = format_indented_lines(parts.cs_format(precision), 1) # Generate generic ffc code snippets and add uflacs specific parts code = initialize_integral_code(ir, prefix, parameters) code["tabulate_tensor"] = body code["additional_includes_set"] = set(ig.get_includes()) code["additional_includes_set"].update( ir.get("additional_includes_set", ())) # TODO: Move to initialize_integral_code, this is not representation specific if ir.get("num_cells") is not None: ret = backend.language.Return(ir["num_cells"]) code["num_cells"] = format_indented_lines(ret.cs_format(), 1) return code
def UnitTriangle(color=(0.0, 1.0, 0.0, 0.5)): "Return model for unit tetrahedron." info("Plotting unit triangle") # Create separate scene (since we will extract a model, not render) scene = soya.World() # Create vertice v0 = soya.Vertex(scene, 0.0, 0.0, 0.0, diffuse=color) v1 = soya.Vertex(scene, 1.0, 0.0, 0.0, diffuse=color) v2 = soya.Vertex(scene, 0.0, 1.0, 0.0, diffuse=color) # Create edges e0 = Cylinder(scene, v0, v1, 0.007) e1 = Cylinder(scene, v0, v2, 0.007) e2 = Cylinder(scene, v1, v2, 0.007) # Create face f = soya.Face(scene, (v0, v1, v2)) # Make face double sided f.double_sided = 1 # Extract model model = scene.to_model() return model
def generate_integral_code(ir, prefix, parameters): "Generate code for integral from intermediate representation." info("Generating code from ffc.uflacs representation") # FIXME: Is this the right precision value to use? Make it default to None or 0. precision = ir["integrals_metadata"]["precision"] # Create FFC C++ backend backend = FFCBackend(ir, parameters) # Configure kernel generator ig = IntegralGenerator(ir, backend, precision) # Generate code ast for the tabulate_tensor body parts = ig.generate() # Format code as string body = format_indented_lines(parts.cs_format(precision), 1) # Generate generic ffc code snippets and add uflacs specific parts code = initialize_integral_code(ir, prefix, parameters) code["tabulate_tensor"] = body code["additional_includes_set"] = set(ig.get_includes()) code["additional_includes_set"].update(ir.get("additional_includes_set", ())) # TODO: Move to initialize_integral_code, this is not representation specific if ir.get("num_cells") is not None: ret = backend.language.Return(ir["num_cells"]) code["num_cells"] = format_indented_lines(ret.cs_format(), 1) return code
def generate_test_cases(bench, only_forms): "Generate form files for all test cases." begin("Generating test cases") # Copy form files if bench: form_directory = bench_directory else: form_directory = demo_directory # Make list of form files form_files = [f for f in os.listdir(form_directory) if f.endswith(".ufl")] if only_forms: form_files = [f for f in form_files if f in only_forms] form_files.sort() for f in form_files: shutil.copy(os.path.join(form_directory, f), ".") info_green("Found %d form files" % len(form_files)) # Generate form files for forms info("Generating form files for extra forms: Not implemented") # Generate form files for elements if not bench: from elements import elements info("Generating form files for extra elements (%d elements)" % len(elements)) for (i, element) in enumerate(elements): open("X_Element%d.ufl" % i, "w").write("element = %s" % element) end()
def PointSecondDerivative(x): "Return model for evaluation of second derivatives at given point." info("Plotting dof: point derivative at x = %s" % str(x)) # Make sure point is 3D x = to3d(x) # Create separate scene (since we will extract a model, not render) scene = soya.World() # Define material (color) for the sphere material = soya.Material() material.diffuse = (0.0, 0.0, 0.0, 0.05) # Create sphere sphere = Sphere(scene, material=material) # Scale and moveand move to coordinate sphere.scale(0.15, 0.15, 0.15) p = sphere.position() p.set_xyz(x[0], x[1], x[2]) sphere.move(p) # Extract model model = scene.to_model() return model
def UnitTriangle(color=(0.0, 1.0, 0.0, 0.5)): "Return model for unit tetrahedron." info("Plotting unit triangle") # Create separate scene (since we will extract a model, not render) scene = soya.World() # Create vertice v0 = soya.Vertex(scene, 0.0, 0.0, 0.0, diffuse=color) v1 = soya.Vertex(scene, 1.0, 0.0, 0.0, diffuse=color) v2 = soya.Vertex(scene, 0.0, 1.0, 0.0, diffuse=color) # Create edges e0 = Cylinder(scene, v0, v1, 0.007) e1 = Cylinder(scene, v0, v2, 0.007) e2 = Cylinder(scene, v1, v2, 0.007) # Create face f = soya.Face(scene, (v0, v1, v2)) # Make face double sided f.double_sided = 1 # Extract model model = scene.to_model() return model
def generate_integral_code(ir, prefix, parameters): "Generate code for integral from intermediate representation." info("Generating code from tsfc representation") # Generate generic ffc code snippets code = initialize_integral_code(ir, prefix, parameters) # Go unoptimized if TSFC mode has not been set yet integral_data, form_data, prefix, parameters = ir["compile_integral"] parameters = parameters.copy() parameters.setdefault("mode", "vanilla") # Generate tabulate_tensor body ast = compile_integral(integral_data, form_data, None, parameters, interface=ufc_interface) # COFFEE vectorize knl = ASTKernel(ast) knl.plan_cpu(dict(optlevel='Ov')) tsfc_code = "".join(b.gencode() for b in ast.body) tsfc_code = tsfc_code.replace("#pragma coffee", "//#pragma coffee") # FIXME code["tabulate_tensor"] = tsfc_code includes = set() includes.update(ir.get("additional_includes_set", ())) includes.update(ast.headers) includes.add("#include <cstring>") # memset if any(node.funcall.symbol.startswith("boost::math::") for node in Find(coffee.FunCall).visit(ast)[coffee.FunCall]): includes.add("#include <boost/math/special_functions.hpp>") code["additional_includes_set"] = includes return code
def extract_monomial_form(integrals, function_replace_map): """ Extract monomial representation of form (if possible). When successful, the form is represented as a sum of products of scalar components of basis functions or derivatives of basis functions. If unsuccessful, MonomialException is raised. """ info("Extracting monomial form representation from UFL form") # Iterate over all integrals monomial_form = MonomialForm() for integral in integrals: # Get measure and integrand measure = integral.measure() if measure.domain_type() == "point": raise MonomialException( "Point integrals are not supported by tensor representation.") integrand = integral.integrand() # Extract monomial representation if possible integrand = extract_monomial_integrand(integrand, function_replace_map) monomial_form.append(integrand, measure) return monomial_form
def DirectionalEvaluation(x, n, flip=False, center=False): "Return model for directional evaluation at given point in given direction." info("Plotting dof: directional evaluation at x = %s in direction n = %s" % (str(x), str(n))) # Make sure points are 3D x = to3d(x) n = to3d(n) # Create separate scene (since we will extract a model, not render) scene = soya.World() # Normalize n = array(n) n = 0.75 * n / norm(n) # Flip normal if necessary if flip and not pointing_outwards(x, n): info("Flipping direction of arrow so it points outward.") n = -n # Create arrow arrow = Arrow(scene, x, n, center) # Extract model model = scene.to_model() return model
def PointSecondDerivative(x): "Return model for evaluation of second derivatives at given point." info("Plotting dof: point derivative at x = %s" % str(x)) # Make sure point is 3D x = to3d(x) # Create separate scene (since we will extract a model, not render) scene = soya.World() # Define material (color) for the sphere material = soya.Material() material.diffuse = (0.0, 0.0, 0.0, 0.05) # Create sphere sphere = Sphere(scene, material=material) # Scale and moveand move to coordinate sphere.scale(0.15, 0.15, 0.15) p = sphere.position() p.set_xyz(x[0], x[1], x[2]) sphere.move(p) # Extract model model = scene.to_model() return model
def verify_element(num_elements, i, ufl_element): info("\nVerifying element %d of %d: %s" % (i, num_elements, str(ufl_element))) error = compile_element(ufl_element, ffc_fail, log_file) # Return if test failed if error: return 1 # Get FIAT values that are formatted in the same way as the values from # evaluate_basis and evaluate_basis_derivatives. # t = time.time() fiat_values = get_fiat_values(ufl_element) # print "fiat_vals: ", time.time() - t # Get FFC values. t = time.time() ffc_values = get_ffc_values(ufl_element) if ffc_values is None: return 1 debug(" time to compute FFC values: %f" % (time.time() - t)) # Compare values and return number of tests. return verify_values(ufl_element, fiat_values, ffc_values, dif_cri, dif_acc, correct, log_file)
def DirectionalEvaluation(x, n, flip=False, center=False): "Return model for directional evaluation at given point in given direction." info("Plotting dof: directional evaluation at x = %s in direction n = %s" % (str(x), str(n))) # Make sure points are 3D x = to3d(x) n = to3d(n) # Create separate scene (since we will extract a model, not render) scene = soya.World() # Normalize n = array(n) n = 0.75 * n / norm(n) # Flip normal if necessary if flip and not pointing_outwards(x, n): info("Flipping direction of arrow so it points outward.") n = -n # Create arrow arrow = Arrow(scene, x, n, center) # Extract model model = scene.to_model() return model
def generate_test_cases(bench, only_forms): "Generate form files for all test cases." begin("Generating test cases") # Copy form files if bench: form_directory = bench_directory else: form_directory = demo_directory # Make list of form files form_files = [f for f in os.listdir(form_directory) if f.endswith(".ufl")] if only_forms: form_files = [f for f in form_files if f in only_forms] form_files.sort() for f in form_files: shutil.copy("%s/%s" % (form_directory, f), ".") info_green("Found %d form files" % len(form_files)) # Generate form files for forms info("Generating form files for extra forms: Not implemented") # Generate form files for elements if not bench: from elements import elements info("Generating form files for extra elements (%d elements)" % len(elements)) for (i, element) in enumerate(elements): open("X_Element%d.ufl" % i, "w").write("element = %s" % element) end()
def integrate(monomial, integral_type, facet0, facet1, quadrature_degree, quadrature_rule, cellname, facet_cellname): """Compute the reference tensor for a given monomial term of a multilinear form""" info("Precomputing integrals on reference element") # Start timing tic = time.time() # Initialize quadrature points and weights (points, weights) = _init_quadrature(monomial.arguments, integral_type, quadrature_degree, quadrature_rule, cellname, facet_cellname) # Initialize quadrature table for basis functions table = _init_table(monomial.arguments, integral_type, points, facet0, facet1) # Compute table Psi for each factor psis = [_compute_psi(v, table, len(points), integral_type) \ for v in monomial.arguments] # Compute product of all Psis A0 = _compute_product(psis, monomial.float_value * weights) # Report elapsed time and number of entries toc = time.time() - tic num_entries = numpy.prod(numpy.shape(A0)) debug("%d entries computed in %.3g seconds" % (num_entries, toc)) debug("Shape of reference tensor: " + str(numpy.shape(A0))) return A0
def _analyze_form(form, parameters): "Analyze form, returning form data." # Check that form is not empty ffc_assert(not form.empty(), "Form (%s) seems to be zero: cannot compile it." % str(form)) # Compute form metadata if parameters["representation"] == "uflacs": # Temporary workaround to let uflacs have a different preprocessing pipeline # than the legacy representations quadrature and tensor. This approach imposes # a limitation that e.g. uflacs and tensor representation cannot be mixed in the same form. from ufl.classes import Jacobian form_data = compute_form_data(form, do_apply_function_pullbacks=True, do_apply_integral_scaling=True, do_apply_geometry_lowering=True, preserve_geometry_types=(Jacobian,), do_apply_restrictions=True, ) else: form_data = compute_form_data(form) info("") info(str(form_data)) # Attach integral meta data _attach_integral_metadata(form_data, parameters) return form_data
def _analyze_form(form, parameters): "Analyze form, returning form data." # Check that form is not empty if form.empty(): error("Form (%s) seems to be zero: cannot compile it." % str(form)) # Hack to override representation with environment variable forced_r = os.environ.get("FFC_FORCE_REPRESENTATION") if forced_r: warning( "representation: forced by $FFC_FORCE_REPRESENTATION to '%s'" % forced_r) r = forced_r else: # Check representation parameters to figure out how to # preprocess r = _extract_representation_family(form, parameters) debug("Preprocessing form using '%s' representation family." % r) # Compute form metadata if r == "uflacs": # Temporary workaround to let uflacs have a different # preprocessing pipeline than the legacy quadrature # representation. This approach imposes a limitation that, # e.g. uflacs and qudrature, representations cannot be mixed # in the same form. from ufl.classes import Jacobian form_data = compute_form_data(form, do_apply_function_pullbacks=True, do_apply_integral_scaling=True, do_apply_geometry_lowering=True, preserve_geometry_types=(Jacobian, ), do_apply_restrictions=True) elif r == "tsfc": try: # TSFC provides compute_form_data wrapper using correct # kwargs from tsfc.ufl_utils import compute_form_data as tsfc_compute_form_data except ImportError: error( "Failed to import tsfc.ufl_utils.compute_form_data when asked " "for tsfc representation.") form_data = tsfc_compute_form_data(form) elif r == "quadrature": # quadrature representation form_data = compute_form_data(form) else: error("Unexpected representation family '%s' for form preprocessing." % r) info("") info(str(form_data)) # Attach integral meta data _attach_integral_metadata(form_data, r, parameters) _validate_representation_choice(form_data, r) return form_data
def compute_integral_ir(itg_data, form_data, form_id, parameters): "Compute intermediate represention of integral." info("Computing quadrature representation") # Initialise representation ir = initialize_integral_ir("quadrature", itg_data, form_data, form_id) # Sort integrals into a dict with number of integral points as key sorted_integrals = _sort_integrals(itg_data.integrals, itg_data.metadata, form_data) # Tabulate quadrature points and basis function values in these points integrals_dict, psi_tables, quad_weights = \ _tabulate_basis(sorted_integrals, itg_data.domain_type, form_data) # Save tables for quadrature weights and points ir["quadrature_weights"] = quad_weights # Create dimensions of primary indices, needed to reset the argument 'A' # given to tabulate_tensor() by the assembler. ir["prim_idims"] = [create_element(ufl_element).space_dimension() for ufl_element in form_data.argument_elements] # Create and save the optisation parameters. ir["optimise_parameters"] = _parse_optimise_parameters(parameters) # Create transformer. if ir["optimise_parameters"]["optimisation"]: QuadratureTransformerClass = QuadratureTransformerOpt else: QuadratureTransformerClass = QuadratureTransformer transformer = QuadratureTransformerClass(psi_tables, quad_weights, form_data.geometric_dimension, form_data.topological_dimension, ir["entitytype"], form_data.function_replace_map, ir["optimise_parameters"]) # Transform integrals. ir["trans_integrals"] = _transform_integrals_by_type(ir, transformer, integrals_dict, itg_data.domain_type, form_data.cell) # Save tables populated by transformer ir["name_map"] = transformer.name_map ir["unique_tables"] = transformer.unique_tables # Basis values? # Save tables map, to extract table names for optimisation option -O. ir["psi_tables_map"] = transformer.psi_tables_map ir["additional_includes_set"] = transformer.additional_includes_set # Insert empty data which will be populated if optimization is turned on ir["geo_consts"] = {} return ir
def compute_integral_ir(itg_data, form_data, form_id, parameters): "Compute intermediate represention of integral." info("Computing quadrature representation") # Initialise representation ir = initialize_integral_ir("quadrature", itg_data, form_data, form_id) # Sort integrals into a dict with number of integral points as key sorted_integrals = _sort_integrals(itg_data.integrals, itg_data.metadata, form_data) # Tabulate quadrature points and basis function values in these points integrals_dict, psi_tables, quad_weights = \ _tabulate_basis(sorted_integrals, itg_data.domain_type, form_data) # Save tables for quadrature weights and points ir["quadrature_weights"] = quad_weights # Create dimensions of primary indices, needed to reset the argument 'A' # given to tabulate_tensor() by the assembler. ir["prim_idims"] = [ create_element(ufl_element).space_dimension() for ufl_element in form_data.argument_elements ] # Create and save the optisation parameters. ir["optimise_parameters"] = _parse_optimise_parameters(parameters) # Create transformer. if ir["optimise_parameters"]["optimisation"]: QuadratureTransformerClass = QuadratureTransformerOpt else: QuadratureTransformerClass = QuadratureTransformer transformer = QuadratureTransformerClass(psi_tables, quad_weights, form_data.geometric_dimension, form_data.topological_dimension, ir["entitytype"], form_data.function_replace_map, ir["optimise_parameters"]) # Transform integrals. ir["trans_integrals"] = _transform_integrals_by_type( ir, transformer, integrals_dict, itg_data.domain_type, form_data.cell) # Save tables populated by transformer ir["name_map"] = transformer.name_map ir["unique_tables"] = transformer.unique_tables # Basis values? # Save tables map, to extract table names for optimisation option -O. ir["psi_tables_map"] = transformer.psi_tables_map ir["additional_includes_set"] = transformer.additional_includes_set # Insert empty data which will be populated if optimization is turned on ir["geo_consts"] = {} return ir
def compute_integral_ir(itg_data, form_data, form_id, element_numbers, parameters): "Compute intermediate represention of integral." info("Computing tensor representation") # Extract monomial representation integrands = [itg.integrand() for itg in itg_data.integrals] monomial_form = extract_monomial_form(integrands, form_data.function_replace_map) # Transform monomial form to reference element transform_monomial_form(monomial_form) # Get some integral properties integral_type = itg_data.integral_type quadrature_degree = itg_data.metadata["quadrature_degree"] quadrature_rule = itg_data.metadata["quadrature_rule"] # Get some cell properties cell = itg_data.domain.ufl_cell() num_facets = cell.num_facets() # Helper to simplify code below compute_terms = lambda i, j: _compute_terms(monomial_form, i, j, integral_type, quadrature_degree, quadrature_rule, cell) # Compute representation of cell tensor if integral_type == "cell": # Compute sum of tensor representations terms = compute_terms(None, None) elif integral_type == "exterior_facet": # Compute sum of tensor representations for each facet terms = [compute_terms(i, None) for i in range(num_facets)] elif integral_type == "interior_facet": # Compute sum of tensor representations for each facet-facet pair terms = [[compute_terms(i, j) for j in range(num_facets)] for i in range(num_facets)] for i in range(num_facets): for j in range(num_facets): reorder_entries(terms[i][j]) else: error("Unhandled domain type: " + str(integral_type)) # Initialize representation and store terms ir = initialize_integral_ir("tensor", itg_data, form_data, form_id) ir["AK"] = terms return ir
def _write_file(output, prefix, postfix, parameters): "Write generated code to file." prefix = prefix.split(os.path.join(' ',' ').split()[0])[-1] full_prefix = os.path.join(parameters["output_dir"], prefix) filename = "%s%s" % (full_prefix, postfix) hfile = open(filename, "w") hfile.write(output) hfile.close() info("Output written to " + filename + ".")
def optimize_integral_ir(ir, parameters): "Compute optimized intermediate representation of integral." info("Optimizing uflacs representation") # TODO: Implement optimization of ssa representation prior to code generation here. oir = ir return oir
def optimize_integral_ir(ir, parameters): "Compute optimized intermediate representation of integral." info("Optimizing uflacs representation") # Call upon uflacs to optimize ssa representation prior to code generation. Should be possible to skip this step. import uflacs.backends.ffc oir = uflacs.backends.ffc.optimize_tabulate_tensor_ir(ir, parameters) return oir
def optimize_integral_ir(ir, parameters): "Compute optimized intermediate representation of integral." info("Optimizing uflacs representation") # Call upon uflacs to optimize ssa representation prior to code generation. Should be possible to skip this step. import uflacs.backends.ffc oir = uflacs.backends.ffc.optimize_tabulate_tensor_ir(ir, parameters) return oir
def compute_integral_ir(itg_data, form_data, form_id, element_numbers, parameters): "Compute intermediate represention of integral." info("Computing tensor representation") # Extract monomial representation integrands = [itg.integrand() for itg in itg_data.integrals] monomial_form = extract_monomial_form(integrands, form_data.function_replace_map) # Transform monomial form to reference element transform_monomial_form(monomial_form) # Get some integral properties integral_type = itg_data.integral_type quadrature_degree = itg_data.metadata["quadrature_degree"] quadrature_rule = itg_data.metadata["quadrature_rule"] # Get some cell properties cell = itg_data.domain.cell() cellname = cell.cellname() facet_cellname = cell.facet_cellname() num_facets = cell.num_facets() # Helper to simplify code below compute_terms = lambda i, j: _compute_terms( monomial_form, i, j, integral_type, quadrature_degree, quadrature_rule, cellname, facet_cellname) # Compute representation of cell tensor if integral_type == "cell": # Compute sum of tensor representations terms = compute_terms(None, None) elif integral_type == "exterior_facet": # Compute sum of tensor representations for each facet terms = [compute_terms(i, None) for i in range(num_facets)] elif integral_type == "interior_facet": # Compute sum of tensor representations for each facet-facet pair terms = [[compute_terms(i, j) for j in range(num_facets)] for i in range(num_facets)] for i in range(num_facets): for j in range(num_facets): reorder_entries(terms[i][j]) else: error("Unhandled domain type: " + str(integral_type)) # Initialize representation and store terms ir = initialize_integral_ir("tensor", itg_data, form_data, form_id) ir["AK"] = terms return ir
def _analyze_form(form, parameters): "Analyze form, returning form data." # Check that form is not empty if form.empty(): error("Form (%s) seems to be zero: cannot compile it." % str(form)) # Hack to override representation with environment variable forced_r = os.environ.get("FFC_FORCE_REPRESENTATION") if forced_r: warning("representation: forced by $FFC_FORCE_REPRESENTATION to '%s'" % forced_r) r = forced_r else: # Check representation parameters to figure out how to # preprocess r = _extract_representation_family(form, parameters) debug("Preprocessing form using '%s' representation family." % r) # Compute form metadata if r == "uflacs": # Temporary workaround to let uflacs have a different # preprocessing pipeline than the legacy quadrature # representation. This approach imposes a limitation that, # e.g. uflacs and qudrature, representations cannot be mixed # in the same form. from ufl.classes import Jacobian form_data = compute_form_data(form, do_apply_function_pullbacks=True, do_apply_integral_scaling=True, do_apply_geometry_lowering=True, preserve_geometry_types=(Jacobian,), do_apply_restrictions=True) elif r == "tsfc": try: # TSFC provides compute_form_data wrapper using correct # kwargs from tsfc.ufl_utils import compute_form_data as tsfc_compute_form_data except ImportError: error("Failed to import tsfc.ufl_utils.compute_form_data when asked " "for tsfc representation.") form_data = tsfc_compute_form_data(form) elif r == "quadrature": # quadrature representation form_data = compute_form_data(form) else: error("Unexpected representation family '%s' for form preprocessing." % r) info("") info(str(form_data)) # Attach integral meta data _attach_integral_metadata(form_data, r, parameters) _validate_representation_choice(form_data, r) return form_data
def _extract_common_quadrature_rule(integral_metadatas): # Check that quadrature rule is the same (To support mixed rules # would be some work since num_points is used to identify # quadrature rules in large parts of the pipeline) quadrature_rules = [md["quadrature_rule"] for md in integral_metadatas] if all_equal(quadrature_rules): qr = quadrature_rules[0] else: qr = "canonical" # FIXME: Shouldn't we raise here? info("Quadrature rule must be equal within each sub domain, using %s rule." % qr) return qr
def _validate_quadrature_schemes_of_elements(quad_schemes, elements): # Update scheme for QuadratureElements if quad_schemes and all_equal(quad_schemes): scheme = quad_schemes[0] else: scheme = "canonical" info("Quadrature rule must be equal within each sub domain, using %s rule." % scheme) for element in elements: if element.family() == "Quadrature": qs = element.quadrature_scheme() if qs != scheme: error("Quadrature element must have specified quadrature scheme (%s) equal to the integral (%s)." % (qs, scheme))
def _extract_common_quadrature_rule(integral_metadatas): # Check that quadrature rule is the same (To support mixed rules # would be some work since num_points is used to identify # quadrature rules in large parts of the pipeline) quadrature_rules = [md["quadrature_rule"] for md in integral_metadatas] if all_equal(quadrature_rules): qr = quadrature_rules[0] else: qr = "canonical" # FIXME: Shouldn't we raise here? info( "Quadrature rule must be equal within each sub domain, using %s rule." % qr) return qr
def compute_integral_ir(itg_data, form_data, form_id, element_numbers, parameters): "Compute intermediate represention of integral." info("Computing uflacs representation") # Initialise representation ir = initialize_integral_ir("uflacs", itg_data, form_data, form_id) # Sort integrals into a dict with quadrature degree and rule as key sorted_integrals = sort_integrals(itg_data.integrals, itg_data.metadata["quadrature_degree"], itg_data.metadata["quadrature_rule"]) # TODO: Might want to create the uflacs ir first and then create the tables we need afterwards! # Tabulate quadrature points and basis function values in these points integrals_dict, psi_tables, quadrature_rules = \ tabulate_basis(sorted_integrals, form_data, itg_data) # Store element numbers, needed for classnames ir["element_numbers"] = element_numbers # Delegate to flacs to build its intermediate representation and add to ir uflacs_ir = compute_uflacs_integral_ir(psi_tables, ir["entitytype"], integrals_dict, form_data, parameters) # Store uflacs generated part separately ir["uflacs"] = uflacs_ir # Create and save the optisation parameters # TODO: Define uflacs specific optimization parameters instead #ir["optimise_parameters"] = parse_optimise_parameters(parameters) # Save tables for quadrature weights and points ir["quadrature_rules"] = quadrature_rules # Create dimensions of primary indices, needed to reset the argument 'A' # given to tabulate_tensor() by the assembler. ir["prim_idims"] = [ create_element(ufl_element).space_dimension() for ufl_element in form_data.argument_elements ] # Added for uflacs, not sure if this is the best way to get this: ir["coeff_idims"] = [ create_element(ufl_element).space_dimension() for ufl_element in form_data.coefficient_elements ] return ir
def generate_code(ir, prefix, parameters): "Generate code from intermediate representation." begin("Compiler stage 4: Generating code") # FIXME: Document option -fconvert_exceptions_to_warnings # FIXME: Remove option epsilon and just rely on precision? # Set code generation parameters # set_float_formatting(int(parameters["precision"])) set_exception_handling(parameters["convert_exceptions_to_warnings"]) # Extract representations ir_elements, ir_dofmaps, ir_integrals, ir_forms = ir # Generate code for elements info("Generating code for %d element(s)" % len(ir_elements)) code_elements = [_generate_element_code(ir, prefix, parameters) for ir in ir_elements] # Generate code for dofmaps info("Generating code for %d dofmap(s)" % len(ir_dofmaps)) code_dofmaps = [_generate_dofmap_code(ir, prefix, parameters) for ir in ir_dofmaps] # Generate code for integrals info("Generating code for integrals") code_integrals = [_generate_integral_code(ir, prefix, parameters) for ir in ir_integrals] # Generate code for forms info("Generating code for forms") code_forms = [_generate_form_code(ir, prefix, parameters) for ir in ir_forms] end() return code_elements, code_dofmaps, code_integrals, code_forms
def compute_ir(analysis, parameters): "Compute intermediate representation." begin("Compiler stage 2: Computing intermediate representation") # Set code generation parameters set_float_formatting(int(parameters["precision"])) # Extract data from analysis form_datas, elements, element_numbers = analysis # Compute representation of elements info("Computing representation of %d elements" % len(elements)) ir_elements = [_compute_element_ir(e, i, element_numbers) \ for (i, e) in enumerate(elements)] # Compute representation of dofmaps info("Computing representation of %d dofmaps" % len(elements)) ir_dofmaps = [_compute_dofmap_ir(e, i, element_numbers) for (i, e) in enumerate(elements)] # Compute and flatten representation of integrals info("Computing representation of integrals") irs = [_compute_integral_ir(fd, i, parameters) \ for (i, fd) in enumerate(form_datas)] ir_integrals = [ir for ir in chain(*irs) if not ir is None] # Compute representation of forms info("Computing representation of forms") ir_forms = [_compute_form_ir(fd, i, element_numbers) \ for (i, fd) in enumerate(form_datas)] end() return ir_elements, ir_dofmaps, ir_integrals, ir_forms
def _extract_common_quadrature_degree(integral_metadatas): # Check that quadrature degree is the same quadrature_degrees = [md["quadrature_degree"] for md in integral_metadatas] for d in quadrature_degrees: if not isinstance(d, int): error("Invalid non-integer quadrature degree %s" % (str(d),)) qd = max(quadrature_degrees) if not all_equal(quadrature_degrees): # FIXME: Shouldn't we raise here? # TODO: This may be loosened up without too much effort, # if the form compiler handles mixed integration degree, # something that most of the pipeline seems to be ready for. info("Quadrature degree must be equal within each sub domain, using degree %d." % qd) return qd
def generate_integral_code(ir, prefix, parameters): "Generate code for integral from intermediate representation." info("Generating code from uflacs representation") # Generate generic ffc code snippets code = initialize_integral_code(ir, prefix, parameters) # Delegate to uflacs to generate tabulate_tensor body import uflacs.backends.ffc ucode = uflacs.backends.ffc.generate_tabulate_tensor_code(ir, parameters) code["tabulate_tensor"] = ucode["tabulate_tensor"] code["additional_includes_set"] = ir.get("additional_includes_set",set()) | set(ucode["additional_includes_set"]) return code
def _transform_integrals_by_type(ir, transformer, integrals_dict, integral_type, cell): num_facets = cell.num_facets() num_vertices = cell.num_vertices() if integral_type == "cell": # Compute transformed integrals. info("Transforming cell integral") transformer.update_cell() terms = _transform_integrals(transformer, integrals_dict, integral_type) elif integral_type == "exterior_facet": # Compute transformed integrals. terms = [None] * num_facets for i in range(num_facets): info("Transforming exterior facet integral %d" % i) transformer.update_facets(i, None) terms[i] = _transform_integrals(transformer, integrals_dict, integral_type) elif integral_type == "interior_facet": # Compute transformed integrals. terms = [[None] * num_facets for i in range(num_facets)] for i in range(num_facets): for j in range(num_facets): info("Transforming interior facet integral (%d, %d)" % (i, j)) transformer.update_facets(i, j) terms[i][j] = _transform_integrals(transformer, integrals_dict, integral_type) elif integral_type == "point": # Compute transformed integrals. terms = [None] * num_vertices for i in range(num_vertices): info("Transforming point integral (%d)" % i) transformer.update_vertex(i) terms[i] = _transform_integrals(transformer, integrals_dict, integral_type) elif integral_type == "custom": # Compute transformed integrale: same as for cell integrals info("Transforming custom integral") transformer.update_cell() terms = _transform_integrals(transformer, integrals_dict, integral_type) else: error("Unhandled domain type: " + str(integral_type)) return terms
def compute_ir(analysis, prefix, parameters, object_names=None): "Compute intermediate representation." begin("Compiler stage 2: Computing intermediate representation") # Set code generation parameters set_float_formatting(int(parameters["precision"])) # Extract data from analysis form_datas, elements, element_numbers, coordinate_elements = analysis # Compute representation of elements if not parameters["format"] == "pyop2": info("Computing representation of %d elements" % len(elements)) ir_elements = [_compute_element_ir(e, prefix, element_numbers) for e in elements] else: ir_elements = [None] # Compute representation of dofmaps if not parameters["format"] == "pyop2": info("Computing representation of %d dofmaps" % len(elements)) ir_dofmaps = [_compute_dofmap_ir(e, prefix, element_numbers) for e in elements] # Compute representation of coordinate mappings info("Computing representation of %d coordinate mappings" % len(coordinate_elements)) ir_compute_coordinate_mappings = [_compute_coordinate_mapping_ir(e, prefix, element_numbers) for e in coordinate_elements] else: ir_dofmaps = [None] ir_compute_coordinate_mappings = [None] # Compute and flatten representation of integrals info("Computing representation of integrals") irs = [_compute_integral_ir(fd, i, prefix, element_numbers, parameters, object_names=object_names) for (i, fd) in enumerate(form_datas)] ir_integrals = [ir for ir in chain(*irs) if not ir is None] # Compute representation of forms if not parameters["format"] == "pyop2": info("Computing representation of forms") ir_forms = [_compute_form_ir(fd, i, prefix, element_numbers) for (i, fd) in enumerate(form_datas)] else: ir_forms = [None] end() return ir_elements, ir_dofmaps, ir_compute_coordinate_mappings, ir_integrals, ir_forms
def compile_element(elements, prefix="Element", parameters=default_parameters()): """This function generates UFC code for a given UFL element or list of UFL elements.""" info("Compiling element %s\n" % prefix) # Reset timing cpu_time_0 = time() # Check input arguments elements = _check_elements(elements) parameters = _check_parameters(parameters) if not elements: return # Stage 1: analysis cpu_time = time() analysis = analyze_elements(elements, parameters) _print_timing(1, time() - cpu_time) # Stage 2: intermediate representation cpu_time = time() ir = compute_ir(analysis, parameters) _print_timing(2, time() - cpu_time) # Stage 3: optimization cpu_time = time() oir = optimize_ir(ir, parameters) _print_timing(3, time() - cpu_time) # Stage 4: code generation cpu_time = time() code = generate_code(oir, prefix, parameters) _print_timing(4, time() - cpu_time) # Stage 4.1: generate wrappers cpu_time = time() object_names = {} wrapper_code = generate_wrapper_code(analysis, prefix, object_names, parameters) _print_timing(4.1, time() - cpu_time) # Stage 5: format code cpu_time = time() format_code(code, wrapper_code, prefix, parameters) _print_timing(5, time() - cpu_time) info_green("FFC finished in %g seconds.", time() - cpu_time_0)
def _transform_integrals_by_type(ir, transformer, integrals_dict, integral_type, cell): num_facets = cell.num_facets() num_vertices = cell.num_vertices() if integral_type == "cell": # Compute transformed integrals. info("Transforming cell integral") transformer.update_cell() terms = _transform_integrals(transformer, integrals_dict, integral_type) elif integral_type == "exterior_facet": # Compute transformed integrals. terms = [None]*num_facets for i in range(num_facets): info("Transforming exterior facet integral %d" % i) transformer.update_facets(i, None) terms[i] = _transform_integrals(transformer, integrals_dict, integral_type) elif integral_type == "interior_facet": # Compute transformed integrals. terms = [[None]*num_facets for i in range(num_facets)] for i in range(num_facets): for j in range(num_facets): info("Transforming interior facet integral (%d, %d)" % (i, j)) transformer.update_facets(i, j) terms[i][j] = _transform_integrals(transformer, integrals_dict, integral_type) elif integral_type == "vertex": # Compute transformed integrals. terms = [None]*num_vertices for i in range(num_vertices): info("Transforming vertex integral (%d)" % i) transformer.update_vertex(i) terms[i] = _transform_integrals(transformer, integrals_dict, integral_type) elif integral_type in custom_integral_types: # Compute transformed integrals: same as for cell integrals info("Transforming custom integral") transformer.update_cell() terms = _transform_integrals(transformer, integrals_dict, integral_type) else: error("Unhandled domain type: " + str(integral_type)) return terms
def optimize_integral_ir(ir, parameters): "Compute optimized intermediate representation of integral." # FIXME: input argument "parameters" has been added to optimize_integral_ir # FIXME: which shadows a local parameter parameters = ir["optimise_parameters"] if parameters["optimisation"]: integrals = ir["trans_integrals"] domain_type = ir["domain_type"] num_facets = ir["num_facets"] num_vertices = ir["num_vertices"] geo_consts = ir["geo_consts"] psi_tables_map = ir["psi_tables_map"] if domain_type == "cell": info("Optimising expressions for cell integral") if parameters["optimisation"] in ("precompute_ip_const", "precompute_basis_const"): _precompute_expressions(integrals, geo_consts, parameters["optimisation"]) else: _simplify_expression(integrals, geo_consts, psi_tables_map) elif domain_type == "exterior_facet": for i in range(num_facets): info("Optimising expressions for facet integral %d" % i) if parameters["optimisation"] in ("precompute_ip_const", "precompute_basis_const"): _precompute_expressions(integrals[i], geo_consts, parameters["optimisation"]) else: _simplify_expression(integrals[i], geo_consts, psi_tables_map) elif domain_type == "interior_facet": for i in range(num_facets): for j in range(num_facets): info("Optimising expressions for facet integral (%d, %d)" % (i, j)) if parameters["optimisation"] in ( "precompute_ip_const", "precompute_basis_const"): _precompute_expressions(integrals[i][j], geo_consts, parameters["optimisation"]) else: _simplify_expression(integrals[i][j], geo_consts, psi_tables_map) elif domain_type == "point": for i in range(num_vertices): info("Optimising expressions for poin integral %d" % i) if parameters["optimisation"] in ("precompute_ip_const", "precompute_basis_const"): _precompute_expressions(integrals[i], geo_consts, parameters["optimisation"]) else: _simplify_expression(integrals[i], geo_consts, psi_tables_map) else: error("Unhandled domain type: " + str(domain_type)) return ir
def compute_integral_ir(integral_data, form_data, form_id, element_numbers, classnames, parameters): "Compute intermediate represention of integral." info("Computing tsfc representation") # Initialise representation ir = initialize_integral_ir("tsfc", integral_data, form_data, form_id) # TSFC treats None and unset differently, so remove None values. parameters = {k: v for k, v in parameters.items() if v is not None} # Delay TSFC compilation ir["compile_integral"] = (integral_data, form_data, None, parameters) return ir
def generate_integral_code(ir, prefix, parameters): "Generate code for integral from intermediate representation." info("Generating code from uflacs representation") # Generate generic ffc code snippets code = initialize_integral_code(ir, prefix, parameters) # Delegate to uflacs to generate tabulate_tensor body import uflacs.backends.ffc ucode = uflacs.backends.ffc.generate_tabulate_tensor_code(ir, parameters) code["tabulate_tensor"] = ucode["tabulate_tensor"] code["additional_includes_set"] = ir.get( "additional_includes_set", set()) | set( ucode["additional_includes_set"]) return code
def _generate_dolfin_wrapper(analysis, prefix, object_names, parameters): begin("Compiler stage 4.1: Generating additional wrapper code") # Encapsulate data (capsules, common_space) = _encapsulate(prefix, object_names, analysis, parameters) # Generate code info("Generating wrapper code for DOLFIN") code = generate_dolfin_code(prefix, "", capsules, common_space, error_control=parameters["error_control"]) code += "\n\n" end() return code
def _extract_common_quadrature_degree(integral_metadatas): # Check that quadrature degree is the same quadrature_degrees = [md["quadrature_degree"] for md in integral_metadatas] for d in quadrature_degrees: if not isinstance(d, int): error("Invalid non-integer quadrature degree %s" % (str(d), )) qd = max(quadrature_degrees) if not all_equal(quadrature_degrees): # FIXME: Shouldn't we raise here? # TODO: This may be loosened up without too much effort, # if the form compiler handles mixed integration degree, # something that most of the pipeline seems to be ready for. info( "Quadrature degree must be equal within each sub domain, using degree %d." % qd) return qd
def _validate_quadrature_schemes_of_elements(quad_schemes, elements): # Update scheme for QuadratureElements if quad_schemes and all_equal(quad_schemes): scheme = quad_schemes[0] else: scheme = "canonical" info( "Quadrature rule must be equal within each sub domain, using %s rule." % scheme) for element in elements: if element.family() == "Quadrature": qs = element.quadrature_scheme() if qs != scheme: error( "Quadrature element must have specified quadrature scheme (%s) equal to the integral (%s)." % (qs, scheme))
def _generate_dolfin_wrapper(analysis, prefix, object_names, parameters): begin("Compiler stage 4.1: Generating additional wrapper code") # Encapsulate data (capsules, common_space) = _encapsulate(prefix, object_names, analysis, parameters) # Generate code info("Generating wrapper code for DOLFIN") code = generate_dolfin_code(prefix, "", capsules, common_space, error_control=parameters["error_control"]) code += "\n\n" end() return code
def generate_code(ir, parameters): "Generate code from intermediate representation." begin("Compiler stage 4: Generating code") full_ir = ir # FIXME: This has global side effects # Set code generation parameters # set_float_formatting(parameters["precision"]) # set_exception_handling(parameters["convert_exceptions_to_warnings"]) # Extract representations ir_finite_elements, ir_dofmaps, ir_coordinate_mappings, ir_integrals, ir_forms = ir # Generate code for finite_elements info("Generating code for %d finite_element(s)" % len(ir_finite_elements)) code_finite_elements = [_generate_finite_element_code(ir, parameters) for ir in ir_finite_elements] # Generate code for dofmaps info("Generating code for %d dofmap(s)" % len(ir_dofmaps)) code_dofmaps = [_generate_dofmap_code(ir, parameters) for ir in ir_dofmaps] # Generate code for coordinate_mappings info("Generating code for %d coordinate_mapping(s)" % len(ir_coordinate_mappings)) code_coordinate_mappings = [_generate_coordinate_mapping_code(ir, parameters) for ir in ir_coordinate_mappings] # Generate code for integrals info("Generating code for integrals") code_integrals = [_generate_integral_code(ir, parameters) for ir in ir_integrals] # Generate code for forms info("Generating code for forms") code_forms = [_generate_form_code(ir, parameters) for ir in ir_forms] # Extract additional includes includes = _extract_includes(full_ir, code_integrals) end() return (code_finite_elements, code_dofmaps, code_coordinate_mappings, code_integrals, code_forms, includes)
def compute_integral_ir(itg_data, form_data, form_id, element_numbers, parameters): "Compute intermediate represention of integral." info("Computing uflacs representation") # Initialise representation ir = initialize_integral_ir("uflacs", itg_data, form_data, form_id) # Sort integrals into a dict with quadrature degree and rule as key sorted_integrals = sort_integrals(itg_data.integrals, itg_data.metadata["quadrature_degree"], itg_data.metadata["quadrature_rule"]) # TODO: Might want to create the uflacs ir first and then create the tables we need afterwards! # Tabulate quadrature points and basis function values in these points integrals_dict, psi_tables, quadrature_rules = \ tabulate_basis(sorted_integrals, form_data, itg_data) # Store element numbers, needed for classnames ir["element_numbers"] = element_numbers # Delegate to flacs to build its intermediate representation and add to ir uflacs_ir = compute_uflacs_integral_ir(psi_tables, ir["entitytype"], integrals_dict, form_data, parameters) # Store uflacs generated part separately ir["uflacs"] = uflacs_ir # Create and save the optisation parameters # TODO: Define uflacs specific optimization parameters instead #ir["optimise_parameters"] = parse_optimise_parameters(parameters) # Save tables for quadrature weights and points ir["quadrature_rules"] = quadrature_rules # Create dimensions of primary indices, needed to reset the argument 'A' # given to tabulate_tensor() by the assembler. ir["prim_idims"] = [create_element(ufl_element).space_dimension() for ufl_element in form_data.argument_elements] # Added for uflacs, not sure if this is the best way to get this: ir["coeff_idims"] = [create_element(ufl_element).space_dimension() for ufl_element in form_data.coefficient_elements] return ir
def compile_form(forms, object_names={}, prefix="Form",\ parameters=default_parameters()): """This function generates UFC code for a given UFL form or list of UFL forms.""" info("Compiling form %s\n" % prefix) # Reset timing cpu_time_0 = time() # Check input arguments forms = _check_forms(forms) parameters = _check_parameters(parameters) if not forms: return # Stage 1: analysis cpu_time = time() analysis = analyze_forms(forms, object_names, parameters) _print_timing(1, time() - cpu_time) # Stage 2: intermediate representation cpu_time = time() ir = compute_ir(analysis, parameters) _print_timing(2, time() - cpu_time) # Stage 3: optimization cpu_time = time() oir = optimize_ir(ir, parameters) _print_timing(3, time() - cpu_time) # Stage 4: code generation cpu_time = time() code = generate_code(oir, prefix, parameters) _print_timing(4, time() - cpu_time) # Stage 4.1: generate wrappers cpu_time = time() wrapper_code = generate_wrapper_code(analysis, prefix, parameters) _print_timing(4.1, time() - cpu_time) # Stage 5: format code cpu_time = time() format_code(code, wrapper_code, prefix, parameters) _print_timing(5, time() - cpu_time) info_green("FFC finished in %g seconds.", time() - cpu_time_0)
def _analyze_form(form, parameters): "Analyze form, returning form data." # Check that form is not empty ffc_assert(not form.empty(), "Form (%s) seems to be zero: cannot compile it." % str(form)) # Compute form metadata form_data = compute_form_data(form) info("") info(str(form_data)) # Attach integral meta data _attach_integral_metadata(form_data, parameters) return form_data
def compute_integral_ir(itg_data, form_data, form_id, parameters): "Compute intermediate represention of integral." info("Computing uflacs representation") # Initialise representation ir = initialize_integral_ir("uflacs", itg_data, form_data, form_id) # Sort integrals into a dict with number of integral points as key sorted_integrals = _sort_integrals(itg_data.integrals, itg_data.metadata, form_data) # Tabulate quadrature points and basis function values in these points integrals_dict, psi_tables, quad_weights = \ _tabulate_basis(sorted_integrals, itg_data.domain_type, form_data) # Save tables for quadrature weights and points ir["quadrature_weights"] = quad_weights # Save tables for basis function values ir["psi_tables"] = psi_tables # Create dimensions of primary indices, needed to reset the argument 'A' # given to tabulate_tensor() by the assembler. ir["prim_idims"] = [ create_element(ufl_element).space_dimension() for ufl_element in form_data.argument_elements ] # Added for uflacs, not sure if this is the best way to get this: ir["coeff_idims"] = [ create_element(ufl_element).space_dimension() for ufl_element in form_data.coefficient_elements ] # Create and save the optisation parameters. ir["optimise_parameters"] = _parse_optimise_parameters(parameters) # Delegate to flacs to build its intermediate representation and add to ir import uflacs.backends.ffc uir = uflacs.backends.ffc.compute_tabulate_tensor_ir( ir, integrals_dict, form_data, parameters) ir.update(uir) return ir
def extract_monomial_form(integrands, function_replace_map): """ Extract monomial representation of form (if possible). When successful, the form is represented as a sum of products of scalar components of basis functions or derivatives of basis functions. If unsuccessful, MonomialException is raised. """ info("Extracting monomial form representation from UFL form") # Iterate over all integrals monomial_form = MonomialForm() for integrand in integrands: # Extract monomial representation if possible monomial_integrand = extract_monomial_integrand(integrand, function_replace_map) monomial_form.append(monomial_integrand) return monomial_form
def _optimize_tensor_contraction(A0, rank): "Compute optimized tensor contraction for given reference tensor." # Select FErari optimization algorithm if rank == 2: optimize = binary.optimize elif rank == 1: optimize = binary.optimize_action else: warning("Tensor optimization only available for rank 1 and 2 tensors, skipping optimizations") return None # Write a message info("Calling FErari to optimize tensor of size %s (%d entries)", " x ".join(str(d) for d in shape(A0)), product(shape(A0)))# # Compute optimized tensor contraction return optimize(A0)
def optimize_integral_ir(ir, parameters): "Compute optimized intermediate representation of integral." # FIXME: input argument "parameters" has been added to optimize_integral_ir # FIXME: which shadows a local parameter # Get integral type and optimization parameters integral_type = ir["integral_type"] parameters = ir["optimise_parameters"] # Check whether we should optimize if parameters["optimisation"]: # Get parameters integrals = ir["trans_integrals"] integral_type = ir["integral_type"] num_facets = ir["num_facets"] num_vertices = ir["num_vertices"] geo_consts = ir["geo_consts"] psi_tables_map = ir["psi_tables_map"] # Optimize based on integral type if integral_type == "cell": info("Optimising expressions for cell integral") if parameters["optimisation"] in ("precompute_ip_const", "precompute_basis_const"): _precompute_expressions(integrals, geo_consts, parameters["optimisation"]) else: _simplify_expression(integrals, geo_consts, psi_tables_map) elif integral_type == "exterior_facet": for i in range(num_facets): info("Optimising expressions for facet integral %d" % i) if parameters["optimisation"] in ("precompute_ip_const", "precompute_basis_const"): _precompute_expressions(integrals[i], geo_consts, parameters["optimisation"]) else: _simplify_expression(integrals[i], geo_consts, psi_tables_map) elif integral_type == "interior_facet": for i in range(num_facets): for j in range(num_facets): info("Optimising expressions for facet integral (%d, %d)" % (i, j)) if parameters["optimisation"] in ("precompute_ip_const", "precompute_basis_const"): _precompute_expressions(integrals[i][j], geo_consts,parameters["optimisation"]) else: _simplify_expression(integrals[i][j], geo_consts, psi_tables_map) elif integral_type == "vertex": for i in range(num_vertices): info("Optimising expressions for poin integral %d" % i) if parameters["optimisation"] in ("precompute_ip_const", "precompute_basis_const"): _precompute_expressions(integrals[i], geo_consts, parameters["optimisation"]) else: _simplify_expression(integrals[i], geo_consts, psi_tables_map) else: error("Unhandled domain type: " + str(integral_type)) return ir
def IntegralMoment(cellname, num_moments, x=None): "Return model for integral moment for given element." info("Plotting dof: integral moment") # Set position if x is None and cellname == "triangle": a = 1.0 / (2 + sqrt(2)) # this was a fun exercise x = (a, a, 0.0) elif x is None: a = 1.0 / (3 + sqrt(3)) # so was this x = (a, a, a) # Make sure point is 3D x = to3d(x) # Fancy scaling of radius and color r = 1.0 / (num_moments + 5) if num_moments % 2 == 0: c = 1.0 else: c = 0.0 # Create separate scene (since we will extract a model, not render) scene = soya.World() # Define material (color) for the sphere material = soya.Material() material.diffuse = (c, c, c, 0.7) # Create sphere sphere = Sphere(scene, material=material) # Scale and moveand move to coordinate sphere.scale(r, r, r) p = sphere.position() p.set_xyz(x[0], x[1], x[2]) sphere.move(p) # Extract model model = scene.to_model() return model
def _analyze_form(form, object_names, parameters): "Analyze form, returning form data." # Check that form is not empty ffc_assert(len(form.integrals()), "Form (%s) seems to be zero: cannot compile it." % str(form)) # Compute form metadata form_data = form.form_data() if form_data is None: form_data = form.compute_form_data(object_names=object_names) info("") info(str(form_data)) # Attach integral meta data _attach_integral_metadata(form_data, parameters) return form_data
def IntegralMoment(cellname, num_moments, x=None): "Return model for integral moment for given element." info("Plotting dof: integral moment") # Set position if x is None and cellname == "triangle": a = 1.0 / (2 + sqrt(2)) # this was a fun exercise x = (a, a, 0.0) elif x is None: a = 1.0 / (3 + sqrt(3)) # so was this x = (a, a, a) # Make sure point is 3D x = to3d(x) # Fancy scaling of radius and color r = 1.0 / (num_moments + 5) if num_moments % 2 == 0: c = 1.0 else: c = 0.0 # Create separate scene (since we will extract a model, not render) scene = soya.World() # Define material (color) for the sphere material = soya.Material() material.diffuse = (c, c, c, 0.7) # Create sphere sphere = Sphere(scene, material=material) # Scale and moveand move to coordinate sphere.scale(r, r, r) p = sphere.position() p.set_xyz(x[0], x[1], x[2]) sphere.move(p) # Extract model model = scene.to_model() return model
def integrate(monomial, domain_type, facet0, facet1, quadrature_degree, quadrature_rule, cellname, facet_cellname): """Compute the reference tensor for a given monomial term of a multilinear form""" info("Precomputing integrals on reference element") # Start timing tic = time.time() # Initialize quadrature points and weights (points, weights) = _init_quadrature(monomial.arguments, domain_type, quadrature_degree, quadrature_rule, cellname, facet_cellname) # Initialize quadrature table for basis functions table = _init_table(monomial.arguments, domain_type, points, facet0, facet1) # Compute table Psi for each factor psis = [_compute_psi(v, table, len(points), domain_type) \ for v in monomial.arguments] # Compute product of all Psis A0 = _compute_product(psis, monomial.float_value * weights) # Report elapsed time and number of entries toc = time.time() - tic num_entries = numpy.prod(numpy.shape(A0)) debug("%d entries computed in %.3g seconds" % (num_entries, toc)) debug("Shape of reference tensor: " + str(numpy.shape(A0))) return A0