def Lagrange(C, zeta, eta, beta, arrange=1): """Computes higher order Lagrangian bases with equally spaced points """ Neta = np.zeros((C + 2, 1)) Nzeta = np.zeros((C + 2, 1)) Nbeta = np.zeros((C + 2, 1)) Nzeta[:, 0] = OneD.Lagrange(C, zeta)[0] Neta[:, 0] = OneD.Lagrange(C, eta)[0] Nbeta[:, 0] = OneD.Lagrange(C, beta)[0] # Ternsorial product if arrange == 1: node_arranger = NodeArrangementHex(C)[2] Bases = np.einsum('i,j,k', Nbeta[:, 0], Neta[:, 0], Nzeta[:, 0]).flatten() Bases = Bases[node_arranger] Bases = Bases[:, None] elif arrange == 0: Bases = np.zeros((C + 2, C + 2, C + 2)) for i in range(0, C + 2): Bases[:, :, i] = Nbeta[i] * np.dot(Nzeta, Neta.T) Bases = Bases.reshape((C + 2)**3, 1) return Bases
def GradLagrange(C, zeta, eta, beta, arrange=1): """Computes gradient of higher order Lagrangian bases with equally spaced points """ gBases = np.zeros(((C + 2)**3, 3)) Nzeta = np.zeros((C + 2, 1)) Neta = np.zeros((C + 2, 1)) Nbeta = np.zeros((C + 2, 1)) gNzeta = np.zeros((C + 2, 1)) gNeta = np.zeros((C + 2, 1)) gNbeta = np.zeros((C + 2, 1)) # Compute each from one-dimensional bases Nzeta[:, 0] = OneD.Lagrange(C, zeta)[0] Neta[:, 0] = OneD.Lagrange(C, eta)[0] Nbeta[:, 0] = OneD.Lagrange(C, beta)[0] gNzeta[:, 0] = OneD.Lagrange(C, zeta)[1] gNeta[:, 0] = OneD.Lagrange(C, eta)[1] gNbeta[:, 0] = OneD.Lagrange(C, beta)[1] # Ternsorial product if arrange == 1: node_arranger = NodeArrangementHex(C)[2] # g0 = np.einsum('i,j,k', gNbeta[:,0], Neta[:,0], Nzeta[:,0]).flatten() # g1 = np.einsum('i,j,k', Nbeta[:,0], gNeta[:,0], Nzeta[:,0]).flatten() # g2 = np.einsum('i,j,k', Nbeta[:,0], Neta[:,0], gNzeta[:,0]).flatten() g0 = np.einsum('i,j,k', Nbeta[:, 0], Neta[:, 0], gNzeta[:, 0]).flatten() g1 = np.einsum('i,j,k', Nbeta[:, 0], gNeta[:, 0], Nzeta[:, 0]).flatten() g2 = np.einsum('i,j,k', gNbeta[:, 0], Neta[:, 0], Nzeta[:, 0]).flatten() gBases[:, 0] = g0[node_arranger] gBases[:, 1] = g1[node_arranger] gBases[:, 2] = g2[node_arranger] elif arrange == 0: gBases1 = np.zeros((C + 2, C + 2, C + 2)) gBases2 = np.zeros((C + 2, C + 2, C + 2)) gBases3 = np.zeros((C + 2, C + 2, C + 2)) for i in range(0, C + 2): gBases1[:, :, i] = Nbeta[i] * np.dot(gNzeta, Neta.T) gBases2[:, :, i] = Nbeta[i] * np.dot(Nzeta, gNeta.T) gBases3[:, :, i] = gNbeta[i] * np.dot(Nzeta, Neta.T) gBases1 = gBases1.reshape((C + 2)**3, 1) gBases2 = gBases2.reshape((C + 2)**3, 1) gBases3 = gBases3.reshape((C + 2)**3, 1) gBases[:, 0] = gBases1 gBases[:, 1] = gBases2 gBases[:, 2] = gBases3 return gBases
def GaussLobattoPointsHex(C): xs = GaussLobattoQuadrature(C + 2)[0] x, y, z = np.meshgrid(xs, xs, xs) points = np.concatenate( (y.T.flatten()[:, None], x.T.flatten()[:, None], z.T.flatten()[:, None]), axis=1) # p = 1 # [-1. -1. -1.] # [ 1. -1. -1.] # [ 1. 1. -1.] # [-1. 1. -1.] # [-1. -1. 1.] # [ 1. -1. 1.] # [ 1. 1. 1.] # [-1. 1. 1.] node_aranger = NodeArrangementHex(C)[2] return points[node_aranger, :]
def LagrangeGaussLobatto(C, zeta, eta, beta, arrange=1): """This routine computes stable higher order Lagrangian bases with Gauss-Lobatto-Legendre points Refer to: Spencer's Spectral hp elements for details""" Neta = np.zeros((C + 2, 1)) Nzeta = np.zeros((C + 2, 1)) Nbeta = np.zeros((C + 2, 1)) Nzeta[:, 0] = OneD.LagrangeGaussLobatto(C, zeta)[0] Neta[:, 0] = OneD.LagrangeGaussLobatto(C, eta)[0] Nbeta[:, 0] = OneD.LagrangeGaussLobatto(C, beta)[0] if arrange == 1: # Bases = np.zeros(((C+2)**3,1)) # # Arrange in counterclockwise # zeta_index, eta_index = GetCounterClockwiseIndices(C) # TBases = np.dot(Nzeta,Neta.T) # counter=0 # for j in range(0,C+2): # for i in range(0,(C+2)**2): # Bases[counter] = Nbeta[j]*TBases[zeta_index[i],eta_index[i]] # counter+=1 node_arranger = NodeArrangementHex(C)[2] Bases = np.einsum('i,j,k', Nbeta[:, 0], Neta[:, 0], Nzeta[:, 0]).flatten() Bases = Bases[node_arranger] Bases = Bases[:, None] elif arrange == 0: Bases = np.zeros((C + 2, C + 2, C + 2)) for i in range(0, C + 2): Bases[:, :, i] = Nbeta[i] * np.dot(Nzeta, Neta.T) Bases = Bases.reshape((C + 2)**3, 1) return Bases
def test_quadrature_functionspace(): print("Running tests on QuadratureRule and FunctionSpace modules") mesh = Mesh() etypes = ["line", "tri", "quad", "tet", "hex"] for etype in etypes: if etype == "line": mesh.Line() elif etype == "tri": mesh.Circle(element_type="tri") elif etype == "quad": mesh.Circle(element_type="quad") elif etype == "tet": mesh.Cube(element_type="tet", nx=1, ny=1, nz=1) elif etype == "hex": mesh.Cube(element_type="hex", nx=1, ny=1, nz=1) for p in range(2, 7): mesh.GetHighOrderMesh(p=p, check_duplicates=False) q = QuadratureRule(mesh_type=etype, norder=p + 2, flatten=False) FunctionSpace(mesh, q, p=p, equally_spaced=False) FunctionSpace(mesh, q, p=p, equally_spaced=True) q = QuadratureRule(mesh_type=etype, norder=p + 2, flatten=True) FunctionSpace(mesh, q, p=p, equally_spaced=False) FunctionSpace(mesh, q, p=p, equally_spaced=True) # now test all Fekete/ES point creation from Florence.QuadratureRules import FeketePointsTri from Florence.QuadratureRules.QuadraturePointsWeightsTri import QuadraturePointsWeightsTri from Florence.QuadratureRules import FeketePointsTet from Florence.QuadratureRules.QuadraturePointsWeightsTet import QuadraturePointsWeightsTet from Florence.QuadratureRules import GaussLobattoPoints1D, GaussLobattoPointsQuad, GaussLobattoPointsHex from Florence.QuadratureRules.QuadraturePointsWeightsTri import QuadraturePointsWeightsTri from Florence.QuadratureRules.WVQuadraturePointsWeightsQuad import WVQuadraturePointsWeightsQuad from Florence.QuadratureRules.WVQuadraturePointsWeightsHex import WVQuadraturePointsWeightsHex from Florence.QuadratureRules.EquallySpacedPoints import EquallySpacedPoints, EquallySpacedPointsTri, EquallySpacedPointsTet from Florence.MeshGeneration.NodeArrangement import NodeArrangementLine, NodeArrangementTri, NodeArrangementQuad from Florence.MeshGeneration.NodeArrangement import NodeArrangementTet, NodeArrangementHex, NodeArrangementQuadToTri from Florence.MeshGeneration.NodeArrangement import NodeArrangementHexToTet, NodeArrangementLayeredToHex for i in range(21): FeketePointsTri(i) QuadraturePointsWeightsTri(i, 3) QuadraturePointsWeightsTet(i) EquallySpacedPoints(2, i) EquallySpacedPoints(3, i) EquallySpacedPoints(4, i) EquallySpacedPointsTri(i) EquallySpacedPointsTet(i) NodeArrangementLine(i) NodeArrangementTri(i) NodeArrangementQuad(i) NodeArrangementHex(i) NodeArrangementLayeredToHex(i) if i < 6: NodeArrangementQuadToTri(i) if i < 2: NodeArrangementHexToTet(i) if i < 18: FeketePointsTet(i) NodeArrangementTet(i) WVQuadraturePointsWeightsQuad(i) if i <= 16: WVQuadraturePointsWeightsHex(i) print( "Successfully finished running tests on QuadratureRule and FunctionSpace modules\n" )
def GradLagrangeGaussLobatto(C, zeta, eta, beta, arrange=1): """This routine computes stable higher order Lagrangian bases with Gauss-Lobatto-Legendre points Refer to: Spencer's Spectral hp elements for details""" gBases = np.zeros(((C + 2)**3, 3)) Nzeta = np.zeros((C + 2, 1)) Neta = np.zeros((C + 2, 1)) Nbeta = np.zeros((C + 2, 1)) gNzeta = np.zeros((C + 2, 1)) gNeta = np.zeros((C + 2, 1)) gNbeta = np.zeros((C + 2, 1)) # Compute each from one-dimensional bases Nzeta[:, 0] = OneD.LagrangeGaussLobatto(C, zeta)[0] Neta[:, 0] = OneD.LagrangeGaussLobatto(C, eta)[0] Nbeta[:, 0] = OneD.LagrangeGaussLobatto(C, beta)[0] gNzeta[:, 0] = OneD.LagrangeGaussLobatto(C, zeta)[1] gNeta[:, 0] = OneD.LagrangeGaussLobatto(C, eta)[1] gNbeta[:, 0] = OneD.LagrangeGaussLobatto(C, beta)[1] # Ternsorial product if arrange == 1: # # Arrange in counterclockwise # zeta_index, eta_index = GetCounterClockwiseIndices(C) # gBases1 = np.dot(gNzeta,Neta.T) # gBases2 = np.dot(Nzeta,gNeta.T) # gBases3 = np.dot(Nzeta,Neta.T) # counter=0 # for j in range(0,C+2): # for i in range(0,(C+2)**2): # gBases[counter,0] = Nbeta[j]*gBases1[zeta_index[i],eta_index[i]] # gBases[counter,1] = Nbeta[j]*gBases2[zeta_index[i],eta_index[i]] # gBases[counter,2] = gNbeta[j]*gBases3[zeta_index[i],eta_index[i]] # counter+=1 node_arranger = NodeArrangementHex(C)[2] # g0 = np.einsum('i,j,k', gNbeta[:,0], Neta[:,0], Nzeta[:,0]).flatten() # g1 = np.einsum('i,j,k', Nbeta[:,0], gNeta[:,0], Nzeta[:,0]).flatten() # g2 = np.einsum('i,j,k', Nbeta[:,0], Neta[:,0], gNzeta[:,0]).flatten() g0 = np.einsum('i,j,k', Nbeta[:, 0], Neta[:, 0], gNzeta[:, 0]).flatten() g1 = np.einsum('i,j,k', Nbeta[:, 0], gNeta[:, 0], Nzeta[:, 0]).flatten() g2 = np.einsum('i,j,k', gNbeta[:, 0], Neta[:, 0], Nzeta[:, 0]).flatten() gBases[:, 0] = g0[node_arranger] gBases[:, 1] = g1[node_arranger] gBases[:, 2] = g2[node_arranger] elif arrange == 0: gBases1 = np.zeros((C + 2, C + 2, C + 2)) gBases2 = np.zeros((C + 2, C + 2, C + 2)) gBases3 = np.zeros((C + 2, C + 2, C + 2)) for i in range(0, C + 2): gBases1[:, :, i] = Nbeta[i] * np.dot(gNzeta, Neta.T) gBases2[:, :, i] = Nbeta[i] * np.dot(Nzeta, gNeta.T) gBases3[:, :, i] = gNbeta[i] * np.dot(Nzeta, Neta.T) gBases1 = gBases1.reshape((C + 2)**3, 1) gBases2 = gBases2.reshape((C + 2)**3, 1) gBases3 = gBases3.reshape((C + 2)**3, 1) gBases[:, 0] = gBases1 gBases[:, 1] = gBases2 gBases[:, 2] = gBases3 return gBases
def HighOrderMeshHex(C, mesh, Decimals=10, equally_spaced=False, check_duplicates=True, Zerofy=True, Parallel=False, nCPU=1, ComputeAll=True): from Florence.FunctionSpace import Hex, HexES from Florence.QuadratureRules import GaussLobattoPointsHex from Florence.QuadratureRules.EquallySpacedPoints import EquallySpacedPoints from Florence.MeshGeneration.NodeArrangement import NodeArrangementHex # SWITCH OFF MULTI-PROCESSING FOR SMALLER PROBLEMS WITHOUT GIVING A MESSAGE if (mesh.elements.shape[0] < 500) and (C < 5): Parallel = False nCPU = 1 if not equally_spaced: eps = GaussLobattoPointsHex(C) # COMPUTE BASES FUNCTIONS AT ALL NODAL POINTS Neval = np.zeros((8, eps.shape[0]), dtype=np.float64) hpBases = Hex.LagrangeGaussLobatto for i in range(8, eps.shape[0]): Neval[:, i] = hpBases(0, eps[i, 0], eps[i, 1], eps[i, 2])[:, 0] else: eps = EquallySpacedPoints(4, C) # COMPUTE BASES FUNCTIONS AT ALL NODAL POINTS Neval = np.zeros((8, eps.shape[0]), dtype=np.float64) hpBases = HexES.Lagrange for i in range(8, eps.shape[0]): Neval[:, i] = hpBases(0, eps[i, 0], eps[i, 1], eps[i, 2])[:, 0] # THIS IS NECESSARY FOR REMOVING DUPLICATES makezero(Neval, tol=1e-12) nodeperelem = mesh.elements.shape[1] renodeperelem = int((C + 2)**3) left_over_nodes = renodeperelem - nodeperelem reelements = -1 * np.ones( (mesh.elements.shape[0], renodeperelem), dtype=np.int64) reelements[:, :8] = mesh.elements # TOTAL NUMBER OF (INTERIOR+EDGE+FACE) NODES iesize = renodeperelem - 8 repoints = np.zeros( (mesh.points.shape[0] + iesize * mesh.elements.shape[0], 3), dtype=np.float64) repoints[:mesh.points.shape[0], :] = mesh.points telements = time() xycoord_higher = [] ParallelTuple1 = [] if Parallel: # GET HIGHER ORDER COORDINATES - PARALLEL ParallelTuple1 = parmap.map(ElementLoopTet, np.arange(0, mesh.elements.shape[0]), mesh.elements, mesh.points, 'hex', eps, Neval, pool=MP.Pool(processes=nCPU)) maxNode = np.max(reelements) for elem in range(0, mesh.elements.shape[0]): # maxNode = np.max(reelements) # BIG BOTTLENECK if Parallel: xycoord_higher = ParallelTuple1[elem] else: xycoord = mesh.points[mesh.elements[elem, :], :] # GET HIGHER ORDER COORDINATES xycoord_higher = GetInteriorNodesCoordinates( xycoord, 'hex', elem, eps, Neval) # EXPAND THE ELEMENT CONNECTIVITY newElements = np.arange(maxNode + 1, maxNode + 1 + left_over_nodes) reelements[elem, 8:] = newElements # INSTEAD COMPUTE maxNode BY INDEXING maxNode = newElements[-1] repoints[mesh.points.shape[0] + elem * iesize:mesh.points.shape[0] + (elem + 1) * iesize] = xycoord_higher[8:, :] if Parallel: del ParallelTuple1 telements = time() - telements #-------------------------------------------------------------------------------------- # NOW REMOVE DUPLICATED POINTS tnodes = time() nnode_linear = mesh.points.shape[0] # KEEP ZEROFY ON, OTHERWISE YOU GET STRANGE BEHVAIOUR # rounded_repoints = makezero(repoints[nnode_linear:,:].copy()) rounded_repoints = repoints[nnode_linear:, :].copy() makezero(rounded_repoints) rounded_repoints = np.round(rounded_repoints, decimals=Decimals) _, idx_repoints, inv_repoints = unique2d(rounded_repoints, order=False, consider_sort=False, return_index=True, return_inverse=True) # idx_repoints.sort() del rounded_repoints #, flattened_repoints idx_repoints = np.concatenate( (np.arange(nnode_linear), idx_repoints + nnode_linear)) repoints = repoints[idx_repoints, :] unique_reelements, inv_reelements = np.unique(reelements[:, 8:], return_inverse=True) unique_reelements = unique_reelements[inv_repoints] reelements = unique_reelements[inv_reelements] reelements = reelements.reshape(mesh.elements.shape[0], renodeperelem - 8) reelements = np.concatenate((mesh.elements, reelements), axis=1) # SANITY CHECK fOR DUPLICATES #---------------------------------------------------------------------# # NOTE THAT THIS REMAPS THE ELEMENT CONNECTIVITY FOR THE WHOLE MESH # AND AS A RESULT THE FIRST FEW COLUMNS WOULD NO LONGER CORRESPOND TO # LINEAR CONNECTIVITY if check_duplicates: last_shape = repoints.shape[0] deci = int(Decimals) - 2 if Decimals < 6: deci = Decimals repoints, idx_repoints, inv_repoints = remove_duplicates_2D( repoints, decimals=deci) unique_reelements, inv_reelements = np.unique(reelements, return_inverse=True) unique_reelements = unique_reelements[inv_repoints] reelements = unique_reelements[inv_reelements] reelements = reelements.reshape(mesh.elements.shape[0], renodeperelem) if last_shape != repoints.shape[0]: warn( 'Duplicated points generated in high order mesh. Lower the "Decimals". I have fixed it for now' ) #---------------------------------------------------------------------# tnodes = time() - tnodes #------------------------------------------------------------------------------------------ # USE ALTERNATIVE APPROACH TO GET MESH EDGES AND FACES reedges = np.zeros((mesh.edges.shape[0], C + 2)) fsize = int((C + 2.) * (C + 3.) / 2.) refaces = np.zeros((mesh.faces.shape[0], fsize), dtype=mesh.faces.dtype) if ComputeAll == True: #------------------------------------------------------------------------------------------ # BUILD FACES NOW tfaces = time() refaces = np.zeros((mesh.faces.shape[0], fsize)) # DO NOT CHANGE THE FACES, BY RECOMPUTING THEM, AS THE LINEAR FACES CAN COME FROM # AN EXTERNAL MESH GENERATOR, WHOSE ORDERING MAY NOT BE THE SAME, SO JUST FIND WHICH # ELEMENTS CONTAIN THESE FACES face_to_elements = mesh.GetElementsWithBoundaryFacesHex() node_arranger = NodeArrangementHex(C)[0] refaces = reelements[face_to_elements[:, 0][:, None], node_arranger[face_to_elements[:, 1], :]].astype( mesh.faces.dtype) tfaces = time() - tfaces #------------------------------------------------------------------------------------------ #------------------------------------------------------------------------------------------ # BUILD EDGES NOW tedges = time() # BUILD A 2D MESH from Florence import Mesh tmesh = Mesh() tmesh.element_type = "quad" tmesh.elements = refaces tmesh.nelem = tmesh.elements.shape[0] # GET BOUNDARY EDGES reedges = tmesh.GetEdgesQuad() del tmesh tedges = time() - tedges #------------------------------------------------------------------------------------------ class nmesh(object): # """Construct pMesh""" points = repoints elements = reelements edges = np.array([[], []]) faces = np.array([[], []]) nnode = repoints.shape[0] nelem = reelements.shape[0] info = 'hex' if ComputeAll is True: nmesh.edges = reedges nmesh.faces = refaces gc.collect() # print '\nHigh order meshing timing:\n\t\tElement loop:\t '+str(telements)+' seconds\n\t\tNode loop:\t\t '+str(tnodes)+\ # ' seconds'+'\n\t\tEdge loop:\t\t '+str(tedges)+' seconds'+\ # '\n\t\tFace loop:\t\t '+str(tfaces)+' seconds\n' return nmesh