def compute_shapes(form: ufl.Form): """Computes the shapes of the cell tensor, coefficient & coordinate arrays for a form""" # Cell tensor elements = tuple(arg.ufl_element() for arg in form.arguments()) fiat_elements = (create_element(element) for element in elements) element_dims = tuple(fe.space_dimension() for fe in fiat_elements) A_shape = element_dims # Coefficient arrays ws_shapes = [] for coefficient in form.coefficients(): w_element = coefficient.ufl_element() w_dim = create_element(w_element).space_dimension() ws_shapes.append((w_dim,)) if len(ws_shapes) > 0: max_w_dim = sorted(ws_shapes, key=lambda w_dim: np.prod(w_dim))[-1] w_full_shape = (len(ws_shapes), ) + max_w_dim else: w_full_shape = (0,) # Coordinate dofs array num_vertices_per_cell = form.ufl_cell().num_vertices() gdim = form.ufl_cell().geometric_dimension() coords_shape = (num_vertices_per_cell, gdim) return A_shape, w_full_shape, coords_shape
def __init__(self, form: ufl.Form, form_compiler_parameters: dict = {}, jit_parameters: dict = {}): """Create dolfinx Form Parameters ---------- form Pure UFL form form_compiler_parameters See :py:func:`ffcx_jit <dolfinx.jit.ffcx_jit>` jit_parameters See :py:func:`ffcx_jit <dolfinx.jit.ffcx_jit>` Note ---- This wrapper for UFL form is responsible for the actual FFCX compilation and attaching coefficients and domains specific data to the underlying C++ Form. """ # Extract subdomain data from UFL form sd = form.subdomain_data() self._subdomains, = list(sd.values()) # Assuming single domain domain, = list(sd.keys()) # Assuming single domain mesh = domain.ufl_cargo() if mesh is None: raise RuntimeError("Expecting to find a Mesh in the form.") # Compile UFL form with JIT ufc_form = jit.ffcx_jit( mesh.mpi_comm(), form, form_compiler_parameters=form_compiler_parameters, jit_parameters=jit_parameters) # For every argument in form extract its function space function_spaces = [ func.ufl_function_space()._cpp_object for func in form.arguments() ] # Prepare coefficients data. For every coefficient in form take # its C++ object. original_coefficients = form.coefficients() coeffs = [original_coefficients[ufc_form.original_coefficient_position( i)]._cpp_object for i in range(ufc_form.num_coefficients)] # Create dictionary of of subdomain markers (possible None for # some dimensions subdomains = {cpp.fem.IntegralType.cell: self._subdomains.get("cell"), cpp.fem.IntegralType.exterior_facet: self._subdomains.get("exterior_facet"), cpp.fem.IntegralType.interior_facet: self._subdomains.get("interior_facet"), cpp.fem.IntegralType.vertex: self._subdomains.get("vertex")} # Prepare dolfinx.cpp.fem.Form and hold it as a member ffi = cffi.FFI() self._cpp_object = cpp.fem.create_form(ffi.cast("uintptr_t", ufc_form), function_spaces, coeffs, [c._cpp_object for c in form.constants()], subdomains, mesh)
def compile_terminal_form(tensor, prefix=None, tsfc_parameters=None, coffee=True): """Compiles the TSFC form associated with a Slate :class:`Tensor` object. This function will return a :class:`ContextKernel` which stores information about the original tensor, integral types and the corresponding TSFC kernels. :arg tensor: A Slate `Tensor`. :arg prefix: An optional `string` indicating the prefix for the subkernel. :arg tsfc_parameters: An optional `dict` of parameters to provide TSFC. Returns: A `ContextKernel` containing all relevant information. """ assert isinstance( tensor, Tensor), ("Only terminal tensors have forms associated with them!") # Sets a default name for the subkernel prefix. # NOTE: the builder will choose a prefix independent of # the tensor name for code idempotency reasons, but is not # strictly required. prefix = prefix or "subkernel%s_" % tensor.__str__() mapper = RemoveRestrictions() integrals = map(partial(map_integrand_dags, mapper), tensor.form.integrals()) transformed_integrals = transform_integrals(integrals) cxt_kernels = [] for orig_it_type, integrals in transformed_integrals.items(): subkernel_prefix = prefix + "%s_to_" % orig_it_type form = Form(integrals) kernels = tsfc_compile(form, subkernel_prefix, parameters=tsfc_parameters, coffee=coffee, split=False) if kernels: cxt_k = ContextKernel(tensor=tensor, coefficients=form.coefficients(), original_integral_type=orig_it_type, tsfc_kernels=kernels) cxt_kernels.append(cxt_k) cxt_kernels = tuple(cxt_kernels) return cxt_kernels
def __init__(self, form: ufl.Form, form_compiler_parameters: dict = None): """Create dolfin Form Parameters ---------- form Pure UFL form form_compiler_parameters Parameters used in JIT FFC compilation of this form Note ---- This wrapper for UFL form is responsible for the actual FFC compilation and attaching coefficients and domains specific data to the underlying C++ Form. """ self.form_compiler_parameters = form_compiler_parameters # Extract subdomain data from UFL form sd = form.subdomain_data() self._subdomains, = list(sd.values()) # Assuming single domain domain, = list(sd.keys()) # Assuming single domain mesh = domain.ufl_cargo() # Compile UFL form with JIT ufc_form = jit.ffc_jit( form, form_compiler_parameters=self.form_compiler_parameters, mpi_comm=mesh.mpi_comm()) # Cast compiled library to pointer to ufc_form ffi = cffi.FFI() ufc_form = fem.dofmap.make_ufc_form(ffi.cast("uintptr_t", ufc_form)) # For every argument in form extract its function space function_spaces = [ func.function_space()._cpp_object for func in form.arguments() ] # Prepare dolfin.Form and hold it as a member self._cpp_object = cpp.fem.create_form(ufc_form, function_spaces) # Need to fill the form with coefficients data # For every coefficient in form take its CPP object original_coefficients = form.coefficients() for i in range(self._cpp_object.num_coefficients()): j = self._cpp_object.original_coefficient_position(i) self._cpp_object.set_coefficient( i, original_coefficients[j]._cpp_object) if mesh is None: raise RuntimeError("Expecting to find a Mesh in the form.") # Attach mesh (because function spaces and coefficients may be # empty lists) if not function_spaces: self._cpp_object.set_mesh(mesh) # Attach subdomains to C++ Form if we have them subdomains = self._subdomains.get("cell") if subdomains: self._cpp_object.set_cell_domains(subdomains) subdomains = self._subdomains.get("exterior_facet") if subdomains: self._cpp_object.set_exterior_facet_domains(subdomains) subdomains = self._subdomains.get("interior_facet") if subdomains: self._cpp_object.set_interior_facet_domains(subdomains) subdomains = self._subdomains.get("vertex") if subdomains: self._cpp_object.set_vertex_domains(subdomains)
def __init__(self, form: ufl.Form, form_compiler_parameters: dict = None): """Create dolfin Form Parameters ---------- form Pure UFL form form_compiler_parameters Parameters used in JIT FFC compilation of this form Note ---- This wrapper for UFL form is responsible for the actual FFC compilation and attaching coefficients and domains specific data to the underlying C++ Form. """ self.form_compiler_parameters = form_compiler_parameters # Add DOLFIN include paths (just the Boost path for special # math functions is really required) # FIXME: move getting include paths to elsewhere if self.form_compiler_parameters is None: self.form_compiler_parameters = { "external_include_dirs": jit.dolfin_pc["include_dirs"] } else: # FIXME: add paths if dict entry already exists self.form_compiler_parameters[ "external_include_dirs"] = jit.dolfin_pc["include_dirs"] # Extract subdomain data from UFL form sd = form.subdomain_data() self._subdomains, = list(sd.values()) # Assuming single domain domain, = list(sd.keys()) # Assuming single domain mesh = domain.ufl_cargo() # Compile UFL form with JIT ufc_form = jit.ffc_jit( form, form_compiler_parameters=self.form_compiler_parameters, mpi_comm=mesh.mpi_comm()) # Cast compiled library to pointer to ufc_form ufc_form = fem.dofmap.make_ufc_form(ufc_form[0]) # For every argument in form extract its function space function_spaces = [ func.function_space()._cpp_object for func in form.arguments() ] # Prepare dolfin.Form and hold it as a member self._cpp_object = cpp.fem.Form(ufc_form, function_spaces) # Need to fill the form with coefficients data # For every coefficient in form take its CPP object original_coefficients = form.coefficients() for i in range(self._cpp_object.num_coefficients()): j = self._cpp_object.original_coefficient_position(i) self._cpp_object.set_coefficient( j, original_coefficients[i]._cpp_object) if mesh is None: raise RuntimeError("Expecting to find a Mesh in the form.") # Attach mesh (because function spaces and coefficients may be # empty lists) if not function_spaces: self._cpp_object.set_mesh(mesh) # Attach subdomains to C++ Form if we have them subdomains = self._subdomains.get("cell") self._cpp_object.set_cell_domains(subdomains) subdomains = self._subdomains.get("exterior_facet") self._cpp_object.set_exterior_facet_domains(subdomains) subdomains = self._subdomains.get("interior_facet") self._cpp_object.set_interior_facet_domains(subdomains) subdomains = self._subdomains.get("vertex") self._cpp_object.set_vertex_domains(subdomains)
def __init__(self, form: ufl.Form, form_compiler_parameters: dict = {}, jit_parameters: dict = {}): """Create dolfinx Form Parameters ---------- form Pure UFL form form_compiler_parameters Parameters used in FFCX compilation of this form. Run `ffcx --help` in the commandline to see all available options. jit_parameters Parameters controlling JIT compilation of C code. Note ---- This wrapper for UFL form is responsible for the actual FFCX compilation and attaching coefficients and domains specific data to the underlying C++ Form. """ # Extract subdomain data from UFL form sd = form.subdomain_data() self._subdomains, = list(sd.values()) # Assuming single domain domain, = list(sd.keys()) # Assuming single domain mesh = domain.ufl_cargo() # Compile UFL form with JIT ufc_form = jit.ffcx_jit( form, form_compiler_parameters=form_compiler_parameters, jit_parameters=jit_parameters, mpi_comm=mesh.mpi_comm()) # For every argument in form extract its function space function_spaces = [ func.ufl_function_space()._cpp_object for func in form.arguments() ] # Prepare dolfinx.Form and hold it as a member ffi = cffi.FFI() self._cpp_object = cpp.fem.create_form(ffi.cast("uintptr_t", ufc_form), function_spaces) # Need to fill the form with coefficients data # For every coefficient in form take its C++ object original_coefficients = form.coefficients() for i in range(self._cpp_object.num_coefficients()): j = self._cpp_object.original_coefficient_position(i) self._cpp_object.set_coefficient( i, original_coefficients[j]._cpp_object) # Constants are set based on their position in original form original_constants = [c._cpp_object for c in form.constants()] self._cpp_object.set_constants(original_constants) if mesh is None: raise RuntimeError("Expecting to find a Mesh in the form.") # Attach mesh (because function spaces and coefficients may be # empty lists) if not function_spaces: self._cpp_object.set_mesh(mesh) # Attach subdomains to C++ Form if we have them subdomains = self._subdomains.get("cell") if subdomains: self._cpp_object.set_cell_domains(subdomains) subdomains = self._subdomains.get("exterior_facet") if subdomains: self._cpp_object.set_exterior_facet_domains(subdomains) subdomains = self._subdomains.get("interior_facet") if subdomains: self._cpp_object.set_interior_facet_domains(subdomains) subdomains = self._subdomains.get("vertex") if subdomains: self._cpp_object.set_vertex_domains(subdomains)