def __init__(self, mesh, elem, mapping, intorder: Optional[int] = None, side: int = 0): super(MortarBasis, self).__init__(mesh, elem, mapping, intorder) self.ib1 = InteriorBasis(mesh.mesh1, elem) self.ib2 = InteriorBasis(mesh.mesh2, elem) self.X, self.W = get_quadrature(self.brefdom, self.intorder) self.find = np.nonzero(self.mesh.f2t[1, :] != -1)[0] self.tind = self.mesh.f2t[side, self.find] # boundary refdom to global facet x = self.mapping.G(self.X, find=self.find) # global facet to refdom facet Y = self.mapping.invF(x, tind=self.tind) self.normals = np.repeat(mesh.normals[:, :, None], len(self.W), axis=2) self.nelems = len(self.find) self.basis = [self.elem.gbasis(self.mapping, Y, j, self.tind) for j in range(self.Nbfun)] self.dx = np.abs(self.mapping.detDG(self.X, find=self.find)) * np.tile(self.W, (self.nelems, 1)) if side == 0: self.element_dofs = self.ib1.element_dofs[:, self.tind] elif side == 1: self.element_dofs = self.ib2.element_dofs[:, self.tind - mesh.mesh1.t.shape[1]] + self.ib1.N self.N = self.ib1.N + self.ib2.N
def __init__(self, mesh, elem, mapping=None, intorder=None, side=None, dofnum=None): super(FacetBasis, self).__init__(mesh, elem, mapping, intorder) if dofnum is not None: self.dofnum = dofnum self.Nbfun = self.dofnum.t_dof.shape[0] self.X, self.W = get_quadrature(self.brefdom, self.intorder) # triangles where the basis is evaluated if side is None: self.find = np.nonzero(self.mesh.f2t[1, :] == -1)[0] self.tind = self.mesh.f2t[0, self.find] elif side == 0 or side == 1: self.find = np.nonzero(self.mesh.f2t[1, :] != -1)[0] self.tind = self.mesh.f2t[side, self.find] else: raise Exception( "Parameter side must be 0 or 1. Facet shares only two elements." ) # boundary refdom to global facet x = self.mapping.G(self.X, find=self.find) # global facet to refdom facet Y = self.mapping.invF(x, tind=self.tind) if hasattr(mesh, 'normals'): self.normals = np.repeat(mesh.normals[:, :, None], len(self.W), axis=2) else: # construct normal vectors from side=0 always Y0 = self.mapping.invF(x, tind=self.mesh.f2t[ 0, self.find]) # TODO check why without this works also (Y0 = Y) self.normals = self.mapping.normals(Y0, self.mesh.f2t[0, self.find], self.find, self.mesh.t2f) self.nf = len(self.find) self.basis = list( zip(*[ self.elem.gbasis(self.mapping, Y, j, self.tind) for j in range(self.Nbfun) ])) self.nelems = self.nf self.dx = np.abs(self.mapping.detDG(self.X, find=self.find)) * np.tile( self.W, (self.nelems, 1)) self.dofnum.t_dof = self.dofnum.t_dof[:, self. tind] # TODO this is required for asm(). Check for other options.
def __init__(self, mesh: Mesh, elem: Element, mapping: Mapping = None, intorder: int = None, elements: ndarray = None, quadrature: Tuple[ndarray, ndarray] = None): """Combine :class:`~skfem.mesh.Mesh` and :class:`~skfem.element.Element` into a set of precomputed global basis functions. Parameters ---------- mesh An object of type :class:`~skfem.mesh.Mesh`. elem An object of type :class:`~skfem.element.Element`. mapping An object of type :class:`skfem.mapping.Mapping`. If `None`, uses `mesh.mapping`. intorder Optional integration order, i.e. the degree of polynomials that are integrated exactly by the used quadrature. Not used if `quadrature` is specified. elements Optional subset of element indices. quadrature Optional tuple of quadrature points and weights. """ super(InteriorBasis, self).__init__(mesh, elem, mapping) if quadrature is not None: self.X, self.W = quadrature else: self.X, self.W = get_quadrature( self.refdom, intorder if intorder is not None else 2 * self.elem.maxdeg) self.basis = [ self.elem.gbasis(self.mapping, self.X, j, tind=elements) for j in range(self.Nbfun) ] if elements is None: self.nelems = self.mesh.t.shape[1] self.tind = np.arange(self.nelems, dtype=np.int64) else: self.nelems = len(elements) self.tind = elements self.dx = (np.abs(self.mapping.detDF(self.X, tind=elements)) * np.tile(self.W, (self.nelems, 1))) self.element_dofs = self.element_dofs[:, self.tind]
def __init__(self, mesh, elem, mapping=None, intorder=None): super(InteriorBasis, self).__init__(mesh, elem, mapping, intorder) self.X, self.W = get_quadrature(self.refdom, self.intorder) self.basis = list( zip(*[ self.elem.gbasis(self.mapping, self.X, j) for j in range(self.Nbfun) ])) self.nelems = self.nt self.dx = np.abs(self.mapping.detDF(self.X)) * np.tile( self.W, (self.nelems, 1))
def __init__(self, mesh: Mesh, elem: Element, mapping: Optional[Mapping] = None, intorder: Optional[int] = None): super(InteriorBasis, self).__init__(mesh, elem, mapping, intorder) self.X, self.W = get_quadrature(self.refdom, self.intorder) self.basis = [ self.elem.gbasis(self.mapping, self.X, j) for j in range(self.Nbfun) ] self.nelems = self.mesh.t.shape[1] self.dx = np.abs(self.mapping.detDF(self.X)) * np.tile( self.W, (self.nelems, 1))
def __init__(self, mesh: Mesh, elem: Element, mapping: Optional[Mapping] = None, intorder: Optional[int] = None, elements: Optional[ndarray] = None): """Combine :class:`~skfem.mesh.Mesh` and :class:`~skfem.element.Element` into a set of precomputed global basis functions. Parameters ---------- mesh An object of type :class:`~skfem.mesh.Mesh`. elem An object of type :class:`~skfem.element.Element`. mapping An object of type :class:`~skfem.mapping.Mapping`. intorder Optional integration order, i.e. the degree of polynomials that are integrated exactly by the used quadrature. elements Optional subset of element indices. """ super(InteriorBasis, self).__init__(mesh, elem, mapping, intorder) self.X, self.W = get_quadrature(self.refdom, self.intorder) self.basis = [ self.elem.gbasis(self.mapping, self.X, j, tind=elements) for j in range(self.Nbfun) ] if elements is None: self.nelems = self.mesh.t.shape[1] self.tind = np.arange(self.nelems, dtype=np.int64) else: self.nelems = len(elements) self.tind = elements self.dx = (np.abs(self.mapping.detDF(self.X, tind=elements)) * np.tile(self.W, (self.nelems, 1))) self.element_dofs = self.element_dofs[:, self.tind]
def __init__(self, mesh: Mesh, elem: Element, mapping: Optional[Mapping] = None, intorder: Optional[int] = None, quadrature: Optional[Tuple[ndarray, ndarray]] = None, refdom: Type[Refdom] = Refdom, dofs: Optional[Dofs] = None): if mesh.refdom != elem.refdom: raise ValueError("Incompatible Mesh and Element.") self.mapping = mesh._mapping() if mapping is None else mapping self.dofs = Dofs(mesh, elem) if dofs is None else dofs # global degree-of-freedom location try: doflocs = self.mapping.F(elem.doflocs.T) self.doflocs = np.zeros((doflocs.shape[0], self.N)) # match mapped dofs and global dof numbering for itr in range(doflocs.shape[0]): for jtr in range(self.dofs.element_dofs.shape[0]): self.doflocs[itr, self.dofs.element_dofs[jtr]] =\ doflocs[itr, :, jtr] except Exception: logger.warning("Unable to calculate global DOF locations.") self.mesh = mesh self.elem = elem self.Nbfun = self.dofs.element_dofs.shape[0] self.nelems = 0 # subclasses should overwrite if quadrature is not None: self.X, self.W = quadrature else: self.X, self.W = get_quadrature( refdom, intorder if intorder is not None else 2 * self.elem.maxdeg )
def __init__(self, mesh, elem, mapping=None, intorder: int = None, side: int = None, facets: ndarray = None, quadrature: Tuple[ndarray, ndarray] = None): """Combine :class:`~skfem.mesh.Mesh` and :class:`~skfem.element.Element` into a set of precomputed global basis functions at element facets. Parameters ---------- mesh An object of type :class:`~skfem.mesh.Mesh`. elem An object of type :class:`~skfem.element.Element`. mapping An object of type :class:`skfem.mapping.Mapping`. If `None`, uses `mesh.mapping`. intorder Optional integration order, i.e. the degree of polynomials that are integrated exactly by the used quadrature. Not used if `quadrature` is specified. side If 0 or 1, basis functions are evaluated on the interior facets. The numbers 0 and 1 refer to the different sides of the facets. Side 0 corresponds to the indices `mesh.f2t[0]`. If `None`, basis is evaluated only on the exterior facets. facets Optional subset of facet indices. quadrature Optional tuple of quadrature points and weights. """ super(FacetBasis, self).__init__(mesh, elem, mapping) if quadrature is not None: self.X, self.W = quadrature else: self.X, self.W = get_quadrature( self.brefdom, intorder if intorder is not None else 2 * self.elem.maxdeg) # facets where the basis is evaluated if facets is None: if side is None: self.find = np.nonzero(self.mesh.f2t[1] == -1)[0] self.tind = self.mesh.f2t[0, self.find] elif hasattr(self.mapping, 'helper_to_orig') and side in [0, 1]: self.mapping.side = side self.find = self.mapping.helper_to_orig[side] self.tind = self.mesh.f2t[0, self.find] elif side in [0, 1]: self.find = np.nonzero(self.mesh.f2t[1] != -1)[0] self.tind = self.mesh.f2t[side, self.find] else: raise Exception("Parameter 'side' must be either 0 or 1. " "A facet shares only two elements.") else: self.find = facets self.tind = self.mesh.f2t[0, self.find] # boundary refdom to global facet x = self.mapping.G(self.X, find=self.find) # global facet to refdom facet Y = self.mapping.invF(x, tind=self.tind) # construct normal vectors from side=0 always Y0 = self.mapping.invF(x, tind=self.mesh.f2t[0, self.find]) self.normals = DiscreteField(value=self.mapping.normals( Y0, self.mesh.f2t[0, self.find], self.find, self.mesh.t2f)) self.nelems = len(self.find) self.basis = [ self.elem.gbasis(self.mapping, Y, j, tind=self.tind) for j in range(self.Nbfun) ] self.dx = (np.abs(self.mapping.detDG(self.X, find=self.find)) * np.tile(self.W, (self.nelems, 1)))
def __init__(self, mesh, elem, mapping=None, intorder: Optional[int] = None, side: Optional[int] = None, facets: Optional[ndarray] = None): """Combine :class:`~skfem.mesh.Mesh` and :class:`~skfem.element.Element` into a set of precomputed global basis functions at element facets. Parameters ---------- mesh An object of type :class:`~skfem.mesh.Mesh`. elem An object of type :class:`~skfem.element.Element`. mapping An object of type :class:`~skfem.mapping.Mapping`. intorder Optional integration order, i.e. the degree of polynomials that are integrated exactly by the used quadrature. side If 0 or 1, the basis functions are evaluated on the interior facets. The numbers 0 and 1 refer to the different sides of the facets. Side 0 corresponds to the indices mesh.f2t[0, :]. facets Optional subset of facet indices. """ super(FacetBasis, self).__init__(mesh, elem, mapping, intorder) self.X, self.W = get_quadrature(self.brefdom, self.intorder) # facets where the basis is evaluated if facets is None: if side is None: self.find = np.nonzero(self.mesh.f2t[1, :] == -1)[0] self.tind = self.mesh.f2t[0, self.find] elif side == 0 or side == 1: self.find = np.nonzero(self.mesh.f2t[1, :] != -1)[0] self.tind = self.mesh.f2t[side, self.find] else: raise Exception("Parameter 'side' must be either 0 or 1. " "A facet shares only two elements.") else: self.find = facets self.tind = self.mesh.f2t[0, self.find] # boundary refdom to global facet x = self.mapping.G(self.X, find=self.find) # global facet to refdom facet Y = self.mapping.invF(x, tind=self.tind) if hasattr(mesh, 'normals'): self.normals = np.repeat(mesh.normals[:, :, None], len(self.W), axis=2) else: # construct normal vectors from side=0 always Y0 = self.mapping.invF(x, tind=self.mesh.f2t[0, self.find]) self.normals = self.mapping.normals(Y0, self.mesh.f2t[0, self.find], self.find, self.mesh.t2f) self.nelems = len(self.find) self.basis = [ self.elem.gbasis(self.mapping, Y, j, self.tind) for j in range(self.Nbfun) ] self.dx = np.abs(self.mapping.detDG(self.X, find=self.find)) *\ np.tile(self.W, (self.nelems, 1)) self.element_dofs = self.element_dofs[:, self.tind]