def getInterpolationMatCartMesh(self, Mrect, locType='CC'): """ Takes a cartesian mesh and returns a projection to translate onto the cartesian grid. """ assert self.isSymmetric, "Currently we have not taken into account other projections for more complicated CylMeshes" if locType == 'F': # do this three times for each component X = self.getInterpolationMatCartMesh(Mrect, locType='Fx') Y = self.getInterpolationMatCartMesh(Mrect, locType='Fy') Z = self.getInterpolationMatCartMesh(Mrect, locType='Fz') return sp.vstack((X, Y, Z)) if locType == 'E': X = self.getInterpolationMatCartMesh(Mrect, locType='Ex') Y = self.getInterpolationMatCartMesh(Mrect, locType='Ey') Z = spzeros(Mrect.nEz, self.nE) return sp.vstack((X, Y, Z)) grid = getattr(Mrect, 'grid' + locType) # This is unit circle stuff, 0 to 2*pi, starting at x-axis, rotating counter clockwise in an x-y slice theta = -np.arctan2(grid[:, 0] - self.cartesianOrigin[0], grid[:, 1] - self.cartesianOrigin[1]) + np.pi / 2 theta[theta < 0] += np.pi * 2.0 r = ((grid[:, 0] - self.cartesianOrigin[0])**2 + (grid[:, 1] - self.cartesianOrigin[1])**2)**0.5 if locType in ['CC', 'N', 'Fz', 'Ez']: G, proj = np.c_[r, theta, grid[:, 2]], np.ones(r.size) else: dotMe = { 'Fx': Mrect.normals[:Mrect.nFx, :], 'Fy': Mrect.normals[Mrect.nFx:(Mrect.nFx + Mrect.nFy), :], 'Fz': Mrect.normals[-Mrect.nFz:, :], 'Ex': Mrect.tangents[:Mrect.nEx, :], 'Ey': Mrect.tangents[Mrect.nEx:(Mrect.nEx + Mrect.nEy), :], 'Ez': Mrect.tangents[-Mrect.nEz:, :], }[locType] if 'F' in locType: normals = np.c_[np.cos(theta), np.sin(theta), np.zeros(theta.size)] proj = (normals * dotMe).sum(axis=1) if 'E' in locType: tangents = np.c_[-np.sin(theta), np.cos(theta), np.zeros(theta.size)] proj = (tangents * dotMe).sum(axis=1) G = np.c_[r, theta, grid[:, 2]] interpType = locType if interpType == 'Fy': interpType = 'Fx' elif interpType == 'Ex': interpType = 'Ey' Pc2r = self.getInterpolationMat(G, interpType) Proj = sdiag(proj) return Proj * Pc2r
def getInterpolationMatCartMesh(self, Mrect, locType='CC', locTypeTo=None): """ Takes a cartesian mesh and returns a projection to translate onto the cartesian grid. """ assert self.isSymmetric, "Currently we have not taken into account other projections for more complicated CylMeshes" if locTypeTo is None: locTypeTo = locType if locType == 'F': # do this three times for each component X = self.getInterpolationMatCartMesh(Mrect, locType='Fx', locTypeTo=locTypeTo+'x') Y = self.getInterpolationMatCartMesh(Mrect, locType='Fy', locTypeTo=locTypeTo+'y') Z = self.getInterpolationMatCartMesh(Mrect, locType='Fz', locTypeTo=locTypeTo+'z') return sp.vstack((X,Y,Z)) if locType == 'E': X = self.getInterpolationMatCartMesh(Mrect, locType='Ex', locTypeTo=locTypeTo+'x') Y = self.getInterpolationMatCartMesh(Mrect, locType='Ey', locTypeTo=locTypeTo+'y') Z = spzeros(getattr(Mrect, 'n' + locTypeTo + 'z'), self.nE) return sp.vstack((X,Y,Z)) grid = getattr(Mrect, 'grid' + locTypeTo) # This is unit circle stuff, 0 to 2*pi, starting at x-axis, rotating counter clockwise in an x-y slice theta = - np.arctan2(grid[:,0] - self.cartesianOrigin[0], grid[:,1] - self.cartesianOrigin[1]) + np.pi/2 theta[theta < 0] += np.pi*2.0 r = ((grid[:,0] - self.cartesianOrigin[0])**2 + (grid[:,1] - self.cartesianOrigin[1])**2)**0.5 if locType in ['CC', 'N', 'Fz', 'Ez']: G, proj = np.c_[r, theta, grid[:,2]], np.ones(r.size) else: dotMe = { 'Fx': Mrect.normals[:Mrect.nFx,:], 'Fy': Mrect.normals[Mrect.nFx:(Mrect.nFx+Mrect.nFy),:], 'Fz': Mrect.normals[-Mrect.nFz:,:], 'Ex': Mrect.tangents[:Mrect.nEx,:], 'Ey': Mrect.tangents[Mrect.nEx:(Mrect.nEx+Mrect.nEy),:], 'Ez': Mrect.tangents[-Mrect.nEz:,:], }[locTypeTo] if 'F' in locType: normals = np.c_[np.cos(theta), np.sin(theta), np.zeros(theta.size)] proj = ( normals * dotMe ).sum(axis=1) if 'E' in locType: tangents = np.c_[-np.sin(theta), np.cos(theta), np.zeros(theta.size)] proj = ( tangents * dotMe ).sum(axis=1) G = np.c_[r, theta, grid[:,2]] interpType = locType if interpType == 'Fy': interpType = 'Fx' elif interpType == 'Ex': interpType = 'Ey' Pc2r = self.getInterpolationMat(G, interpType) Proj = sdiag(proj) return Proj * Pc2r
def fget(self): if(self._edgeCurl is None): assert self.dim > 1, "Edge Curl only programed for 2 or 3D." # The number of cell centers in each direction n = self.vnC # Compute lengths of cell edges L = self.edge # Compute areas of cell faces S = self.area # Compute divergence operator on faces if self.dim == 2: D21 = sp.kron(ddx(n[1]), speye(n[0])) D12 = sp.kron(speye(n[1]), ddx(n[0])) C = sp.hstack((-D21, D12), format="csr") self._edgeCurl = C*sdiag(1/S) elif self.dim == 3: D32 = kron3(ddx(n[2]), speye(n[1]), speye(n[0]+1)) D23 = kron3(speye(n[2]), ddx(n[1]), speye(n[0]+1)) D31 = kron3(ddx(n[2]), speye(n[1]+1), speye(n[0])) D13 = kron3(speye(n[2]), speye(n[1]+1), ddx(n[0])) D21 = kron3(speye(n[2]+1), ddx(n[1]), speye(n[0])) D12 = kron3(speye(n[2]+1), speye(n[1]), ddx(n[0])) O1 = spzeros(np.shape(D32)[0], np.shape(D31)[1]) O2 = spzeros(np.shape(D31)[0], np.shape(D32)[1]) O3 = spzeros(np.shape(D21)[0], np.shape(D13)[1]) C = sp.vstack((sp.hstack((O1, -D32, D23)), sp.hstack((D31, O2, -D13)), sp.hstack((-D21, D12, O3))), format="csr") self._edgeCurl = sdiag(1/S)*(C*sdiag(L)) return self._edgeCurl
def _getInnerProductDerivFunction(self, tensorType, P, projType, v): """ :param numpy.array prop: material property (tensor properties are possible) at each cell center (nC, (1, 3, or 6)) :param numpy.array v: vector to multiply (required in the general implementation) :param list P: list of projection matrices :param str projType: 'F' for faces 'E' for edges :rtype: scipy.sparse.csr_matrix :return: dMdm, the derivative of the inner product matrix (n, nC*nA) """ assert projType in [ 'F', 'E' ], "projType must be 'F' for faces or 'E' for edges" n = getattr(self, 'n' + projType) if tensorType == -1: return None if v is None: raise Exception('v must be supplied for this implementation.') d = self.dim Z = spzeros(self.nC, self.nC) if tensorType == 0: dMdm = spzeros(n, 1) for i, p in enumerate(P): dMdm = dMdm + sp.csr_matrix( (p.T * (p * v), (range(n), np.zeros(n))), shape=(n, 1)) if d == 1: if tensorType == 1: dMdm = spzeros(n, self.nC) for i, p in enumerate(P): dMdm = dMdm + p.T * sdiag(p * v) elif d == 2: if tensorType == 1: dMdm = spzeros(n, self.nC) for i, p in enumerate(P): Y = p * v y1 = Y[:self.nC] y2 = Y[self.nC:] dMdm = dMdm + p.T * sp.vstack((sdiag(y1), sdiag(y2))) elif tensorType == 2: dMdms = [spzeros(n, self.nC) for _ in range(2)] for i, p in enumerate(P): Y = p * v y1 = Y[:self.nC] y2 = Y[self.nC:] dMdms[0] = dMdms[0] + p.T * sp.vstack((sdiag(y1), Z)) dMdms[1] = dMdms[1] + p.T * sp.vstack((Z, sdiag(y2))) dMdm = sp.hstack(dMdms) elif tensorType == 3: dMdms = [spzeros(n, self.nC) for _ in range(3)] for i, p in enumerate(P): Y = p * v y1 = Y[:self.nC] y2 = Y[self.nC:] dMdms[0] = dMdms[0] + p.T * sp.vstack((sdiag(y1), Z)) dMdms[1] = dMdms[1] + p.T * sp.vstack((Z, sdiag(y2))) dMdms[2] = dMdms[2] + p.T * sp.vstack( (sdiag(y2), sdiag(y1))) dMdm = sp.hstack(dMdms) elif d == 3: if tensorType == 1: dMdm = spzeros(n, self.nC) for i, p in enumerate(P): Y = p * v y1 = Y[:self.nC] y2 = Y[self.nC:self.nC * 2] y3 = Y[self.nC * 2:] dMdm = dMdm + p.T * sp.vstack( (sdiag(y1), sdiag(y2), sdiag(y3))) elif tensorType == 2: dMdms = [spzeros(n, self.nC) for _ in range(3)] for i, p in enumerate(P): Y = p * v y1 = Y[:self.nC] y2 = Y[self.nC:self.nC * 2] y3 = Y[self.nC * 2:] dMdms[0] = dMdms[0] + p.T * sp.vstack((sdiag(y1), Z, Z)) dMdms[1] = dMdms[1] + p.T * sp.vstack((Z, sdiag(y2), Z)) dMdms[2] = dMdms[2] + p.T * sp.vstack((Z, Z, sdiag(y3))) dMdm = sp.hstack(dMdms) elif tensorType == 3: dMdms = [spzeros(n, self.nC) for _ in range(6)] for i, p in enumerate(P): Y = p * v y1 = Y[:self.nC] y2 = Y[self.nC:self.nC * 2] y3 = Y[self.nC * 2:] dMdms[0] = dMdms[0] + p.T * sp.vstack((sdiag(y1), Z, Z)) dMdms[1] = dMdms[1] + p.T * sp.vstack((Z, sdiag(y2), Z)) dMdms[2] = dMdms[2] + p.T * sp.vstack((Z, Z, sdiag(y3))) dMdms[3] = dMdms[3] + p.T * sp.vstack( (sdiag(y2), sdiag(y1), Z)) dMdms[4] = dMdms[4] + p.T * sp.vstack( (sdiag(y3), Z, sdiag(y1))) dMdms[5] = dMdms[5] + p.T * sp.vstack( (Z, sdiag(y3), sdiag(y2))) dMdm = sp.hstack(dMdms) return dMdm