def LocallyInjectiveHessian(J, gJ, HJ): H1 = 6. * (2 * J**4 - 8 * J**3 + 12 * J**2 - 9 * J + 3) / (J**3 * (J**6 - 9 * J**5 + 36 * J**4 - 81 * J**3 + 108 * J**2 - 81 * J + 27)) * np.outer(gJ, gJ) H1 += 3. * (-J**2 + 2 * J - 1) / (J**2 * (J**2 - 3 * J + 3)**2) * HJ makezero(H1, 1e-12) return H1
def dJdF(F): if F.shape[0] == 2: return np.array([[F[1, 1], -F[1, 0]], [-F[0, 1], F[0, 0]]]) else: f0 = F[:, 0] f1 = F[:, 1] f2 = F[:, 2] final = np.zeros((3, 3)) final[:, 0] = np.cross(f1, f2) final[:, 1] = np.cross(f2, f0) final[:, 2] = np.cross(f0, f1) makezero(final) return final
def CauchyStress(self, StrainTensors, ElectricDisplacementx, elem=0, gcounter=0): mu = self.mu lamb = self.lamb d = self.ndim I = StrainTensors['I'] F = StrainTensors['F'][gcounter] J = StrainTensors['J'][gcounter] b = StrainTensors['b'][gcounter] u, s, vh = svd(F, full_matrices=True) vh = vh.T R = u.dot(vh.T) S = np.dot(vh, np.dot(np.diag(s), vh.T)) J2 = J**2 J3 = J**3 I1 = trace(S) I2 = trace(b) if self.ndim == 2: sigma = 2. * (1. + 1. / J2) * F - 2. * (1. + 1. / J) * R + ( 2. / J2) * (I1 - I2 / J) * dJdF(F) else: djdf = dJdF(F) C = np.dot(F.T, F) IC = trace(C) IIC = trace(C.dot(C)) IIStarC = 0.5 * (IC * IC - IIC) IS = trace(S) # IIS = trace(S.dot(S)); IIS = I2 IIStarS = 0.5 * (IS * IS - IIS) # % here's symmetric dirichlet dIIStarC = 2 * IC * F - 2. * b.dot(F) P = 2 * F + dIIStarC / J2 - (2. / J3) * IIStarC * djdf P = P - 2 * ((1 + IS / J) * R - (IIStarS / J2) * djdf - (1. / J) * F) P = P / 2. sigma = P makezero(sigma, 1e-12) # print(sigma) return sigma
def remove_duplicates_2D(A, decimals=10): """Removes duplicates from floating point 2D array (A) with rounding """ assert isinstance(A,np.ndarray) assert (A.dtype == np.float64 or A.dtype == np.float32) from Florence.Tensor import makezero makezero(A) rounded_repoints = np.round(A,decimals=decimals) _, idx_repoints, inv_repoints = unique2d(rounded_repoints,order=False, consider_sort=False,return_index=True,return_inverse=True) A = A[idx_repoints,:] return A, idx_repoints, inv_repoints
def ComputeExtrusion(self, nlong=10): """Computes extrusion of a base mesh along an arc input: nlong: [int] number of discretisation along the arc returns: points: [1D array] of discretisation along arc """ from numpy.linalg import norm npoints = nlong + 1 line0 = self.start - self.center line1 = self.end - self.center # CHECK IF ALL THE POINTS LIE ON A LINE if np.isclose(np.abs(self.angle),0.0) or \ np.isclose(np.abs(self.angle),np.pi) or \ np.isclose(np.abs(self.angle),2.*np.pi): self.angle += 1e-08 warn("The arc points are nearly colinear") t = np.linspace(0, self.angle, npoints + 1) points = (np.einsum("i,j",np.sin(self.angle - t),line0) + \ np.einsum("i,j",np.sin(t),line1))/np.sin(self.angle) + self.center makezero(points) # IF ALL THE Z-COORDIDATES ARE ZERO, THEN EXTRUSION NOT POSSIBLE if np.allclose(points[:, 2], 0.0): warn( "Third dimension is zero. Extrusion will fail, unless axes are swapped" ) return points
def ComputeExtrusion(self, nlong=10): """Computes extrusion of a base mesh along an arc input: nlong: [int] number of discretisation along the arc returns: points: [1D array] of discretisation along arc """ from numpy.linalg import norm npoints = nlong + 1 line0 = self.start - self.center line1 = self.end - self.center # CHECK IF ALL THE POINTS LIE ON A LINE if np.isclose(np.abs(self.angle),0.0) or \ np.isclose(np.abs(self.angle),np.pi) or \ np.isclose(np.abs(self.angle),2.*np.pi): self.angle += 1e-08 warn("The arc points are nearly colinear") t = np.linspace(0,self.angle,npoints+1) points = (np.einsum("i,j",np.sin(self.angle - t),line0) + \ np.einsum("i,j",np.sin(t),line1))/np.sin(self.angle) + self.center makezero(points) # IF ALL THE Z-COORDIDATES ARE ZERO, THEN EXTRUSION NOT POSSIBLE if np.allclose(points[:,2],0.0): warn("Third dimension is zero. Extrusion will fail, unless axes are swapped") return points # # print(tx*self.angle) # # FIND NORMAL TO THE PLANE OF ARC # normal_to_arc_plane = np.cross(self.start - self.center, self.end - self.center) # # FIND TWO ORTHOGONAL VECTORS IN THE PLANE OF ARC # X = self.start/norm(self.start) # Y = np.cross(normal_to_arc_plane, self.start) / norm(np.cross(normal_to_arc_plane, self.start)) # # print(normal_to_arc_plane, self.start) # # t = np.linspace(0, self.angle, npoints+1) # t = np.linspace(0., self.angle, npoints+1) # # t = np.linspace(0, self.angle+0.2284, npoints+1) # # x = norm(np.dot(self.start - self.center, self.end - self.center)) # # print(np.arccos(x)) # # print(self.angle) # points = np.einsum("i,j",self.radius*np.cos(t),X) + np.einsum("i,j",self.radius*np.sin(t),Y) # # points = np.einsum("i,j",self.radius*np.sin(t),X) + np.einsum("i,j",self.radius*np.cos(t),Y) # # y = np.einsum("i,j",self.radius*np.sin(t),Y) # # print(X,Y,t) # print(points) # # print(np.dot(X,Y)) # # t= np.linspace(-np.pi/2,np.pi,100) # # X = np.array([0,1]) # # Y = np.array([1,0]) # # # points = np.einsum("i,j",self.radius*np.cos(t),X) + np.einsum("i,j",self.radius*np.sin(t),Y) # # points = np.einsum("i,j",self.radius*np.sin(t),X) + np.einsum("i,j",self.radius*np.cos(t),Y) # # makezero(points) # # print(points) # exit() # import matplotlib.pyplot as plt # plt.plot(points[:,0],points[:,1],'ro') # plt.axis('equal') # plt.show() # import os # os.environ['ETS_TOOLKIT'] = 'qt4' # from mayavi import mlab # figure = mlab.figure(bgcolor=(1,1,1),fgcolor=(1,1,1),size=(800,600)) # mlab.plot3d(points[:,0],points[:,1],points[:,2]) # mlab.show() # exit() # print(self.start_angle, self.end_angle) # x = self.radius*np.cos(t) # y = self.radius*np.sin(t) # points = np.array([x,y]).T.copy() # makezero(points) # t = np.linspace(0,40.,npoints+1)
def HighOrderMeshQuad(C, mesh, Decimals=10, equally_spaced=False, check_duplicates=True, parallelise=False, nCPU=1, compute_boundary_info=True): from Florence.FunctionSpace import Quad, QuadES from Florence.QuadratureRules import GaussLobattoPointsQuad from Florence.QuadratureRules.EquallySpacedPoints import EquallySpacedPoints from Florence.MeshGeneration.NodeArrangement import NodeArrangementQuad Parallel = parallelise if not equally_spaced: eps = GaussLobattoPointsQuad(C) # COMPUTE BASES FUNCTIONS AT ALL NODAL POINTS Neval = np.zeros((4, eps.shape[0]), dtype=np.float64) for i in range(0, eps.shape[0]): Neval[:, i] = Quad.LagrangeGaussLobatto(0, eps[i, 0], eps[i, 1], arrange=1)[:, 0] else: eps = EquallySpacedPoints(3, C) # COMPUTE BASES FUNCTIONS AT ALL NODAL POINTS Neval = np.zeros((4, eps.shape[0]), dtype=np.float64) for i in range(0, eps.shape[0]): Neval[:, i] = QuadES.Lagrange(0, eps[i, 0], eps[i, 1], arrange=1)[:, 0] makezero(Neval) nodeperelem = mesh.elements.shape[1] renodeperelem = int((C + 2)**2) left_over_nodes = renodeperelem - nodeperelem reelements = -1 * np.ones( (mesh.elements.shape[0], renodeperelem), dtype=np.int64) reelements[:, :4] = mesh.elements iesize = int(4 * C + C**2) repoints = np.zeros( (mesh.points.shape[0] + iesize * mesh.elements.shape[0], mesh.points.shape[1]), 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(ElementLoopTri, np.arange(0, mesh.elements.shape[0]), mesh.elements, mesh.points, 'quad', eps, Neval, pool=MP.Pool(processes=nCPU)) # LOOP OVER ELEMENTS maxNode = np.max(reelements) for elem in range(0, mesh.elements.shape[0]): # GET HIGHER ORDER COORDINATES if Parallel: xycoord_higher = ParallelTuple1[elem] else: xycoord_higher = GetInteriorNodesCoordinates( mesh.points[mesh.elements[elem, :], :], 'quad', elem, eps, Neval) # EXPAND THE ELEMENT CONNECTIVITY newElements = np.arange(maxNode + 1, maxNode + 1 + left_over_nodes) # reelements[elem,3:] = np.arange(maxNode+1,maxNode+1+left_over_nodes) reelements[elem, 4:] = newElements maxNode = newElements[-1] repoints[mesh.points.shape[0] + elem * iesize:mesh.points.shape[0] + (elem + 1) * iesize] = xycoord_higher[4:, :] 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 = 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) del rounded_repoints idx_repoints = np.concatenate( (np.arange(nnode_linear), idx_repoints + nnode_linear)) repoints = repoints[idx_repoints, :] unique_reelements, inv_reelements = np.unique(reelements[:, 4:], return_inverse=True) unique_reelements = unique_reelements[inv_repoints] reelements = unique_reelements[inv_reelements] reelements = reelements.reshape(mesh.elements.shape[0], renodeperelem - 4) 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 #------------------------------------------------------------------------------------------ #------------------------------------------------------------------------------------------ reedges = np.array([]) if compute_boundary_info: # BUILD EDGES NOW tedges = time() edge_to_elements = mesh.GetElementsWithBoundaryEdgesQuad() node_arranger = NodeArrangementQuad(C)[0] reedges = np.zeros((mesh.edges.shape[0], C + 2), dtype=np.int64) reedges = reelements[edge_to_elements[:, 0][:, None], node_arranger[edge_to_elements[:, 1], :]] tedges = time() - tedges #------------------------------------------------------------------------------------------ class nmesh(object): points = repoints elements = reelements edges = reedges faces = [] nnode = repoints.shape[0] nelem = reelements.shape[0] info = 'quad' # print('\npMeshing timing:\n\t\tElement loop 1:\t '+str(telements)+' seconds\n\t\tNode loop:\t\t '+str(tnodes)+\ # ' seconds'+'\n\t\tElement loop 2:\t '+str(telements_2)+' seconds\n\t\tEdge loop:\t\t '+str(tedges)+' seconds\n') return nmesh
def Hessian(self, StrainTensors, ElectricDisplacementx, elem=0, gcounter=0): mu = self.mu lamb = self.lamb d = self.ndim I = StrainTensors['I'] F = StrainTensors['F'][gcounter] J = StrainTensors['J'][gcounter] b = StrainTensors['b'][gcounter] det = np.linalg.det u, s, vh = svd(F, full_matrices=True) vh = vh.T # print(det(u),det(vh)) # exit() if self.ndim == 2: s1 = s[0] s2 = s[1] T = np.array([[0., -1], [1, 0.]]) s1s2 = s1 + s2 if (s1s2 < 2.0): s1s2 = 2.0 lamb = 2. / (s1s2) T = 1. / np.sqrt(2) * np.dot(u, np.dot(T, vh.T)) # C_Voigt = 1.0 * ( einsum("ik,jl",I,I)+einsum("il,jk",I,I) ) - 2. * lamb * np.einsum("ij,kl", T, T) # C_Voigt = 1./ J * np.einsum("kI,lJ,iIjJ->iklj", F, F, C_Voigt) C_Voigt = 2.0 * (einsum("ik,jl", I, I)) - 2. * lamb * np.einsum( "ij,kl", T, T) # C_Voigt = 2.0 * ( einsum("ij,kl",I,I)) - 2. * lamb * np.einsum("ij,kl", T, T) C_Voigt = 1. / J * np.einsum("jJ,iJkL,lL->ijkl", F, C_Voigt, F) # Exclude the stress term from this R = u.dot(vh.T) sigma = 2. * (F - R) sigma = 1. / J * np.dot(sigma, F.T) C_Voigt -= np.einsum("ij,kl", sigma, I) # print(C_Voigt) # print(np.linalg.norm(T.flatten())) # print(Voigt(np.einsum("ij,kl", T, T),1)) # print(np.einsum("ij,kl", T, T)) # exit() C_Voigt = np.ascontiguousarray(C_Voigt) elif self.ndim == 3: s1 = s[0] s2 = s[1] s3 = s[2] T1 = np.array([[0., 0., 0.], [0., 0., -1], [0., 1., 0.]]) T1 = 1. / np.sqrt(2) * np.dot(u, np.dot(T1, vh.T)) T2 = np.array([[0., 0., -1], [0., 0., 0.], [1., 0., 0.]]) T2 = 1. / np.sqrt(2) * np.dot(u, np.dot(T2, vh.T)) T3 = np.array([[0., -1, 0.], [1., 0., 0.], [0., 0., 0.]]) T3 = 1. / np.sqrt(2) * np.dot(u, np.dot(T3, vh.T)) s1s2 = s1 + s2 s1s3 = s1 + s3 s2s3 = s2 + s3 if (s1s2 < 2.0): s1s2 = 2.0 if (s1s3 < 2.0): s1s3 = 2.0 if (s2s3 < 2.0): s2s3 = 2.0 lamb1 = 2. / (s1s2) lamb2 = 2. / (s1s3) lamb3 = 2. / (s2s3) # C_Voigt = 1.0 * ( einsum("ik,jl",I,I)+einsum("il,jk",I,I) ) - 2. * lamb3 * np.einsum("ij,kl", T1, T1) - \ # - 2. * lamb2 * np.einsum("ij,kl", T2, T2) - 2. * lamb1 * np.einsum("ij,kl", T3, T3) # C_Voigt = 1./ J * np.einsum("kI,lJ,iIjJ->iklj", F, F, C_Voigt) # C_Voigt = np.ascontiguousarray(C_Voigt) C_Voigt = 2.0 * ( einsum("ik,jl",I,I)) - 2. * lamb3 * np.einsum("ij,kl", T1, T1) - \ - 2. * lamb2 * np.einsum("ij,kl", T2, T2) - 2. * lamb1 * np.einsum("ij,kl", T3, T3) C_Voigt = 1. / J * np.einsum("jJ,iJkL,lL->ijkl", F, C_Voigt, F) C_Voigt = np.ascontiguousarray(C_Voigt) R = u.dot(vh.T) sigma = 2. * (F - R) sigma = 1. / J * np.dot(sigma, F.T) C_Voigt -= np.einsum("ij,kl", sigma, I) # s1 = s[0] # s2 = s[1] # s3 = s[2] # T1 = np.array([[0.,-1.,0.],[1.,0.,0],[0.,0.,0.]]) # T1 = 1./np.sqrt(2) * np.dot(u, np.dot(T1, vh.T)) # T2 = np.array([[0.,0.,0.],[0.,0., 1],[0.,-1,0.]]) # T2 = 1./np.sqrt(2) * np.dot(u, np.dot(T2, vh.T)) # T3 = np.array([[0.,0.,1.],[0.,0.,0.],[-1,0.,0.]]) # T3 = 1./np.sqrt(2) * np.dot(u, np.dot(T3, vh.T)) # s1s2 = s1 + s2 # s1s3 = s1 + s3 # s2s3 = s2 + s3 # # if (s1s2 < 2.0): # # s1s2 = 2.0 # # if (s1s3 < 2.0): # # s1s3 = 2.0 # # if (s2s3 < 2.0): # # s2s3 = 2.0 # lamb1 = 2. / (s1s2) # lamb2 = 2. / (s1s3) # lamb3 = 2. / (s2s3) # # C_Voigt = 1.0 * ( einsum("ik,jl",I,I)+einsum("il,jk",I,I) ) - 2. * lamb1 * np.einsum("ij,kl", T1, T1) - \ # # - 2. * lamb3 * np.einsum("ij,kl", T2, T2) - 2. * lamb2 * np.einsum("ij,kl", T3, T3) # # C_Voigt = 1./ J * np.einsum("kI,lJ,iIjJ->iklj", F, F, C_Voigt) # # C_Voigt = np.ascontiguousarray(C_Voigt) # C_Voigt = 2.0 * ( einsum("ik,jl",I,I)) - 2. * lamb1 * np.einsum("ij,kl", T1, T1) - \ # - 2. * lamb3 * np.einsum("ij,kl", T2, T2) - 2. * lamb2 * np.einsum("ij,kl", T3, T3) # C_Voigt = 1./ J * np.einsum("kI,lJ,iIjJ->iklj", F, F, C_Voigt) # C_Voigt = np.ascontiguousarray(C_Voigt) # R = u.dot(vh.T) # sigma = 2. * (F - R) # sigma = 1./J * np.dot(sigma, F.T) # C_Voigt -= np.einsum("ij,kl",sigma,I) C_Voigt = Voigt(C_Voigt, 1) makezero(C_Voigt) # C_Voigt = np.eye(3,3)*2 # C_Voigt += 0.05*self.vIikIjl # print(C_Voigt) # s = svd(C_Voigt)[1] # print(s) return C_Voigt
def NodeArrangementQuadToTri(C): nsize = int((C + 2) * (C + 3) / 2.) node_arranger = np.zeros((2, nsize), dtype=np.int64) if C == 0: node_arranger[0, :] = [0, 1, 3] node_arranger[1, :] = [1, 2, 3] elif C == 1: node_arranger[0, :] = [0, 1, 3, 4, 5, 6] node_arranger[1, :] = [1, 2, 3, 7, 6, 8] elif C == 2: node_arranger[0, :] = [0, 1, 3, 4, 5, 6, 7, 8, 10, 11] node_arranger[1, :] = [1, 2, 3, 9, 13, 8, 12, 15, 11, 14] elif C == 3: node_arranger[0, :] = [ 0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 12, 13, 14, 17, 18 ] node_arranger[1, :] = [ 1, 2, 3, 11, 16, 21, 10, 15, 20, 24, 14, 19, 23, 18, 22 ] elif C == 4: node_arranger[0, :] = [ 0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15, 16, 17, 20, 21, 22, 26, 27 ] node_arranger[1, :] = [ 1, 2, 3, 13, 19, 25, 31, 12, 18, 24, 30, 35, 17, 23, 29, 34, 22, 28, 33, 27, 32 ] elif C == 5: node_arranger[0, :] = [ 0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 18, 19, 20, 23, 24, 25, 26, 30, 31, 32, 37, 38 ] node_arranger[1, :] = [ 1, 2, 3, 15, 22, 29, 36, 43, 14, 21, 28, 35, 42, 48, 20, 27, 34, 41, 47, 26, 33, 40, 46, 32, 39, 45, 38, 44 ] else: raise NotImplementedError( 'Conversion beynond p=6 nodes not implemented yet') # THIS FLOATING POINT APPROACH COMAPRES TRI AND QUAD # POINTS TO GET NUMBERING, BUT DOESNOT WORK FOR NOT # EQUALLY DISTANCED POINTS AS FEKETE POINTS ON TRIS # DON'T MATCH GAUSS LOBATTO POINTS OF QUADS FOR THE # INTERIOR NODES from .GaussLobattoPoints import GaussLobattoPointsQuad from .FeketePointsTri import FeketePointsTri from Florence.Tensor import in2d, makezero, unique2d epst = FeketePointsTri(C) epsq = GaussLobattoPointsQuad(C) makezero(epst, tol=1e-12) makezero(epsq, tol=1e-12) aranger = np.arange(int((C + 2)**2)) # makezero(epst) # TAKES CARE OF -0. AND +0. FOR IN2D # T1_idx = in2d(epsq,epst) # T1 = aranger[T1_idx] T1 = np.array(__QuadToTriArrangement__(epsq, epst)) # MAP THE OTHER TRIANGLE # MAP: x_n = -y; y_n = 1+x+y epst_mirror = np.zeros_like(epst) epst_mirror[:, 0] = -epst[:, 1] epst_mirror[:, 1] = 1 + epst[:, 0] + epst[:, 1] # makezero(epst_mirror) # TAKES CARE OF -0. AND +0. FOR IN2D T2 = np.array(__QuadToTriArrangement__(epsq, epst_mirror)) node_arranger[0, :] = T1 node_arranger[1, :] = T2 return node_arranger
def GetLocalStiffness(self, function_space, material, LagrangeElemCoords, EulerElemCoords, fem_solver, elem=0): """Get stiffness matrix of the system""" nvar = self.nvar ndim = self.ndim nodeperelem = function_space.Bases.shape[0] det = np.linalg.det inv = np.linalg.inv Jm = function_space.Jm AllGauss = function_space.AllGauss # ALLOCATE stiffness = np.zeros((nodeperelem * nvar, nodeperelem * nvar), dtype=np.float64) tractionforce = np.zeros((nodeperelem * nvar, 1), dtype=np.float64) B = np.zeros((nodeperelem * nvar, material.H_VoigtSize), dtype=np.float64) # COMPUTE KINEMATIC MEASURES AT ALL INTEGRATION POINTS USING EINSUM (AVOIDING THE FOR LOOP) # MAPPING TENSOR [\partial\vec{X}/ \partial\vec{\varepsilon} (ndim x ndim)] ParentGradientX = np.einsum('ijk,jl->kil', Jm, LagrangeElemCoords) # ParentGradientX = [np.eye(3,3)] # MATERIAL GRADIENT TENSOR IN PHYSICAL ELEMENT [\nabla_0 (N)] MaterialGradient = np.einsum('ijk,kli->ijl', inv(ParentGradientX), Jm) # DEFORMATION GRADIENT TENSOR [\vec{x} \otimes \nabla_0 (N)] F = np.einsum('ij,kli->kjl', EulerElemCoords, MaterialGradient) # COMPUTE REMAINING KINEMATIC MEASURES StrainTensors = KinematicMeasures(F, fem_solver.analysis_nature) # SPATIAL GRADIENT AND MATERIAL GRADIENT TENSORS ARE EQUAL SpatialGradient = np.einsum('ikj', MaterialGradient) # COMPUTE ONCE detJ detJ = np.einsum('i,i->i', AllGauss[:, 0], det(ParentGradientX)) # detJ = np.einsum('i,i,i->i', AllGauss[:,0], det(ParentGradientX), StrainTensors['J']) # LOOP OVER GAUSS POINTS for counter in range(AllGauss.shape[0]): # COMPUTE THE HESSIAN AT THIS GAUSS POINT H_Voigt = material.Hessian(StrainTensors, None, elem, counter) # COMPUTE CAUCHY STRESS TENSOR CauchyStressTensor = [] if fem_solver.requires_geometry_update: CauchyStressTensor = material.CauchyStress( StrainTensors, None, elem, counter) # COMPUTE THE TANGENT STIFFNESS MATRIX BDB_1, t = self.ConstitutiveStiffnessIntegrand( B, SpatialGradient[counter, :, :], StrainTensors['F'][counter], CauchyStressTensor, H_Voigt, requires_geometry_update=fem_solver.requires_geometry_update) # INTEGRATE TRACTION FORCE if fem_solver.requires_geometry_update: tractionforce += t * detJ[counter] # INTEGRATE STIFFNESS stiffness += BDB_1 * detJ[counter] makezero(stiffness, 1e-12) # print(stiffness) # print(tractionforce) # exit() return stiffness, tractionforce
def PointInversionIsoparametricFEM(element_type, C, LagrangeElemCoords, point, equally_spaced=False, tolerance=1.0e-7, maxiter=20, verbose=False, use_simple_bases=False, initial_guess=None): """ This is the inverse isoparametric map, in that given a physical point, find the isoparametric coordinates, provided that the coordinates of physical element 'LagrangeElemCoords' is known input: point: [2S(3D) vector] containing X,Y,(Z) value of the physical point return: iso_parametric_point [2S(3D) vector] containing X,Y,(Z) value of the parametric point convergence_info [boolean] if the iteration converged or not """ from Florence.FunctionSpace import Tri, Tet, Quad, QuadES, Hex, HexES, Pent from Florence.Tensor import makezero # INITIAL GUESS - VERY IMPORTANT if initial_guess is None: if use_simple_bases: p_isoparametric = np.zeros(LagrangeElemCoords.shape[1]) else: p_isoparametric = -np.ones(LagrangeElemCoords.shape[1]) else: p_isoparametric = initial_guess residual = 0. blow_up_value = 1e10 convergence_info = False for niter in range(maxiter): # Using the current iterative solution of isoparametric coordinate evaluate bases and gradient of bases if element_type == "tet": if not use_simple_bases: Neval, gradient = Tet.hpNodal.hpBases( C, p_isoparametric[0], p_isoparametric[1], p_isoparametric[2], False, 1, equally_spaced=equally_spaced) else: Neval, gradient = hpBasesTetSimple(p_isoparametric[0], p_isoparametric[1], p_isoparametric[2]) elif element_type == "hex": if not equally_spaced: Neval = Hex.LagrangeGaussLobatto(C, p_isoparametric[0], p_isoparametric[1], p_isoparametric[2]).flatten() gradient = Hex.GradLagrangeGaussLobatto( C, p_isoparametric[0], p_isoparametric[1], p_isoparametric[2]) else: Neval = HexES.Lagrange(C, p_isoparametric[0], p_isoparametric[1], p_isoparametric[2]).flatten() gradient = HexES.GradLagrange(C, p_isoparametric[0], p_isoparametric[1], p_isoparametric[2]) elif element_type == "tri": if not use_simple_bases: Neval, gradient = Tri.hpNodal.hpBases( C, p_isoparametric[0], p_isoparametric[1], True, 1, equally_spaced=equally_spaced) else: Neval, gradient = hpBasesTriSimple(p_isoparametric[0], p_isoparametric[1]) elif element_type == "quad": if not use_simple_bases: if not equally_spaced: Neval = Quad.LagrangeGaussLobatto( C, p_isoparametric[0], p_isoparametric[1]).flatten() gradient = Quad.GradLagrangeGaussLobatto( C, p_isoparametric[0], p_isoparametric[1]) else: Neval = QuadES.Lagrange(C, p_isoparametric[0], p_isoparametric[1]).flatten() gradient = QuadES.GradLagrange(C, p_isoparametric[0], p_isoparametric[1]) else: Neval, gradient = hpBasesQuadSimple(p_isoparametric[0], p_isoparametric[1]) elif element_type == "pent": Neval, gradient = Pent.PentBases(C, p_isoparametric[0], p_isoparametric[1]) makezero(np.atleast_2d(Neval)) makezero(gradient) # Find the residual X - X(N) [i.e. point - FEM interpolated point] residual = point - np.dot(Neval, LagrangeElemCoords) # print(np.dot(Neval,LagrangeElemCoords)) # Find the isoparametric (Jacobian) matrix dX/d\Xi ParentGradientX = np.dot(gradient.T, LagrangeElemCoords) # ParentGradientX = np.fliplr(ParentGradientX) # Solve and update incremental solution old_p_isoparametric = np.copy(p_isoparametric) # print(p_isoparametric) try: # p_isoparametric += np.dot(np.linalg.inv(ParentGradientX), residual) p_isoparametric += np.linalg.solve(ParentGradientX, residual) except: convergence_info = False break # CHECK IF WITHIN TOLERANCE if norm(p_isoparametric - old_p_isoparametric) < tolerance: convergence_info = True break # print(norm(residual)) if norm(residual) < tolerance * 1e2: convergence_info = True break # OTHERWISE DEAL WITH BLOW UP SITUATION if np.isnan(norm(residual)) > blow_up_value or norm( residual) > blow_up_value: break if np.isnan(norm( p_isoparametric)) or norm(p_isoparametric) > blow_up_value: break if verbose: return p_isoparametric, convergence_info return p_isoparametric
def HighOrderMeshLine(C, mesh, Decimals=10, equally_spaced=False, check_duplicates=True, Parallel=False, nCPU=1): from Florence.FunctionSpace import Line from Florence.QuadratureRules import GaussLobattoPoints1D from Florence.QuadratureRules.EquallySpacedPoints import EquallySpacedPoints from Florence.MeshGeneration.NodeArrangement import NodeArrangementLine # ARRANGE NODES FOR LINES HERE (DONE ONLY FOR LINES) - IMPORTANT node_aranger = NodeArrangementLine(C) if not equally_spaced: eps = GaussLobattoPoints1D(C).ravel() eps = eps[node_aranger] # COMPUTE BASES FUNCTIONS AT ALL NODAL POINTS Neval = np.zeros((2, eps.shape[0]), dtype=np.float64) for i in range(0, eps.shape[0]): Neval[:, i] = Line.LagrangeGaussLobatto(0, eps[i])[0] else: eps = EquallySpacedPoints(2, C).ravel() eps = eps[node_aranger] # COMPUTE BASES FUNCTIONS AT ALL NODAL POINTS Neval = np.zeros((2, eps.shape[0]), dtype=np.float64) for i in range(0, eps.shape[0]): Neval[:, i] = Line.Lagrange(0, eps[i])[0] makezero(Neval) nodeperelem = mesh.elements.shape[1] renodeperelem = int(C + 2) left_over_nodes = renodeperelem - nodeperelem reelements = -1 * np.ones( (mesh.elements.shape[0], renodeperelem), dtype=np.int64) reelements[:, :2] = mesh.elements iesize = int(C) repoints = np.zeros( (mesh.points.shape[0] + iesize * mesh.elements.shape[0], mesh.points.shape[1]), 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(ElementLoopTri, np.arange(0, mesh.elements.shape[0]), mesh.elements, mesh.points, 'line', eps, Neval, pool=MP.Pool(processes=nCPU)) # LOOP OVER ELEMENTS maxNode = np.max(reelements) for elem in range(0, mesh.elements.shape[0]): # GET HIGHER ORDER COORDINATES if Parallel: xycoord_higher = ParallelTuple1[elem] else: xycoord_higher = GetInteriorNodesCoordinates( mesh.points[mesh.elements[elem, :], :], 'line', elem, eps, Neval) # EXPAND THE ELEMENT CONNECTIVITY newElements = np.arange(maxNode + 1, maxNode + 1 + left_over_nodes) # reelements[elem,3:] = np.arange(maxNode+1,maxNode+1+left_over_nodes) reelements[elem, 2:] = newElements maxNode = newElements[-1] repoints[mesh.points.shape[0] + elem * iesize:mesh.points.shape[0] + (elem + 1) * iesize] = xycoord_higher[2:, :] 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 = 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) del rounded_repoints idx_repoints = np.concatenate( (np.arange(nnode_linear), idx_repoints + nnode_linear)) repoints = repoints[idx_repoints, :] unique_reelements, inv_reelements = np.unique(reelements[:, 2:], return_inverse=True) unique_reelements = unique_reelements[inv_repoints] reelements = unique_reelements[inv_reelements] reelements = reelements.reshape(mesh.elements.shape[0], renodeperelem - 2) 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 #------------------------------------------------------------------------------------------ class nmesh(object): points = repoints elements = reelements edges = [] faces = [] nnode = repoints.shape[0] nelem = reelements.shape[0] info = 'line' # MESH CORNERS REMAIN THE SAME FOR ALL POLYNOMIAL DEGREES if isinstance(mesh.corners, np.ndarray): nmesh.corners = mesh.corners return nmesh
>>>>>>> upstream/master # COMPUTE BASES FUNCTIONS AT ALL NODAL POINTS Neval = np.zeros((2,eps.shape[0]),dtype=np.float64) for i in range(0,eps.shape[0]): Neval[:,i] = Line.LagrangeGaussLobatto(0,eps[i])[0] else: eps = EquallySpacedPoints(2,C).ravel() <<<<<<< HEAD ======= eps = eps[node_aranger] >>>>>>> upstream/master # COMPUTE BASES FUNCTIONS AT ALL NODAL POINTS Neval = np.zeros((2,eps.shape[0]),dtype=np.float64) for i in range(0,eps.shape[0]): Neval[:,i] = Line.Lagrange(0,eps[i])[0] makezero(Neval) <<<<<<< HEAD ======= >>>>>>> upstream/master nodeperelem = mesh.elements.shape[1] renodeperelem = int(C+2) left_over_nodes = renodeperelem - nodeperelem reelements = -1*np.ones((mesh.elements.shape[0],renodeperelem),dtype=np.int64) reelements[:,:2] = mesh.elements iesize = int(C) repoints = np.zeros((mesh.points.shape[0]+iesize*mesh.elements.shape[0],mesh.points.shape[1]),dtype=np.float64) repoints[:mesh.points.shape[0],:]=mesh.points
def GetIdealElement(self, elem, fem_solver, function_space, LagrangeElemCoords): """Retrieves ideal element/domain """ from Florence.Tensor import makezero from Florence.FunctionSpace import Tri, Tet, Quad, Hex from Florence.QuadratureRules.EquallySpacedPoints import EquallySpacedPoints, EquallySpacedPointsTri, EquallySpacedPointsTet sqrt = np.sqrt if function_space.element_type == "tri": nodeperlinearelem = 3 eps = EquallySpacedPointsTri(function_space.degree - 1) hpBases = Tri.hpNodal.hpBases Neval = np.zeros((nodeperlinearelem, eps.shape[0]), dtype=np.float64) for i in range(0, eps.shape[0]): Neval[:, i] = hpBases(0, eps[i, 0], eps[i, 1], Transform=1, EvalOpt=1, equally_spaced=True)[0] xycoord = LagrangeElemCoords[:nodeperlinearelem, :] xycoord = np.array([[-0.5, 0], [0.5, 0], [0., np.sqrt(3.) / 2.]]) # xycoord = eps[:nodeperlinearelem,:] # xycoord = fem_solver.imesh.points[elem,:] elif function_space.element_type == "quad": nodeperlinearelem = 4 eps = EquallySpacedPoints(3, function_space.degree - 1) hpBases = Quad.LagrangeGaussLobatto Neval = np.zeros((nodeperlinearelem, eps.shape[0]), dtype=np.float64) for i in range(0, eps.shape[0]): Neval[:, i] = hpBases(0, eps[i, 0], eps[i, 1], arrange=1)[:, 0] xycoord = LagrangeElemCoords[:nodeperlinearelem, :] xycoord = np.array([[0., 0], [1., 0], [1., 1.], [0., 1.]]) xycoord = eps[:nodeperlinearelem, :] elif function_space.element_type == "tet": nodeperlinearelem = 4 eps = EquallySpacedPointsTet(function_space.degree - 1) hpBases = Tet.hpNodal.hpBases Neval = np.zeros((nodeperlinearelem, eps.shape[0]), dtype=np.float64) for i in range(0, eps.shape[0]): Neval[:, i] = hpBases(0, eps[i, 0], eps[i, 1], eps[i, 2], Transform=1, EvalOpt=1, equally_spaced=True)[0] xycoord = LagrangeElemCoords[:nodeperlinearelem, :] xycoord = np.array([[sqrt(8. / 9.), 0, -1 / 3.], [-sqrt(2. / 9.), sqrt(2. / 3.), -1 / 3.], [-sqrt(2. / 9.), -sqrt(2. / 3.), -1 / 3.], [0., 0, 1.]]) elif function_space.element_type == "hex": nodeperlinearelem = 8 eps = EquallySpacedPoints(4, function_space.degree - 1) hpBases = Hex.LagrangeGaussLobatto Neval = np.zeros((nodeperlinearelem, eps.shape[0]), dtype=np.float64) for i in range(0, eps.shape[0]): Neval[:, i] = hpBases(0, eps[i, 0], eps[i, 1], eps[i, 2], arrange=1)[:, 0] xycoord = LagrangeElemCoords[:nodeperlinearelem, :] xycoord = eps[:nodeperlinearelem, :] makezero(Neval) xycoord_higher = np.copy(LagrangeElemCoords) xycoord_higher[:nodeperlinearelem, :] = xycoord if function_space.degree > 1: xycoord_higher[nodeperlinearelem:, :] = np.dot( Neval[:, nodeperlinearelem:].T, xycoord) LagrangeElemCoords = xycoord_higher return LagrangeElemCoords
def HighOrderMeshTri_SEMISTABLE(C, mesh, Decimals=10, equally_spaced=False, check_duplicates=True, Parallel=False, nCPU=1, ComputeAll=False): from Florence.FunctionSpace import Tri from Florence.QuadratureRules.FeketePointsTri import FeketePointsTri from Florence.MeshGeneration.NodeArrangement import NodeArrangementTri # SWITCH OFF MULTI-PROCESSING FOR SMALLER PROBLEMS WITHOUT GIVING A MESSAGE if (mesh.elements.shape[0] < 1000) and (C < 8): Parallel = False nCPU = 1 if not equally_spaced: eps = FeketePointsTri(C) # COMPUTE BASES FUNCTIONS AT ALL NODAL POINTS hpBases = Tri.hpNodal.hpBases Neval = np.zeros((3, eps.shape[0]), dtype=np.float64) for i in range(3, eps.shape[0]): Neval[:, i] = hpBases(0, eps[i, 0], eps[i, 1], 1)[0] else: from Florence.QuadratureRules.EquallySpacedPoints import EquallySpacedPointsTri eps = EquallySpacedPointsTri(C) # COMPUTE BASES FUNCTIONS AT ALL NODAL POINTS hpBases = Tri.hpNodal.hpBases Neval = np.zeros((3, eps.shape[0]), dtype=np.float64) for i in range(3, eps.shape[0]): Neval[:, i] = hpBases(0, eps[i, 0], eps[i, 1], Transform=1, EvalOpt=1, equally_spaced=True)[0] # THIS IS NECESSARY FOR REMOVING DUPLICATES makezero(Neval, tol=1e-12) nodeperelem = mesh.elements.shape[1] renodeperelem = int((C + 2.) * (C + 3.) / 2.) left_over_nodes = renodeperelem - nodeperelem reelements = -1 * np.ones( (mesh.elements.shape[0], renodeperelem), dtype=np.int64) reelements[:, :3] = mesh.elements iesize = int(C * (C + 5.) / 2.) repoints = np.zeros( (mesh.points.shape[0] + iesize * mesh.elements.shape[0], mesh.points.shape[1]), dtype=np.float64) # repoints[:mesh.points.shape[0],:]=mesh.points[:,:2] repoints[:mesh.points.shape[0], :] = mesh.points pshape0, pshape1 = mesh.points.shape[0], mesh.points.shape[1] repshape0, repshape1 = repoints.shape[0], repoints.shape[1] telements = time() xycoord_higher = [] ParallelTuple1 = [] if Parallel: # GET HIGHER ORDER COORDINATES - PARALLEL ParallelTuple1 = parmap.map(ElementLoopTri, np.arange(0, mesh.elements.shape[0]), mesh.elements, mesh.points, 'tri', eps, Neval, pool=MP.Pool(processes=nCPU)) # LOOP OVER ELEMENTS maxNode = np.max(reelements) for elem in range(0, mesh.elements.shape[0]): # GET HIGHER ORDER COORDINATES if Parallel: xycoord_higher = ParallelTuple1[elem] else: # xycoord = mesh.points[mesh.elements[elem,:],:] xycoord_higher = GetInteriorNodesCoordinates( mesh.points[mesh.elements[elem, :], :], 'tri', elem, eps, Neval) # EXPAND THE ELEMENT CONNECTIVITY newElements = np.arange(maxNode + 1, maxNode + 1 + left_over_nodes) # reelements[elem,3:] = np.arange(maxNode+1,maxNode+1+left_over_nodes) reelements[elem, 3:] = newElements maxNode = newElements[-1] repoints[mesh.points.shape[0] + elem * iesize:mesh.points.shape[0] + (elem + 1) * iesize] = xycoord_higher[3:, :] 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 = repoints[nnode_linear:, :].copy() makezero(rounded_repoints) rounded_repoints = np.round(rounded_repoints, decimals=Decimals) # flattened_repoints = np.ascontiguousarray(rounded_repoints).view(np.dtype((np.void, # rounded_repoints.dtype.itemsize * rounded_repoints.shape[1]))) # _, idx_repoints, inv_repoints = np.unique(flattened_repoints,return_index=True,return_inverse=True) _, idx_repoints, inv_repoints = unique2d(rounded_repoints, order=False, consider_sort=False, return_index=True, return_inverse=True) del rounded_repoints idx_repoints = np.concatenate( (np.arange(nnode_linear), idx_repoints + nnode_linear)) repoints = repoints[idx_repoints, :] unique_reelements, inv_reelements = np.unique(reelements[:, 3:], return_inverse=True) unique_reelements = unique_reelements[inv_repoints] reelements = unique_reelements[inv_reelements] reelements = reelements.reshape(mesh.elements.shape[0], renodeperelem - 3) 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 #------------------------------------------------------------------------------------------ # BUILD EDGES NOW #------------------------------------------------------------------------------------------ tedges = time() edge_to_elements = mesh.GetElementsWithBoundaryEdgesTri() node_arranger = NodeArrangementTri(C)[0] reedges = np.zeros((mesh.edges.shape[0], C + 2), dtype=np.int64) # for i in range(mesh.edges.shape[0]): # reedges[i,:] = reelements[edge_to_elements[i,0],node_arranger[edge_to_elements[i,1],:]] reedges = reelements[edge_to_elements[:, 0][:, None], node_arranger[edge_to_elements[:, 1], :]] tedges = time() - tedges #------------------------------------------------------------------------------------------ class nmesh(object): # """Construct pMesh""" points = repoints elements = reelements edges = reedges faces = np.array([[], []]) nnode = repoints.shape[0] nelem = reelements.shape[0] info = 'tri' # print '\npMeshing timing:\n\t\tElement loop 1:\t '+str(telements)+' seconds\n\t\tNode loop:\t\t '+str(tnodes)+\ # ' seconds'+'\n\t\tElement loop 2:\t '+str(telements_2)+' seconds\n\t\tEdge loop:\t\t '+str(tedges)+' seconds\n' return nmesh
def Hessian(self, StrainTensors, ElectricDisplacementx, elem=0, gcounter=0): mu = self.mu lamb = self.lamb d = self.ndim I = StrainTensors['I'] F = StrainTensors['F'][gcounter] J = StrainTensors['J'][gcounter] b = StrainTensors['b'][gcounter] det = np.linalg.det u, s, vh = svd(F, full_matrices=True) # u, s, vh = np.linalg.svd(F, full_matrices=True) vh = vh.T # print(u) # print(s) # print(vh) # exit() R = u.dot(vh.T) S = np.dot(vh, np.dot(np.diag(s), vh.T)) g = vec(dJdF(F)) J2 = J**2 J3 = J**3 J4 = J**4 f = vec(F) r = vec(R) HJ = d2JdFdF(F) if self.ndim == 2: # HJ = np.eye(4,4); HJ = np.fliplr(HJ); HJ[1,2] = -1; HJ[2,1] = -1; I1 = trace(S) I2 = trace(b) T = np.array([[0., -1], [1, 0.]]) T = 1. / np.sqrt(2.) * np.dot(u, np.dot(T, vh.T)) t = vec(T) H = 2. * (1 + 1 / J2) * np.eye(4, 4) H -= 4. / J3 * (np.outer(g, f) + np.outer(f, g)) H += 2. / J2 * (np.outer(g, r) + np.outer(r, g)) H += 2. / J2 * (I1 - I2 / J) * HJ H += 2. / J3 * (3. * I2 / J - 2. * I1) * np.outer(g, g) H -= 4. / I1 * (1. + 1. / J) * np.outer(t, t) elif self.ndim == 3: # sigma0 = S[0,0] # sigma1 = S[1,1] # sigma2 = S[2,2] # sigma0 = s[0] # sigma1 = s[1] # sigma2 = s[2] # sqrt = np.sqrt # # def sqrt(x): return x # lambdas = [ # (sigma0 ** 4 * sigma1 ** 3 + sigma0 ** 3 * sigma1 ** 4 - 2 * sigma0 ** 3 * sigma1 ** 3 + sigma0 ** 3 * sigma1 - sigma0 ** 3 + sigma0 * sigma1 ** 3 - sigma1 ** 3) / (sigma0 ** 3 * sigma1 ** 3 * (sigma0 + sigma1)), # (sigma1 ** 4 * sigma2 ** 3 + sigma1 ** 3 * sigma2 ** 4 - 2 * sigma1 ** 3 * sigma2 ** 3 + sigma1 ** 3 * sigma2 - sigma1 ** 3 + sigma1 * sigma2 ** 3 - sigma2 ** 3) / (sigma1 ** 3 * sigma2 ** 3 * (sigma1 + sigma2)), # (sigma0 ** 4 * sigma2 ** 3 + sigma0 ** 3 * sigma2 ** 4 - 2 * sigma0 ** 3 * sigma2 ** 3 + sigma0 ** 3 * sigma2 - sigma0 ** 3 + sigma0 * sigma2 ** 3 - sigma2 ** 3) / (sigma0 ** 3 * sigma2 ** 3 * (sigma0 + sigma2)), # (sigma0 ** 3 * sigma1 ** 3 - sigma0 ** 2 * sigma1 + sigma0 ** 2 - sigma0 * sigma1 ** 2 + sigma0 * sigma1 + sigma1 ** 2) / (sigma0 ** 3 * sigma1 ** 3), # (sigma1 ** 3 * sigma2 ** 3 - sigma1 ** 2 * sigma2 + sigma1 ** 2 - sigma1 * sigma2 ** 2 + sigma1 * sigma2 + sigma2 ** 2) / (sigma1 ** 3 * sigma2 ** 3), # (sigma0 ** 3 * sigma2 ** 3 - sigma0 ** 2 * sigma2 + sigma0 ** 2 - sigma0 * sigma2 ** 2 + sigma0 * sigma2 + sigma2 ** 2) / (sigma0 ** 3 * sigma2 ** 3), # (sigma0 ** 4 - 2 * sigma0 + 3) / sigma0 ** 4, # (sigma1 ** 4 - 2 * sigma1 + 3) / sigma1 ** 4, # (sigma2 ** 4 - 2 * sigma2 + 3) / sigma2 ** 4 # ] # qs = [[0, 0, 0, 0, 0, 0, 1, 0, 0], # [sqrt(2) / 2, 0, 0, sqrt(2) / 2, 0, 0, 0, 0, 0], # [0, 0, -sqrt(2) / 2, 0, 0, sqrt(2) / 2, 0, 0, 0], # [-sqrt(2) / 2, 0, 0, sqrt(2) / 2, 0, 0, 0, 0, 0], # [0, 0, 0, 0, 0, 0, 0, 1, 0], # [0, -sqrt(2) / 2, 0, 0, sqrt(2) / 2, 0, 0, 0, 0], # [0, 0, sqrt(2) / 2, 0, 0, sqrt(2) / 2, 0, 0, 0], # [0, sqrt(2) / 2, 0, 0, sqrt(2) / 2, 0, 0, 0, 0], # [0, 0, 0, 0, 0, 0, 0, 0, 1] # ] # qs = np.array(qs).T # H = np.zeros((9,9)) # # mm = 1./np.sqrt(2.) # mm=1. # for i in range(9): # # Qi = qs[i].reshape(3,3) # # Qi = mm * np.dot(u, np.dot(Qi, vh.T)) # # qi = vec(Qi) # qi = qs[i] # # print(lambdas[i]) # H += lambdas[i] * np.outer(qi,qi) # # H += np.max([lambdas[i], 0.]) * np.outer(qi,qi) # # print(H) # return H def DFDF(index): # i = np.mod(index - 1, 3); # j = np.floor((index - 1) / 3); i = np.mod(index, 3) j = np.floor((index) / 3) i = int(i) j = int(j) DF = np.zeros((3, 3)) DF[i, j] = 1 return DF def IIC_Hessian(F): H = np.zeros((9, 9)) for i in range(9): DF = DFDF(i) # print(DF) # exit() # A = 4 * (DF * F' * F + F * F' * DF + F * DF' * F); A = 4 * (DF.dot(F.T.dot(F)) + F.dot(F.T.dot(DF)) + F.dot(DF.T.dot(F))) # print(A) column = A.T.reshape(9) H[:, i] = column return H def IIC_Star_Hessian(F): IC = np.trace(F.T.dot(F)) H = 2 * IC * np.eye(9, 9) f = vec(F) H = H + 4 * np.outer(f, f) # print(H) IIC_H = IIC_Hessian(F) H = H - 2 * (IIC_H / 4.) return H # F = np.arange(9) + 1; F = F.reshape(3,3).T; F[2,2] = 50; F=F.astype(float) # # print(F) # xx = IIC_Star_Hessian(F) # # xx = IIC_Hessian(F) # # xx = IIC_Hessian(F) # print(xx) # exit() C = F.T.dot(F) IC = trace(C) IIC = trace(C.dot(C)) IIStarC = 0.5 * (IC**2 - IIC) dIIStarC = 2 * IC * F - 2 * np.dot(F, np.dot(F.T, F)) t = vec(dIIStarC) d2IIStarC = IIC_Star_Hessian(F) H = 2. * np.eye(9, 9) H -= 2. / J3 * (np.outer(g, t) + np.outer(t, g)) H += 6. * IIStarC / J4 * np.outer(g, g) H += 1. / J2 * d2IIStarC H -= 2. * IIStarC / J3 * d2JdFdF(F) # print(H) s0 = s[0] s1 = s[1] s2 = s[2] # s0 = S[0,0] # s1 = S[1,1] # s2 = S[2,2] T1 = np.array([[0., -1., 0.], [1., 0., 0], [0., 0., 0.]]) T1 = 1. / np.sqrt(2) * np.dot(u, np.dot(T1, vh.T)) T2 = np.array([[0., 0., 0.], [0., 0., 1], [0., -1., 0.]]) T2 = 1. / np.sqrt(2) * np.dot(u, np.dot(T2, vh.T)) T3 = np.array([[0., 0., 1.], [0., 0., 0.], [-1, 0., 0.]]) T3 = 1. / np.sqrt(2) * np.dot(u, np.dot(T3, vh.T)) s0s1 = s0 + s1 s0s2 = s0 + s2 s1s2 = s1 + s2 # if (s0s1 < 2.0): # s0s1 = 2.0 # if (s0s2 < 2.0): # s0s2 = 2.0 # if (s1s2 < 2.0): # s1s2 = 2.0 lamb1 = 2. / (s0s1) lamb2 = 2. / (s0s2) lamb3 = 2. / (s1s2) t1 = vec(T1) t2 = vec(T2) t3 = vec(T3) dRdF = (lamb1) * np.outer(t1, t1) dRdF += (lamb3) * np.outer(t2, t2) dRdF += (lamb2) * np.outer(t3, t3) # print(dRdF) IS = trace(S) IIS = trace(b) IIStarS = 0.5 * (IS * IS - IIS) newH = (1 + IS / J) * dRdF + (1 / J) * np.outer(r, r) newH = newH - (IS / J2) * (np.outer(g, r) + np.outer(r, g)) newH = newH + (2.0 * IIStarS / J3) * np.outer(g, g) newH = newH - (IIStarS / J2) * HJ newH = newH + (1 / J2) * (np.outer(g, f) + np.outer(f, g)) newH = newH - (1 / J) * np.eye(9, 9) H = H - 2.0 * newH H = H / 2. makezero(H) # print(H) # exit() # s = np.linalg.svd(C_Voigt)[1] # print(s) # exit() C_Voigt = H self.H_VoigtSize = H.shape[0] return C_Voigt
def HighOrderMeshTet_SEMISTABLE(C, mesh, Decimals=10, equally_spaced=False, check_duplicates=True, parallelise=False, nCPU=1, compute_boundary_info=True): from Florence.FunctionSpace import Tet from Florence.QuadratureRules.FeketePointsTet import FeketePointsTet from Florence.MeshGeneration.NodeArrangement import NodeArrangementTet # SWITCH OFF MULTI-PROCESSING FOR SMALLER PROBLEMS WITHOUT GIVING A MESSAGE Parallel = parallelise if (mesh.elements.shape[0] < 500) and (C < 5): Parallel = False nCPU = 1 if not equally_spaced: eps = FeketePointsTet(C) # COMPUTE BASES FUNCTIONS AT ALL NODAL POINTS Neval = np.zeros((4, eps.shape[0]), dtype=np.float64) hpBases = Tet.hpNodal.hpBases for i in range(4, eps.shape[0]): Neval[:, i] = hpBases(0, eps[i, 0], eps[i, 1], eps[i, 2], Transform=1, EvalOpt=1)[0] else: from Florence.QuadratureRules.EquallySpacedPoints import EquallySpacedPointsTet eps = EquallySpacedPointsTet(C) # COMPUTE BASES FUNCTIONS AT ALL NODAL POINTS hpBases = Tet.hpNodal.hpBases Neval = np.zeros((4, eps.shape[0]), dtype=np.float64) for i in range(4, eps.shape[0]): Neval[:, i] = hpBases(0, eps[i, 0], eps[i, 1], eps[i, 2], Transform=1, EvalOpt=1, equally_spaced=True)[0] # THIS IS NECESSARY FOR REMOVING DUPLICATES makezero(Neval, tol=1e-12) nodeperelem = mesh.elements.shape[1] renodeperelem = int((C + 2.) * (C + 3.) * (C + 4.) / 6.) left_over_nodes = renodeperelem - nodeperelem reelements = -1 * np.ones( (mesh.elements.shape[0], renodeperelem), dtype=np.int64) reelements[:, :4] = mesh.elements # TOTAL NUMBER OF (INTERIOR+EDGE+FACE) NODES iesize = np.int64(C * (C - 1) * (C - 2) / 6. + 6. * C + 2 * C * (C - 1)) 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, 'tet', 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, 'tet', elem, eps, Neval) # EXPAND THE ELEMENT CONNECTIVITY newElements = np.arange(maxNode + 1, maxNode + 1 + left_over_nodes) reelements[elem, 4:] = 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[4:, :] 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 idx_repoints = np.concatenate( (np.arange(nnode_linear), idx_repoints + nnode_linear)) repoints = repoints[idx_repoints, :] unique_reelements, inv_reelements = np.unique(reelements[:, 4:], return_inverse=True) unique_reelements = unique_reelements[inv_repoints] reelements = unique_reelements[inv_reelements] reelements = reelements.reshape(mesh.elements.shape[0], renodeperelem - 4) 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 #------------------------------------------------------------------------------------------ #------------------------------------------------------------------------------------------ if compute_boundary_info: # BUILD FACES NOW tfaces = time() # GET MESH EDGES AND FACES fsize = int((C + 2.) * (C + 3.) / 2.) refaces = np.zeros((mesh.faces.shape[0], fsize), dtype=mesh.faces.dtype) 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.GetElementsWithBoundaryFacesTet() node_arranger = NodeArrangementTet(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 = "tri" tmesh.elements = refaces tmesh.nelem = tmesh.elements.shape[0] # GET BOUNDARY EDGES reedges = tmesh.GetEdgesTri() 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 = 'tet' if compute_boundary_info: 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
def GetBases3D(C, Quadrature, info, bases_type="nodal", equally_spaced=False, is_flattened=True): from Florence.Tensor import makezero ndim = 3 w = Quadrature.weights z = Quadrature.points ns=[]; Basis=[]; gBasisx=[]; gBasisy=[]; gBasisz=[] if info=='hex': ns = int((C+2)**ndim) if is_flattened is False: Basis = np.zeros((ns,(z.shape[0])**ndim),dtype=np.float64) gBasisx = np.zeros((ns,(z.shape[0])**ndim),dtype=np.float64) gBasisy = np.zeros((ns,(z.shape[0])**ndim),dtype=np.float64) gBasisz = np.zeros((ns,(z.shape[0])**ndim),dtype=np.float64) else: Basis = np.zeros((ns,w.shape[0]),dtype=np.float64) gBasisx = np.zeros((ns,w.shape[0]),dtype=np.float64) gBasisy = np.zeros((ns,w.shape[0]),dtype=np.float64) gBasisz = np.zeros((ns,w.shape[0]),dtype=np.float64) elif info=='tet': p=C+1 ns = int((p+1)*(p+2)*(p+3)/6) Basis = np.zeros((ns,w.shape[0]),dtype=np.float64) gBasisx = np.zeros((ns,w.shape[0]),dtype=np.float64) gBasisy = np.zeros((ns,w.shape[0]),dtype=np.float64) gBasisz = np.zeros((ns,w.shape[0]),dtype=np.float64) if info=='hex': if not equally_spaced: hpBases = Hex.LagrangeGaussLobatto GradhpBases = Hex.GradLagrangeGaussLobatto else: hpBases = HexES.Lagrange GradhpBases = HexES.GradLagrange if is_flattened is False: counter = 0 for i in range(w.shape[0]): for j in range(w.shape[0]): for k in range(w.shape[0]): ndummy = hpBases(C,z[i],z[j],z[k]) dummy = GradhpBases(C,z[i],z[j],z[k]) Basis[:,counter] = ndummy[:,0] gBasisx[:,counter] = dummy[:,0] gBasisy[:,counter] = dummy[:,1] gBasisz[:,counter] = dummy[:,2] counter+=1 else: for i in range(0,w.shape[0]): ndummy = hpBases(C,z[i,0],z[i,1],z[i,2]) dummy = GradhpBases(C,z[i,0],z[i,1],z[i,2]) Basis[:,i] = ndummy[:,0] gBasisx[:,i] = dummy[:,0] gBasisy[:,i] = dummy[:,1] gBasisz[:,i] = dummy[:,2] elif info=='tet': hpBases = Tet.hpNodal.hpBases for i in range(0,w.shape[0]): # Better convergence for curved meshes when Quadrature.optimal!=0 ndummy, dummy = hpBases(C,z[i,0],z[i,1],z[i,2],Quadrature.optimal, equally_spaced=equally_spaced) # ndummy, dummy = Tet.hpBases(C,z[i,0],z[i,1],z[i,2]) # makezero(ndummy) makezero(dummy) Basis[:,i] = ndummy gBasisx[:,i] = dummy[:,0] gBasisy[:,i] = dummy[:,1] gBasisz[:,i] = dummy[:,2] class Domain(object): """docstring for Domain""" Bases = Basis gBasesx = gBasisx gBasesy = gBasisy gBasesz = gBasisz return Domain