def Jfull(self, m, f=None): if f is None: f = self.fields(m) nn = len(f) - 1 Asubs, Adiags, Bs = list(range(nn)), list(range(nn)), list(range(nn)) for ii in range(nn): dt = self.timeSteps[ii] bc = self.getBoundaryConditions(ii, f[ii]) Asubs[ii], Adiags[ii], Bs[ii] = self.diagsJacobian( m, f[ii], f[ii + 1], dt, bc) Ad = sp.block_diag(Adiags) zRight = Utils.spzeros((len(Asubs) - 1) * Asubs[0].shape[0], Adiags[0].shape[1]) zTop = Utils.spzeros(Adiags[0].shape[0], len(Adiags) * Adiags[0].shape[1]) As = sp.vstack((zTop, sp.hstack((sp.block_diag(Asubs[1:]), zRight)))) A = As + Ad B = np.array(sp.vstack(Bs).todense()) Ainv = self.Solver(A, **self.solverOpts) P = self.survey.evalDeriv(f, m) AinvB = Ainv * B z = np.zeros((self.mesh.nC, B.shape[1])) zAinvB = np.vstack((z, AinvB)) J = P * zAinvB return J
def Jfull(self, m=None, f=None): if f is None: f = self.fields(m) nn = len(f)-1 Asubs, Adiags, Bs = list(range(nn)), list(range(nn)), list(range(nn)) for ii in range(nn): dt = self.timeSteps[ii] bc = self.getBoundaryConditions(ii, f[ii]) Asubs[ii], Adiags[ii], Bs[ii] = self.diagsJacobian( m, f[ii], f[ii+1], dt, bc ) Ad = sp.block_diag(Adiags) zRight = Utils.spzeros( (len(Asubs)-1)*Asubs[0].shape[0], Adiags[0].shape[1] ) zTop = Utils.spzeros( Adiags[0].shape[0], len(Adiags)*Adiags[0].shape[1] ) As = sp.vstack((zTop, sp.hstack((sp.block_diag(Asubs[1:]), zRight)))) A = As + Ad B = np.array(sp.vstack(Bs).todense()) Ainv = self.Solver(A, **self.solverOpts) AinvB = Ainv * B z = np.zeros((self.mesh.nC, B.shape[1])) du_dm = np.vstack((z, AinvB)) J = self.survey.deriv(f, du_dm_v=du_dm) # not multiplied by v return J
def Dz(self): if self.mesh.dim == 1: Dz = self.mesh.faceDivx elif self.mesh.dim == 2: Dz = sp.hstack((Utils.spzeros( self.mesh.nC, self.mesh.vnF[0]), self.mesh.faceDivy), format='csr') elif self.mesh.dim == 3: Dz = sp.hstack( (Utils.spzeros(self.mesh.nC, self.mesh.vnF[0] + self.mesh.vnF[1]), self.mesh.faceDivz), format='csr') return Dz
def Dz(self): if self.mesh.dim == 1: return self.mesh.faceDivx if self.mesh.dim == 2: mats = ( Utils.spzeros(self.mesh.nC, self.mesh.vnF[0]), self.mesh.faceDivy ) elif self.mesh.dim == 3: mats = ( Utils.spzeros(self.mesh.nC, self.mesh.vnF[0]+self.mesh.vnF[1]), self.mesh.faceDivz ) return sp.hstack(mats, format='csr')
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 = Utils.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 = Utils.sdiag(proj) return Proj * Pc2r
def getADeriv_sigma(self, freq, f, v, adjoint=False): Ex = f[:self.mesh.nC] dMcc_dsig = self.MccSigmaDeriv(Ex) if adjoint: return sp.hstack( (Utils.spzeros(self.mesh.nC, self.mesh.nN), dMcc_dsig.T)) * v else: return np.r_[np.zeros(self.mesh.nC + 1), dMcc_dsig * v]
def getADeriv_sigma(self, freq, f, v, adjoint=False): Ex = f[:self.mesh.nC] dMcc_dsig = self.MccSigmaDeriv(Ex) if adjoint: return sp.hstack( (Utils.spzeros(self.mesh.nC, self.mesh.nN), dMcc_dsig.T) ) * v else: return np.r_[np.zeros(self.mesh.nC+1), dMcc_dsig*v]
def _b_pyDeriv_u(self, src, du_dm_v, adjoint=False): """ Derivative of b_py with wrt u :param SimPEG.NSEM.src src: The source of the problem :param numpy.ndarray du_dm_v: vector to take product with. Size (nF,) when adjoint=True, (nU,) when adjoint=False :param bool adjoint: adjoint? :rtype: numpy.ndarray :return: The calculated derivative, size (nU,) when adjoint=True. (nF,) when adjoint=False """ # Primary does not depend on u C = sp.hstack((Utils.spzeros(self.mesh.nF, self.mesh.nE), self.mesh.edgeCurl)) # This works for adjoint = None if adjoint: return - 1./(1j*omega(src.freq)) * (C.T * du_dm_v) return - 1./(1j*omega(src.freq)) * (C * du_dm_v)
def _b_pyDeriv_u(self, src, du_dm_v, adjoint=False): """ Derivative of b_py with wrt u :param SimPEG.NSEM.src src: The source of the problem :param numpy.ndarray du_dm_v: vector to take product with. Size (nF,) when adjoint=True, (nU,) when adjoint=False :param bool adjoint: adjoint? :rtype: numpy.ndarray :return: The calculated derivative, size (nU,) when adjoint=True. (nF,) when adjoint=False """ # Primary does not depend on u C = sp.hstack((Utils.spzeros(self.mesh.nF, self.mesh.nE), self.mesh.edgeCurl)) # This works for adjoint = None if adjoint: return -1. / (1j * omega(src.freq)) * (C.T * du_dm_v) return -1. / (1j * omega(src.freq)) * (C * du_dm_v)
def getInterpolationMat(self, loc, locType, zerosOutside=False): """ Produces interpolation matrix :param numpy.ndarray loc: Location of points to interpolate to :param str locType: What to interpolate (see below) :rtype: scipy.sparse.csr.csr_matrix :return: M, the interpolation matrix locType can be:: 'Ex' -> x-component of field defined on edges 'Ey' -> y-component of field defined on edges 'Ez' -> z-component of field defined on edges 'Fx' -> x-component of field defined on faces 'Fy' -> y-component of field defined on faces 'Fz' -> z-component of field defined on faces 'N' -> scalar field defined on nodes 'CC' -> scalar field defined on cell centers """ if self._meshType == 'CYL' and self.isSymmetric and locType in ['Ex','Ez','Fy']: raise Exception('Symmetric CylMesh does not support %s interpolation, as this variable does not exist.' % locType) loc = Utils.asArray_N_x_Dim(loc, self.dim) if zerosOutside is False: assert np.all(self.isInside(loc)), "Points outside of mesh" else: indZeros = np.logical_not(self.isInside(loc)) loc[indZeros, :] = np.array([v.mean() for v in self.getTensor('CC')]) if locType in ['Fx','Fy','Fz','Ex','Ey','Ez']: ind = {'x':0, 'y':1, 'z':2}[locType[1]] assert self.dim >= ind, 'mesh is not high enough dimension.' nF_nE = self.vnF if 'F' in locType else self.vnE components = [Utils.spzeros(loc.shape[0], n) for n in nF_nE] components[ind] = Utils.interpmat(loc, *self.getTensor(locType)) # remove any zero blocks (hstack complains) components = [comp for comp in components if comp.shape[1] > 0] Q = sp.hstack(components) elif locType in ['CC', 'N']: Q = Utils.interpmat(loc, *self.getTensor(locType)) else: raise NotImplementedError('getInterpolationMat: locType=='+locType+' and mesh.dim=='+str(self.dim)) if zerosOutside: Q[indZeros, :] = 0 return Q.tocsr()
def getInterpolationMat(self, loc, locType='CC', zerosOutside=False): """ Produces interpolation matrix :param numpy.ndarray loc: Location of points to interpolate to :param str locType: What to interpolate (see below) :rtype: scipy.sparse.csr_matrix :return: M, the interpolation matrix locType can be:: 'Ex' -> x-component of field defined on edges 'Ey' -> y-component of field defined on edges 'Ez' -> z-component of field defined on edges 'Fx' -> x-component of field defined on faces 'Fy' -> y-component of field defined on faces 'Fz' -> z-component of field defined on faces 'N' -> scalar field defined on nodes 'CC' -> scalar field defined on cell centers 'CCVx' -> x-component of vector field defined on cell centers 'CCVy' -> y-component of vector field defined on cell centers 'CCVz' -> z-component of vector field defined on cell centers """ if self.isSymmetric and locType in ['Ex', 'Ez', 'Fy']: raise Exception( "Symmetric CylMesh does not support {0!s} interpolation, " "as this variable does not exist.".format(locType) ) if locType in ['CCVx', 'CCVy', 'CCVz']: Q = Utils.interpmat(loc, *self.getTensor('CC')) Z = Utils.spzeros(loc.shape[0], self.nC) if locType == 'CCVx': Q = sp.hstack([Q, Z]) elif locType == 'CCVy': Q = sp.hstack([Q]) elif locType == 'CCVz': Q = sp.hstack([Z, Q]) if zerosOutside: Q[indZeros, :] = 0 return Q.tocsr() return self._getInterpolationMat(loc, locType, zerosOutside)
def getInterpolationMat(self, loc, locType='CC', zerosOutside=False): """ Produces interpolation matrix :param numpy.ndarray loc: Location of points to interpolate to :param str locType: What to interpolate (see below) :rtype: scipy.sparse.csr.csr_matrix :return: M, the interpolation matrix locType can be:: 'Ex' -> x-component of field defined on edges 'Ey' -> y-component of field defined on edges 'Ez' -> z-component of field defined on edges 'Fx' -> x-component of field defined on faces 'Fy' -> y-component of field defined on faces 'Fz' -> z-component of field defined on faces 'N' -> scalar field defined on nodes 'CC' -> scalar field defined on cell centers 'CCVx' -> x-component of vector field defined on cell centers 'CCVy' -> y-component of vector field defined on cell centers 'CCVz' -> z-component of vector field defined on cell centers """ if self._meshType == 'CYL' and self.isSymmetric and locType in [ 'Ex', 'Ez', 'Fy' ]: raise Exception( 'Symmetric CylMesh does not support %s interpolation, as this variable does not exist.' % locType) loc = Utils.asArray_N_x_Dim(loc, self.dim) if zerosOutside is False: assert np.all(self.isInside(loc)), "Points outside of mesh" else: indZeros = np.logical_not(self.isInside(loc)) loc[indZeros, :] = np.array( [v.mean() for v in self.getTensor('CC')]) if locType in ['Fx', 'Fy', 'Fz', 'Ex', 'Ey', 'Ez']: ind = {'x': 0, 'y': 1, 'z': 2}[locType[1]] assert self.dim >= ind, 'mesh is not high enough dimension.' nF_nE = self.vnF if 'F' in locType else self.vnE components = [Utils.spzeros(loc.shape[0], n) for n in nF_nE] components[ind] = Utils.interpmat(loc, *self.getTensor(locType)) # remove any zero blocks (hstack complains) components = [comp for comp in components if comp.shape[1] > 0] Q = sp.hstack(components) elif locType in ['CC', 'N']: Q = Utils.interpmat(loc, *self.getTensor(locType)) elif locType in ['CCVx', 'CCVy', 'CCVz']: Q = Utils.interpmat(loc, *self.getTensor('CC')) Z = Utils.spzeros(loc.shape[0], self.nC) if locType == 'CCVx': Q = sp.hstack([Q, Z, Z]) elif locType == 'CCVy': Q = sp.hstack([Z, Q, Z]) elif locType == 'CCVz': Q = sp.hstack([Z, Z, Q]) else: raise NotImplementedError('getInterpolationMat: locType==' + locType + ' and mesh.dim==' + str(self.dim)) if zerosOutside: Q[indZeros, :] = 0 return Q.tocsr()
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 = Utils.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 = Utils.sdiag(proj) return Proj * Pc2r
def getInterpolationMat(self, loc, locType="CC", zerosOutside=False): """ Produces interpolation matrix :param numpy.ndarray loc: Location of points to interpolate to :param str locType: What to interpolate (see below) :rtype: scipy.sparse.csr_matrix :return: M, the interpolation matrix locType can be:: 'Ex' -> x-component of field defined on edges 'Ey' -> y-component of field defined on edges 'Ez' -> z-component of field defined on edges 'Fx' -> x-component of field defined on faces 'Fy' -> y-component of field defined on faces 'Fz' -> z-component of field defined on faces 'N' -> scalar field defined on nodes 'CC' -> scalar field defined on cell centers 'CCVx' -> x-component of vector field defined on cell centers 'CCVy' -> y-component of vector field defined on cell centers 'CCVz' -> z-component of vector field defined on cell centers """ if self._meshType == "CYL" and self.isSymmetric and locType in ["Ex", "Ez", "Fy"]: raise Exception( "Symmetric CylMesh does not support {0!s} interpolation, as this variable does not exist.".format( locType ) ) loc = Utils.asArray_N_x_Dim(loc, self.dim) if zerosOutside is False: assert np.all(self.isInside(loc)), "Points outside of mesh" else: indZeros = np.logical_not(self.isInside(loc)) loc[indZeros, :] = np.array([v.mean() for v in self.getTensor("CC")]) if locType in ["Fx", "Fy", "Fz", "Ex", "Ey", "Ez"]: ind = {"x": 0, "y": 1, "z": 2}[locType[1]] assert self.dim >= ind, "mesh is not high enough dimension." nF_nE = self.vnF if "F" in locType else self.vnE components = [Utils.spzeros(loc.shape[0], n) for n in nF_nE] components[ind] = Utils.interpmat(loc, *self.getTensor(locType)) # remove any zero blocks (hstack complains) components = [comp for comp in components if comp.shape[1] > 0] Q = sp.hstack(components) elif locType in ["CC", "N"]: Q = Utils.interpmat(loc, *self.getTensor(locType)) elif locType in ["CCVx", "CCVy", "CCVz"]: Q = Utils.interpmat(loc, *self.getTensor("CC")) Z = Utils.spzeros(loc.shape[0], self.nC) if locType == "CCVx": Q = sp.hstack([Q, Z, Z]) elif locType == "CCVy": Q = sp.hstack([Z, Q, Z]) elif locType == "CCVz": Q = sp.hstack([Z, Z, Q]) else: raise NotImplementedError("getInterpolationMat: locType==" + locType + " and mesh.dim==" + str(self.dim)) if zerosOutside: Q[indZeros, :] = 0 return Q.tocsr()
def _b_pySecondaryDeriv_u(self, src, v, adjoint=False): # C = sp.kron(self.mesh.edgeCurl,[[0,0],[0,1]]) C = sp.hstack((Utils.spzeros(self.mesh.nF, self.mesh.nE), self.mesh.edgeCurl)) # This works for adjoint = None if adjoint: return -1.0 / (1j * omega(src.freq)) * (C.T * v) return -1.0 / (1j * omega(src.freq)) * (C * v)
def _b_pySecondaryDeriv_u(self, src, v, adjoint = False): # C = sp.kron(self.mesh.edgeCurl,[[0,0],[0,1]]) C = sp.hstack((Utils.spzeros(self.mesh.nF,self.mesh.nE),self.mesh.edgeCurl)) # This works for adjoint = None if adjoint: return - 1./(1j*omega(src.freq)) * (C.T * v) return - 1./(1j*omega(src.freq)) * (C * v)