def test_contains_l2(): l2_elements = [ FiniteElement("Real", triangle, 0), FiniteElement("DG", triangle, 0), FiniteElement("DG", triangle, 1), FiniteElement("DG", triangle, 2), FiniteElement("CR", triangle, 1), # Tensor product elements: TensorProductElement(FiniteElement("DG", interval, 1), FiniteElement("DG", interval, 1)), TensorProductElement(FiniteElement("DG", interval, 1), FiniteElement("CG", interval, 2)), # Enriched element: EnrichedElement(FiniteElement("DG", triangle, 1), FiniteElement("B", triangle, 3)) ] for l2_element in l2_elements: assert l2_element in L2 assert l2_element in H0dx0dy assert l2_element not in H1 assert l2_element not in H1dx1dy assert l2_element not in HCurl assert l2_element not in HDiv assert l2_element not in H2 assert l2_element not in H2dx2dy
def test_contains_h1(): h1_elements = [ # Standard Lagrange elements: FiniteElement("CG", triangle, 1), FiniteElement("CG", triangle, 2), # Some special elements: FiniteElement("AW", triangle), FiniteElement("HER", triangle), FiniteElement("MTW", triangle), # Tensor product elements: TensorProductElement(FiniteElement("CG", interval, 1), FiniteElement("CG", interval, 1)), TensorProductElement(FiniteElement("CG", interval, 2), FiniteElement("CG", interval, 2)), # Enriched elements: EnrichedElement(FiniteElement("CG", triangle, 2), FiniteElement("B", triangle, 3)) ] for h1_element in h1_elements: assert h1_element in H1 assert h1_element in H1dx1dy assert h1_element in HDiv assert h1_element in HCurl assert h1_element in L2 assert h1_element in H0dx0dy assert h1_element not in H2 assert h1_element not in H2dx2dy
def test_contains_hdiv(): hdiv_elements = [ FiniteElement("RT", triangle, 1), FiniteElement("BDM", triangle, 1), FiniteElement("BDFM", triangle, 2), # HDiv elements: HDiv( TensorProductElement(FiniteElement("DG", triangle, 1), FiniteElement("CG", interval, 2))), HDiv( TensorProductElement(FiniteElement("RT", triangle, 1), FiniteElement("DG", interval, 1))), HDiv( TensorProductElement(FiniteElement("N1curl", triangle, 1), FiniteElement("DG", interval, 1))) ] for hdiv_element in hdiv_elements: assert hdiv_element in HDiv assert hdiv_element in L2 assert hdiv_element in H0dx0dy assert hdiv_element not in H1 assert hdiv_element not in H1dx1dy assert hdiv_element not in HCurl assert hdiv_element not in H2 assert hdiv_element not in H2dx2dy
def get_plotting_spaces(mesh, nquadplot, nquadplot_v=None): nquadplot_v = nquadplot_v or nquadplot if mesh.ndim == 1: scalarelem = FiniteElement("DG", interval, nquadplot - 1, variant='feec') if mesh.ndim == 2 and not mesh.extruded: scalarelem = FiniteElement("DQ", quadrilateral, nquadplot - 1, variant='feec') if mesh.ndim == 2 and mesh.extruded: scalarelem = TensorProductElement( FiniteElement("DG", interval, nquadplot - 1, variant='feec'), FiniteElement("DG", interval, nquadplot_v - 1, variant='feec')) if mesh.ndim == 3 and not mesh.extruded: scalarelem = FiniteElement("DG", hexahedron, nquadplot - 1, variant='feec') if mesh.ndim == 3 and mesh.extruded: scalarelem = TensorProductElement( FiniteElement("DG", quadrilateral, nquadplot - 1, variant='feec'), FiniteElement("DG", interval, nquadplot_v - 1, variant='feec')) vectorelem = VectorElement(scalarelem, dim=mesh.ndim) scalarevalspace = FunctionSpace(mesh, scalarelem) vectorevalspace = FunctionSpace(mesh, vectorelem) sptsl2 = Pascal1D(nquadplot) sptsl2v = Pascal1D(nquadplot_v) middle = Pascal1D(1) if mesh.ndim == 1: opts = [sptsl2, middle, middle] if mesh.ndim == 2 and not mesh.extruded: opts = [sptsl2, sptsl2, middle] if mesh.ndim == 2 and mesh.extruded: opts = [sptsl2, sptsl2v, middle] if mesh.ndim == 3 and not mesh.extruded: opts = [sptsl2, sptsl2, sptsl2] if mesh.ndim == 3 and mesh.extruded: opts = [sptsl2, sptsl2, sptsl2v] return scalarevalspace, vectorevalspace, opts
def lower_element_order(elem): if isinstance(elem, VectorElement): ndofs = elem.value_size() baseelem = lower_element_order(elem.sub_elements()[0]) return VectorElement(baseelem, dim=ndofs) elif isinstance(elem, MixedElement): # must come after because VectorElement is a subclass of MixedElement! elemlist = elem.sub_elements() newelemlist = [] for subelem in elemlist: newelemlist.append(lower_element_order(subelem)) return newelemlist if isinstance(elem, EnrichedElement): elem1, elem2 = elem._elements if (isinstance(elem1, HDivElement) and isinstance(elem2, HDivElement)): elem1 = elem1._element elem2 = elem2._element elem1low = lower_element_order(elem1) elem2low = lower_element_order(elem2) return HDivElement(elem1low) + HDivElement(elem2low) if (isinstance(elem1, HCurlElement) and isinstance(elem2, HCurlElement)): elem1 = elem1._element elem2 = elem2._element elem1low = lower_element_order(elem1) elem2low = lower_element_order(elem2) return HCurlElement(elem1low) + HCurlElement(elem2low) elif isinstance(elem, TensorProductElement): elem1, elem2 = elem.sub_elements() elem1low = lower_element_order(elem1) elem2low = lower_element_order(elem2) return TensorProductElement(elem1low, elem2low) elif isinstance(elem, FiniteElement): if elem.cell().cellname() == 'interval': if elem.family() == 'Discontinuous Lagrange': return FiniteElement("DG", interval, 0, variant='mgd') elif elem.family() == 'Lagrange': return FiniteElement("CG", interval, 1, variant='mgd') elif elem.cell().cellname() == 'quadrilateral': if elem.family() == 'Q': return FiniteElement("Q", quadrilateral, 1, variant='mgd') if elem.family() == 'DQ': return FiniteElement("DQ", quadrilateral, 0, variant='mgd') if elem.family() == 'RTCF': return FiniteElement("RTCF", quadrilateral, 1, variant='mgd') if elem.family() == 'RTCE': return FiniteElement("RTCE", quadrilateral, 1, variant='mgd') elif elem.cell().cellname() == 'hexahedron': if elem.family() == 'Q': return FiniteElement("Q", hexahedron, 1, variant='mgd') if elem.family() == 'DQ': return FiniteElement("DQ", hexahedron, 0, variant='mgd') if elem.family() == 'NCF': return FiniteElement("NCF", hexahedron, 1, variant='mgd') if elem.family() == 'NCE': return FiniteElement("NCE", hexahedron, 1, variant='mgd')
def test_varying_continuity_elements(): P1DG_t = FiniteElement("DG", triangle, 1) P1DG_i = FiniteElement("DG", interval, 1) P1 = FiniteElement("CG", interval, 1) P2 = FiniteElement("CG", interval, 2) P3 = FiniteElement("CG", interval, 3) RT1 = FiniteElement("RT", triangle, 1) ARG = FiniteElement("ARG", triangle, 5) # Tensor product elements P1DGP2 = TensorProductElement(P1DG_t, P2) P1P1DG = TensorProductElement(P1, P1DG_i) P1DGP1 = TensorProductElement(P1DG_i, P1) RT1DG1 = TensorProductElement(RT1, P1DG_i) P2P3 = TensorProductElement(P2, P3) ARGP3 = TensorProductElement(ARG, P3) assert P1DGP2 in H1dz and P1DGP2 in L2 assert P1DGP2 not in H1dh assert P1DGP1 in H1dy and P1DGP2 in L2 assert P1P1DG in H1dx and P1P1DG in L2 assert P1P1DG not in H1dx1dy assert RT1DG1 in H000 and RT1DG1 in L2 assert P2P3 in H1dx1dy and P2P3 in H1 assert ARG in H2dx2dy assert ARGP3 in H2dhH1dz
def test_enriched_elements_hcurl(): A = FiniteElement("CG", interval, 1) B = FiniteElement("DG", interval, 0) AxB = TensorProductElement(A, B) BxA = TensorProductElement(B, A) C = FiniteElement("RTCE", quadrilateral, 1) D = FiniteElement("DQ", quadrilateral, 0) Q1 = TensorProductElement(C, B) Q2 = TensorProductElement(D, A) hcurl_elements = [ EnrichedElement(HCurl(AxB), HCurl(BxA)), EnrichedElement(HCurl(Q1), HCurl(Q2)) ] for hcurl_element in hcurl_elements: assert hcurl_element in HCurl assert hcurl_element in L2 assert hcurl_element in H0dx0dy assert hcurl_element not in H1 assert hcurl_element not in H1dx1dy assert hcurl_element not in HDiv assert hcurl_element not in H2 assert hcurl_element not in H2dx2dy
def test_contains_hcurl(): hcurl_elements = [ FiniteElement("N1curl", triangle, 1), FiniteElement("N2curl", triangle, 1), # HCurl elements: HCurl( TensorProductElement(FiniteElement("CG", triangle, 1), FiniteElement("DG", interval, 1))), HCurl( TensorProductElement(FiniteElement("N1curl", triangle, 1), FiniteElement("CG", interval, 1))), HCurl( TensorProductElement(FiniteElement("RT", triangle, 1), FiniteElement("CG", interval, 1))) ] for hcurl_element in hcurl_elements: assert hcurl_element in HCurl assert hcurl_element in L2 assert hcurl_element in H0dx0dy assert hcurl_element not in H1 assert hcurl_element not in H1dx1dy assert hcurl_element not in HDiv assert hcurl_element not in H2 assert hcurl_element not in H2dx2dy
def reconstruct_degree(ele, N): """ Reconstruct an element, modifying its polynomial degree. By default, reconstructed EnrichedElements, TensorProductElements, and MixedElements will have the degree of the sub-elements shifted by the same amount so that the maximum degree is N. This is useful to coarsen spaces like NCF(N) x DQ(N-1). :arg ele: a :class:`ufl.FiniteElement` to reconstruct, :arg N: an integer degree. :returns: the reconstructed element """ if isinstance(ele, VectorElement): return VectorElement(PMGBase.reconstruct_degree( ele._sub_element, N), dim=ele.num_sub_elements()) elif isinstance(ele, TensorElement): return TensorElement(PMGBase.reconstruct_degree( ele._sub_element, N), shape=ele.value_shape(), symmetry=ele.symmetry()) elif isinstance(ele, EnrichedElement): shift = N - PMGBase.max_degree(ele) return EnrichedElement( *(PMGBase.reconstruct_degree(e, PMGBase.max_degree(e) + shift) for e in ele._elements)) elif isinstance(ele, TensorProductElement): shift = N - PMGBase.max_degree(ele) return TensorProductElement(*(PMGBase.reconstruct_degree( e, PMGBase.max_degree(e) + shift) for e in ele.sub_elements()), cell=ele.cell()) elif isinstance(ele, MixedElement): shift = N - PMGBase.max_degree(ele) return MixedElement( *(PMGBase.reconstruct_degree(e, PMGBase.max_degree(e) + shift) for e in ele.sub_elements())) else: try: return type(ele)(PMGBase.reconstruct_degree(ele._element, N)) except AttributeError: return ele.reconstruct(degree=N)
def reconstruct_degree(ele, N): """ Reconstruct a given element, modifying its polynomial degree. Can only set a single degree along all axes of a TensorProductElement. :arg ele: a :class:`ufl.FiniteElement` to reconstruct. :arg N: an integer degree. """ if isinstance(ele, TensorElement): sub = ele.sub_elements() return TensorElement(PMGBase.reconstruct_degree(sub[0], N), shape=ele.value_shape(), symmetry=ele.symmetry()) elif isinstance(ele, VectorElement): sub = ele.sub_elements() return VectorElement(PMGBase.reconstruct_degree(sub[0], N), dim=len(sub)) elif isinstance(ele, TensorProductElement): return TensorProductElement(*(PMGBase.reconstruct_degree(sub, N) for sub in ele.sub_elements()), cell=ele.cell()) else: return ele.reconstruct(degree=N)
def __init__(self, basemesh, layers, layer_height=None, name='singleblockextrudedmesh', coords=None, vcoordelem=None): self.basemesh = basemesh basenxs = basemesh.nxs basebcs = basemesh.bcs basecoordelem = basemesh._celem if layer_height is None: layer_height = 1.0 / layers if coords is None: if not (vcoordelem is None): # ADD SANITY CHECKS HERE velem = vcoordelem else: velem = FiniteElement("CG", interval, 1, variant='feec') celem = TensorProductElement(basecoordelem, velem) else: celem = coords.function_space()._uflelement.sub_elements()[0] ################# nxs = list(basenxs) bcs = list(basebcs) nxs.append(layers) bcs.append('nonperiodic') proc_sizes = list(basemesh.cell_da.getProcSizes()) proc_sizes.append(1) SingleBlockMesh.__init__(self, nxs, bcs, name=name, coordelem=celem, procsizes=proc_sizes) # bdirecs shouldn't include the extruded directions... self.bdirecs = [] for i, bc in enumerate(basebcs): if bc == 'nonperiodic': # THIS WORKS FOR ALL THE UTILITY MESHES SO FAR # MIGHT NEED SOMETHING MORE GENERAL IN THE FUTURE? if i == 0: direc = 'x' if i == 1: direc = 'y' self.bdirecs.append(direc + '-') self.bdirecs.append(direc + '+') self.extruded = True self.extrusion_dim = len(basenxs) # This is just uniform extrusion... if coords is None: basecoordsdm = basemesh.coordinates.space.get_da(0) basecoordsarr = basecoordsdm.getVecArray( basemesh.coordinates._vector)[:] coordsdm = self.coordinates.space.get_da(0) coordsarr = coordsdm.getVecArray(self.coordinates._vector)[:] if len(basecoordsarr.shape) == 1: basecoordsarr = np.expand_dims(basecoordsarr, axis=1) basecoordsarr = np.expand_dims(basecoordsarr, axis=-2) for i in range(len(basenxs)): coordsarr[..., i] = basecoordsarr[..., i] Lx = layer_height * layers coordsarr[..., -1] = coordsarr[..., -1] * Lx else: coords._vector.copy(result=self.coordinates._vector) self.coordinates.scatter()
# # UFL is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # UFL is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with UFL. If not, see <http://www.gnu.org/licenses/>. # # First added: 2012-08-16 # Last changed: 2012-08-16 from ufl import (FiniteElement, TensorProductElement, TestFunction, TrialFunction, dx, interval, tetrahedron, triangle) V0 = FiniteElement("CG", triangle, 1) V1 = FiniteElement("DG", interval, 0) V2 = FiniteElement("DG", tetrahedron, 0) V = TensorProductElement(V0, V1, V2) u = TrialFunction(V) v = TestFunction(V) dxxx = dx * dx * dx a = u * v * dxxx
def __init__(self, nxs, bcs, name='singleblockmesh', coordelem=None): assert (len(nxs) == len(bcs)) self.ndim = len(nxs) self.nxs = [ nxs, ] self.bcs = bcs self.npatches = 1 self.patchlist = [] self._name = name self._blist = [] for bc in bcs: if bc == 'periodic': self._blist.append(PETSc.DM.BoundaryType.PERIODIC) else: self._blist.append(PETSc.DM.BoundaryType.GHOSTED) bdx = 0 bdy = 0 bdz = 0 edgex_nxs = list(nxs) if (bcs[0] == 'nonperiodic'): edgex_nxs[0] = edgex_nxs[0] + 1 bdx = 1 if self.ndim >= 2: edgey_nxs = list(nxs) if (bcs[1] == 'nonperiodic'): edgey_nxs[1] = edgey_nxs[1] + 1 bdy = 1 if self.ndim >= 3: edgez_nxs = list(nxs) if (bcs[2] == 'nonperiodic'): edgez_nxs[2] = edgez_nxs[2] + 1 bdz = 1 # generate mesh cell_da = PETSc.DMDA().create() #THIS SHOULD REALLY BE AN OPTIONS PREFIX THING TO MESH... #MAIN THING IS THE ABILITY TO CONTROL DECOMPOSITION AT COMMAND LINE #BUT WE WANT TO BE ABLE TO IGNORE DECOMPOSITION WHEN RUNNING WITH A SINGLE PROCESSOR #WHICH ALLOWS THE SAME OPTIONS LIST TO BE USED TO RUN SOMETHING IN PARALLEL, AND THEN DO PLOTTING IN SERIAL! if PETSc.COMM_WORLD.size > 1: #this allows the same options list to be used to run something in parallel, but then plot it in serial! cell_da.setOptionsPrefix(self._name + '0_') cell_da.setFromOptions() ############# cell_da.setDim(self.ndim) cell_da.setDof(1) cell_da.setSizes(nxs) cell_da.setBoundaryType(self._blist) cell_da.setStencil(PETSc.DMDA.StencilType.BOX, 1) cell_da.setUp() #print self.cell_da.getProcSizes() edgex_da = PETSc.DMDA().create(dim=self.ndim, dof=1, sizes=edgex_nxs, proc_sizes=cell_da.getProcSizes(), boundary_type=self._blist, stencil_type=PETSc.DMDA.StencilType.BOX, stencil_width=1, setup=False) #THIS IS AN UGLY HACK NEEDED BECAUSE OWNERSHIP RANGES ARGUMENT TO petc4py DMDA_CREATE is BROKEN decompfunction(cell_da, edgex_da, self.ndim, 1, 1, 1, bdx, 0, 0) edgex_da.setUp() if self.ndim >= 2: edgey_da = PETSc.DMDA().create( dim=self.ndim, dof=1, sizes=edgey_nxs, proc_sizes=cell_da.getProcSizes(), boundary_type=self._blist, stencil_type=PETSc.DMDA.StencilType.BOX, stencil_width=1, setup=False) #THIS IS AN UGLY HACK NEEDED BECAUSE OWNERSHIP RANGES ARGUMENT TO petc4py DMDA_CREATE is BROKEN decompfunction(cell_da, edgey_da, self.ndim, 1, 1, 1, 0, bdy, 0) edgey_da.setUp() if self.ndim >= 3: edgez_da = PETSc.DMDA().create( dim=self.ndim, dof=1, sizes=edgez_nxs, proc_sizes=cell_da.getProcSizes(), boundary_type=self._blist, stencil_type=PETSc.DMDA.StencilType.BOX, stencil_width=1, setup=False) #THIS IS AN UGLY HACK NEEDED BECAUSE OWNERSHIP RANGES ARGUMENT TO petc4py DMDA_CREATE is BROKEN decompfunction(cell_da, edgez_da, self.ndim, 1, 1, 1, 0, 0, bdz) edgez_da.setUp() self._cell_das = [ cell_da, ] self._edgex_das = [ edgex_da, ] self._edgex_nxs = [ edgex_nxs, ] if self.ndim >= 2: self._edgey_das = [ edgey_da, ] self._edgey_nxs = [ edgey_nxs, ] if self.ndim >= 3: self._edgez_das = [ edgez_da, ] self._edgez_nxs = [ edgez_nxs, ] #ADD ACTUAL COORDINATE FUNCTION INITIALIZATION HERE #construct coordelem #FIX THIS- SHOULD USE H1 FOR NON-PERIODIC! #Use DG for periodic boundaries to avoid wrapping issues h1elem = FiniteElement("CG", interval, 1) #1 dof per element = linear l2elem = FiniteElement("DG", interval, 1) #2 dofs per element = linear elemlist = [] dxs = [] pxs = [] lxs = [] for i in range(len(nxs)): dxs.append(2.) pxs.append(0.) lxs.append(2. * nxs[i]) #if bcs[i] == 'periodic': elemlist.append(l2elem) #else: # elemlist.append(h1elem) celem = TensorProductElement(*elemlist) if len(nxs) == 1: celem = elemlist[0] if not (coordelem == None): celem = coordelem celem = VectorElement(celem, dim=self.ndim) Mesh.__init__(self, celem) #THIS BREAKS FOR COORDELEM NOT DG1... #construct and set coordsvec coordsspace = FunctionSpace(self, celem) self.coordinates = Function(coordsspace, name='coords') localnxs = self.get_local_nxny(0) newcoords = create_uniform_nodal_coords(self.get_cell_da(0), nxs, pxs, lxs, dxs, bcs, localnxs) coordsdm = coordsspace.get_da(0, 0) coordsarr = coordsdm.getVecArray(self.coordinates._vector)[:] if len(pxs) == 1: coordsarr[:] = np.squeeze(newcoords[:]) else: coordsarr[:] = newcoords[:] self.coordinates.scatter()