def local_facet_dat(self): """Dat indicating which local facet of each adjacent cell corresponds to the current facet.""" return op2.Dat( op2.DataSet(self.set, self._rank), self.local_facet_number, np.uintc, "%s_%s_local_facet_number" % (self.mesh.name, self.kind))
def __init__(self, mesh, element, name=None, real_tensorproduct=False): super(FunctionSpace, self).__init__() if type(element) is ufl.MixedElement: raise ValueError("Can't create FunctionSpace for MixedElement") finat_element = create_element(element) if isinstance(finat_element, finat.TensorFiniteElement): # Retrieve scalar element finat_element = finat_element.base_element # Used for reconstruction of mixed/component spaces self.real_tensorproduct = real_tensorproduct sdata = get_shared_data(mesh, finat_element, real_tensorproduct=real_tensorproduct) # The function space shape is the number of dofs per node, # hence it is not always the value_shape. Vector and Tensor # element modifiers *must* live on the outside! if type(element) is ufl.TensorElement: # UFL enforces value_shape of the subelement to be empty # on a TensorElement. self.shape = element.value_shape() elif type(element) is ufl.VectorElement: # First dimension of the value_shape is the VectorElement # shape. self.shape = element.value_shape()[:1] else: self.shape = () self._ufl_function_space = ufl.FunctionSpace(mesh.ufl_mesh(), element) self._shared_data = sdata self._mesh = mesh self.rank = len(self.shape) r"""The rank of this :class:`FunctionSpace`. Spaces where the element is scalar-valued (or intrinsically vector-valued) have rank zero. Spaces built on :class:`~ufl.classes.VectorElement` or :class:`~ufl.classes.TensorElement` instances have rank equivalent to the number of components of their :meth:`~ufl.classes.FiniteElementBase.value_shape`.""" self.value_size = int(numpy.prod(self.shape, dtype=int)) r"""The total number of degrees of freedom at each function space node.""" self.name = name r"""The (optional) descriptive name for this space.""" self.node_set = sdata.node_set r"""A :class:`pyop2.Set` representing the function space nodes.""" self.dof_dset = op2.DataSet(self.node_set, self.shape or 1, name="%s_nodes_dset" % self.name) r"""A :class:`pyop2.DataSet` representing the function space degrees of freedom.""" self.comm = self.node_set.comm self.finat_element = finat_element self.extruded = sdata.extruded self.offset = sdata.offset self.cell_boundary_masks = sdata.cell_boundary_masks self.interior_facet_boundary_masks = sdata.interior_facet_boundary_masks
def __init__(self, mesh, element, name=None): super(FunctionSpace, self).__init__() if type(element) is ufl.MixedElement: raise ValueError("Can't create FunctionSpace for MixedElement") sdata = get_shared_data(mesh, element) # The function space shape is the number of dofs per node, # hence it is not always the value_shape. Vector and Tensor # element modifiers *must* live on the outside! if type(element) in {ufl.TensorElement, ufl.VectorElement}: # The number of "free" dofs is given by reference_value_shape, # not value_shape due to symmetry specifications rvs = element.reference_value_shape() # This requires that the sub element is not itself a # tensor element (which is checked by the top level # constructor of function spaces) sub = element.sub_elements()[0].value_shape() self.shape = rvs[:len(rvs) - len(sub)] else: self.shape = () self._ufl_function_space = ufl.FunctionSpace(mesh.ufl_mesh(), element) self._shared_data = sdata self._mesh = mesh self.rank = len(self.shape) r"""The rank of this :class:`FunctionSpace`. Spaces where the element is scalar-valued (or intrinsically vector-valued) have rank zero. Spaces built on :class:`~ufl.classes.VectorElement` or :class:`~ufl.classes.TensorElement` instances have rank equivalent to the number of components of their :meth:`~ufl.classes.FiniteElementBase.value_shape`.""" self.value_size = int(numpy.prod(self.shape, dtype=int)) r"""The total number of degrees of freedom at each function space node.""" self.name = name r"""The (optional) descriptive name for this space.""" self.node_set = sdata.node_set r"""A :class:`pyop2.Set` representing the function space nodes.""" self.dof_dset = op2.DataSet(self.node_set, self.shape or 1, name="%s_nodes_dset" % self.name) r"""A :class:`pyop2.DataSet` representing the function space degrees of freedom.""" self.comm = self.node_set.comm # Need to create finat element again as sdata does not # want to carry finat_element. self.finat_element = create_element(element) # Used for reconstruction of mixed/component spaces. # sdata carries real_tensorproduct. self.real_tensorproduct = sdata.real_tensorproduct self.extruded = sdata.extruded self.offset = sdata.offset self.cell_boundary_masks = sdata.cell_boundary_masks self.interior_facet_boundary_masks = sdata.interior_facet_boundary_masks
def matrix_funptr(form): from firedrake.tsfc_interface import compile_form test, trial = map(operator.methodcaller("function_space"), form.arguments()) if test != trial: raise NotImplementedError("Only for matching test and trial spaces") kernel, = compile_form(form, "subspace_form", split=False) kinfo = kernel.kinfo if kinfo.subdomain_id != "otherwise": raise NotImplementedError("Only for full domain integrals") if kinfo.integral_type != "cell": raise NotImplementedError("Only for cell integrals") # OK, now we've validated the kernel, let's build the callback args = [] toset = op2.Set(1, comm=test.comm) dofset = op2.DataSet(toset, 1) arity = sum(m.arity * s.cdim for m, s in zip(test.cell_node_map(), test.dof_dset)) iterset = test.cell_node_map().iterset cell_node_map = op2.Map(iterset, toset, arity, values=numpy.zeros(iterset.total_size * arity, dtype=IntType)) mat = DenseMat(dofset) arg = mat(op2.INC, (cell_node_map[op2.i[0]], cell_node_map[op2.i[1]])) arg.position = 0 args.append(arg) mesh = form.ufl_domains()[kinfo.domain_number] arg = mesh.coordinates.dat(op2.READ, mesh.coordinates.cell_node_map()[op2.i[0]]) arg.position = 1 args.append(arg) for n in kinfo.coefficient_map: c = form.coefficients()[n] for (i, c_) in enumerate(c.split()): map_ = c_.cell_node_map() if map_ is not None: map_ = map_[op2.i[0]] arg = c_.dat(op2.READ, map_) arg.position = len(args) args.append(arg) iterset = op2.Subset(mesh.cell_set, [0]) mod = JITModule(kinfo.kernel, iterset, *args) return mod._fun, kinfo
def dvnodes(nodes): return op2.DataSet(nodes, 2, "dvnodes")
def residual_funptr(form, state): from firedrake.tsfc_interface import compile_form test, = map(operator.methodcaller("function_space"), form.arguments()) if state.function_space() != test: raise NotImplementedError( "State and test space must be dual to one-another") if state is not None: interface = make_builder(dont_split=(state, )) else: interface = None kernel, = compile_form(form, "subspace_form", split=False, interface=interface) kinfo = kernel.kinfo if kinfo.subdomain_id != "otherwise": raise NotImplementedError("Only for full domain integrals") if kinfo.integral_type != "cell": raise NotImplementedError("Only for cell integrals") args = [] toset = op2.Set(1, comm=test.comm) dofset = op2.DataSet(toset, 1) arity = sum(m.arity * s.cdim for m, s in zip(test.cell_node_map(), test.dof_dset)) iterset = test.cell_node_map().iterset cell_node_map = op2.Map(iterset, toset, arity, values=numpy.zeros(iterset.total_size * arity, dtype=IntType)) dat = DenseDat(dofset) statedat = DenseDat(dofset) statearg = statedat(op2.READ, cell_node_map[op2.i[0]]) arg = dat(op2.INC, cell_node_map[op2.i[0]]) arg.position = 0 args.append(arg) mesh = form.ufl_domains()[kinfo.domain_number] arg = mesh.coordinates.dat(op2.READ, mesh.coordinates.cell_node_map()[op2.i[0]]) arg.position = 1 args.append(arg) for n in kinfo.coefficient_map: c = form.coefficients()[n] if c is state: statearg.position = len(args) args.append(statearg) continue for (i, c_) in enumerate(c.split()): map_ = c_.cell_node_map() if map_ is not None: map_ = map_[op2.i[0]] arg = c_.dat(op2.READ, map_) arg.position = len(args) args.append(arg) iterset = op2.Subset(mesh.cell_set, [0]) mod = JITModule(kinfo.kernel, iterset, *args) return mod._fun, kinfo
def dindset2(indset): return op2.DataSet(indset, 2, "dindset2")
def diterset(iterset): return op2.DataSet(iterset, 1, "diterset")
def delems2(elems): return op2.DataSet(elems, 2, "delems2")
def dset(cls, set): return op2.DataSet(set, 1, 'set')
def dele2(ele): return op2.DataSet(ele, 2, 'dele2')
def dele(ele): return op2.DataSet(ele, 1, 'dele')
def dnode2(node): return op2.DataSet(node, 2, 'dnode2')
def dnode(node): return op2.DataSet(node, 1, 'dnode')
def dtoset(cls, toset): return op2.DataSet(toset, 1, 'dtoset')
def xtr_dvnodes(xtr_nodes): return op2.DataSet(xtr_nodes, 3, "xtr_dvnodes")
def test_extruded_assemble_mat_rhs_solve(self, backend, xtr_mat, xtr_coords, xtr_elements, xtr_elem_node, extrusion_kernel, xtr_nodes, vol_comp, xtr_dnodes, vol_comp_rhs, xtr_b): coords_dim = 3 coords_xtr_dim = 3 # dimension # BIG TRICK HERE: # We need the +1 in order to include the entire column of vertices. # Extrusion is meant to iterate over the 3D cells which are layer - 1 in number. # The +1 correction helps in the case of iteration over vertices which need # one extra layer. iterset = op2.Set(NUM_NODES, "verts1") iterset = op2.ExtrudedSet(iterset, layers=(layers + 1)) vnodes = op2.DataSet(iterset, coords_dim) d_nodes_xtr = op2.DataSet(xtr_nodes, coords_xtr_dim) d_lnodes_xtr = op2.DataSet(xtr_nodes, 1) # Create an op2.Dat with the base mesh coordinates coords_vec = numpy.zeros(vnodes.total_size * coords_dim) length = len(xtr_coords.flatten()) coords_vec[0:length] = xtr_coords.flatten() coords = op2.Dat(vnodes, coords_vec, numpy.float64, "dat1") # Create an op2.Dat with slots for the extruded coordinates coords_new = numpy.array([0.] * layers * NUM_NODES * coords_xtr_dim, dtype=numpy.float64) coords_xtr = op2.Dat(d_nodes_xtr, coords_new, numpy.float64, "dat_xtr") # Creat an op2.Dat to hold the layer number layer_vec = numpy.tile(numpy.arange(0, layers), NUM_NODES) layer = op2.Dat(d_lnodes_xtr, layer_vec, numpy.int32, "dat_layer") # Map a map for the bottom of the mesh. vertex_to_coords = [i for i in range(0, NUM_NODES)] v2coords_offset = numpy.array([0], numpy.int32) map_2d = op2.Map(iterset, iterset, 1, vertex_to_coords, "v2coords", v2coords_offset) # Create Map for extruded vertices vertex_to_xtr_coords = [layers * i for i in range(0, NUM_NODES)] v2xtr_coords_offset = numpy.array([1], numpy.int32) map_xtr = op2.Map(iterset, xtr_nodes, 1, vertex_to_xtr_coords, "v2xtr_coords", v2xtr_coords_offset) # Create Map for layer number v2xtr_layer_offset = numpy.array([1], numpy.int32) layer_xtr = op2.Map(iterset, xtr_nodes, 1, vertex_to_xtr_coords, "v2xtr_layer", v2xtr_layer_offset) op2.par_loop(extrusion_kernel, iterset, coords_xtr(op2.INC, map_xtr, flatten=True), coords(op2.READ, map_2d, flatten=True), layer(op2.READ, layer_xtr)) # Assemble the main matrix. op2.par_loop( vol_comp, xtr_elements, xtr_mat(op2.INC, (xtr_elem_node[op2.i[0]], xtr_elem_node[op2.i[1]])), coords_xtr(op2.READ, xtr_elem_node)) eps = 1.e-5 xtr_mat.assemble() assert_allclose(sum(sum(xtr_mat.values)), 36.0, eps) # Assemble the RHS xtr_f_vals = numpy.array([1] * NUM_NODES * layers, dtype=numpy.int32) xtr_f = op2.Dat(d_lnodes_xtr, xtr_f_vals, numpy.int32, "xtr_f") op2.par_loop(vol_comp_rhs, xtr_elements, xtr_b(op2.INC, xtr_elem_node[op2.i[0]], flatten=True), coords_xtr(op2.READ, xtr_elem_node, flatten=True), xtr_f(op2.READ, xtr_elem_node)) assert_allclose(sum(xtr_b.data), 6.0, eps) x_vals = numpy.zeros(NUM_NODES * layers, dtype=valuetype) xtr_x = op2.Dat(d_lnodes_xtr, x_vals, valuetype, "xtr_x") op2.solve(xtr_mat, xtr_x, xtr_b) assert_allclose(sum(xtr_x.data), 7.3333333, eps)
def dset2(cls, set): return op2.DataSet(set, 2, 'set2')
def delems(elems): return op2.DataSet(elems, 1, "delems")
def dnode_set1(node_set1): return op2.DataSet(node_set1, 1, "dnodes1")
def ds2(cls, s2): return op2.DataSet(s2, 1)
def dnode_set2(node_set1): return op2.DataSet(node_set1, 2, "dnodes2")
def dindset(indset): return op2.DataSet(indset, 1, "dindset")
def dedge_set1(edge_set1): return op2.DataSet(edge_set1, 1, "dedges1")
def matrix_funptr(form, state): from firedrake.tsfc_interface import compile_form test, trial = map(operator.methodcaller("function_space"), form.arguments()) if test != trial: raise NotImplementedError("Only for matching test and trial spaces") if state is not None: interface = make_builder(dont_split=(state, )) else: interface = None kernels = compile_form(form, "subspace_form", split=False, interface=interface) cell_kernels = [] int_facet_kernels = [] for kernel in kernels: kinfo = kernel.kinfo if kinfo.subdomain_id != "otherwise": raise NotImplementedError("Only for full domain integrals") if kinfo.integral_type not in {"cell", "interior_facet"}: raise NotImplementedError( "Only for cell or interior facet integrals") # OK, now we've validated the kernel, let's build the callback args = [] if kinfo.integral_type == "cell": get_map = operator.methodcaller("cell_node_map") kernels = cell_kernels elif kinfo.integral_type == "interior_facet": get_map = operator.methodcaller("interior_facet_node_map") kernels = int_facet_kernels else: get_map = None toset = op2.Set(1, comm=test.comm) dofset = op2.DataSet(toset, 1) arity = sum(m.arity * s.cdim for m, s in zip(get_map(test), test.dof_dset)) iterset = get_map(test).iterset entity_node_map = op2.Map(iterset, toset, arity, values=numpy.zeros(iterset.total_size * arity, dtype=IntType)) mat = LocalMat(dofset) arg = mat(op2.INC, (entity_node_map, entity_node_map)) arg.position = 0 args.append(arg) statedat = LocalDat(dofset) state_entity_node_map = op2.Map(iterset, toset, arity, values=numpy.zeros(iterset.total_size * arity, dtype=IntType)) statearg = statedat(op2.READ, state_entity_node_map) mesh = form.ufl_domains()[kinfo.domain_number] arg = mesh.coordinates.dat(op2.READ, get_map(mesh.coordinates)) arg.position = 1 args.append(arg) if kinfo.oriented: c = form.ufl_domain().cell_orientations() arg = c.dat(op2.READ, get_map(c)) arg.position = len(args) args.append(arg) if kinfo.needs_cell_sizes: c = form.ufl_domain().cell_sizes arg = c.dat(op2.READ, get_map(c)) arg.position = len(args) args.append(arg) for n in kinfo.coefficient_map: c = form.coefficients()[n] if c is state: statearg.position = len(args) args.append(statearg) continue for (i, c_) in enumerate(c.split()): map_ = get_map(c_) arg = c_.dat(op2.READ, map_) arg.position = len(args) args.append(arg) if kinfo.integral_type == "interior_facet": arg = test.ufl_domain().interior_facets.local_facet_dat(op2.READ) arg.position = len(args) args.append(arg) iterset = op2.Subset(iterset, [0]) mod = seq.JITModule(kinfo.kernel, iterset, *args) kernels.append(CompiledKernel(mod._fun, kinfo)) return cell_kernels, int_facet_kernels
def delem_set1(elem_set1): return op2.DataSet(elem_set1, 1, "delems1")
def dnodes(nodes): return op2.DataSet(nodes, 1, "dnodes")
def delems_set2(elem_set1): return op2.DataSet(elem_set1, 2, "delems2")
def delements(elements): return op2.DataSet(elements, 1, "delements")
def xtr_dnodes(xtr_nodes): return op2.DataSet(xtr_nodes, 1, "xtr_dnodes")