def S_eDeriv_m(self, problem, v, adjoint=False): ''' Get the derivative of S_e wrt to sigma (m) ''' # Need to deal with if problem.mesh.dim == 1: # Need to use the faceInnerProduct MsigmaDeriv = problem.mesh.getFaceInnerProductDeriv( problem.curModel.sigma)( self.ePrimary(problem)[:, 1]) * problem.curModel.sigmaDeriv # MsigmaDeriv = ( MsigmaDeriv * MsigmaDeriv.T)**2 if problem.mesh.dim == 2: pass if problem.mesh.dim == 3: # Need to take the derivative of both u_px and u_py ePri = self.ePrimary(problem) # MsigmaDeriv = problem.MeSigmaDeriv(ePri[:,0]) + problem.MeSigmaDeriv(ePri[:,1]) # MsigmaDeriv = problem.MeSigmaDeriv(np.sum(ePri,axis=1)) if adjoint: return sp.hstack((problem.MeSigmaDeriv( ePri[:, 0]).T, problem.MeSigmaDeriv(ePri[:, 1]).T)) * v else: return np.hstack( (mkvc(problem.MeSigmaDeriv(ePri[:, 0]) * v, 2), mkvc(problem.MeSigmaDeriv(ePri[:, 1]) * v, 2))) if adjoint: # return MsigmaDeriv.T * v else: # v should be nC size return MsigmaDeriv * v
def S_eDeriv_m(self, problem, v, adjoint=False): """ Get the derivative of S_e wrt to sigma (m) """ # Need to deal with if problem.mesh.dim == 1: # Need to use the faceInnerProduct MsigmaDeriv = ( problem.mesh.getFaceInnerProductDeriv(problem.curModel.sigma)(self.ePrimary(problem)[:, 1]) * problem.curModel.sigmaDeriv ) # MsigmaDeriv = ( MsigmaDeriv * MsigmaDeriv.T)**2 if problem.mesh.dim == 2: pass if problem.mesh.dim == 3: # Need to take the derivative of both u_px and u_py ePri = self.ePrimary(problem) # MsigmaDeriv = problem.MeSigmaDeriv(ePri[:,0]) + problem.MeSigmaDeriv(ePri[:,1]) # MsigmaDeriv = problem.MeSigmaDeriv(np.sum(ePri,axis=1)) if adjoint: return sp.hstack((problem.MeSigmaDeriv(ePri[:, 0]).T, problem.MeSigmaDeriv(ePri[:, 1]).T)) * v else: return np.hstack( (mkvc(problem.MeSigmaDeriv(ePri[:, 0]) * v, 2), mkvc(problem.MeSigmaDeriv(ePri[:, 1]) * v, 2)) ) if adjoint: # return MsigmaDeriv.T * v else: # v should be nC size return MsigmaDeriv * v
def test_invXXXBlockDiagonal(self): a = [np.random.rand(5, 1) for i in range(4)] B = inv2X2BlockDiagonal(*a) A = sp.vstack((sp.hstack((sdiag(a[0]), sdiag(a[1]))), sp.hstack((sdiag(a[2]), sdiag(a[3]))))) Z2 = B*A - sp.identity(10) self.assertTrue(np.linalg.norm(Z2.todense().ravel(), 2) < TOL) a = [np.random.rand(5, 1) for i in range(9)] B = inv3X3BlockDiagonal(*a) A = sp.vstack((sp.hstack((sdiag(a[0]), sdiag(a[1]), sdiag(a[2]))), sp.hstack((sdiag(a[3]), sdiag(a[4]), sdiag(a[5]))), sp.hstack((sdiag(a[6]), sdiag(a[7]), sdiag(a[8]))))) Z3 = B*A - sp.identity(15) self.assertTrue(np.linalg.norm(Z3.todense().ravel(), 2) < TOL)
def getADeriv_m(self, freq, u, v, adjoint=False): """ Calculate the derivative of A wrt m. """ # This considers both polarizations and returns a nE,2 matrix for each polarization if adjoint: dMe_dsigV = sp.hstack(( self.MeSigmaDeriv( u['e_pxSolution'] ).T, self.MeSigmaDeriv(u['e_pySolution'] ).T ))*v else: # Need a nE,2 matrix to be returned dMe_dsigV = np.hstack(( mkvc(self.MeSigmaDeriv( u['e_pxSolution'] )*v,2), mkvc( self.MeSigmaDeriv(u['e_pySolution'] )*v,2) )) return 1j * omega(freq) * dMe_dsigV
def test_invXXXBlockDiagonal(self): a = [np.random.rand(5, 1) for i in range(4)] B = inv2X2BlockDiagonal(*a) A = sp.vstack((sp.hstack( (sdiag(a[0]), sdiag(a[1]))), sp.hstack( (sdiag(a[2]), sdiag(a[3]))))) Z2 = B * A - sp.identity(10) self.assertTrue(np.linalg.norm(Z2.todense().ravel(), 2) < TOL) a = [np.random.rand(5, 1) for i in range(9)] B = inv3X3BlockDiagonal(*a) A = sp.vstack((sp.hstack((sdiag(a[0]), sdiag(a[1]), sdiag(a[2]))), sp.hstack((sdiag(a[3]), sdiag(a[4]), sdiag(a[5]))), sp.hstack((sdiag(a[6]), sdiag(a[7]), sdiag(a[8]))))) Z3 = B * A - sp.identity(15) self.assertTrue(np.linalg.norm(Z3.todense().ravel(), 2) < TOL)
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 getADeriv_m(self, freq, u, v, adjoint=False): """ Calculate the derivative of A wrt m. """ # This considers both polarizations and returns a nE,2 matrix for each polarization if adjoint: dMe_dsigV = sp.hstack((self.MeSigmaDeriv(u['e_pxSolution']).T, self.MeSigmaDeriv(u['e_pySolution']).T)) * v else: # Need a nE,2 matrix to be returned dMe_dsigV = np.hstack( (mkvc(self.MeSigmaDeriv(u['e_pxSolution']) * v, 2), mkvc(self.MeSigmaDeriv(u['e_pySolution']) * v, 2))) return 1j * omega(freq) * dMe_dsigV
def getADeriv_m(self, freq, u, v, adjoint=False): # Nee to account for both the polarizations # dMe_dsig = (self.MeSigmaDeriv( u['e_pxSolution'] ) + self.MeSigmaDeriv( u['e_pySolution'] )) # dMe_dsig = (self.MeSigmaDeriv( u['e_pxSolution'] + u['e_pySolution'] )) # # dMe_dsig = self.MeSigmaDeriv( u ) # if adjoint: # return 1j * omega(freq) * ( dMe_dsig.T * v ) # As in simpegEM # return 1j * omega(freq) * ( dMe_dsig * v ) # As in simpegEM # This considers both polarizations and returns a nE,2 matrix for each polarization if adjoint: dMe_dsigV = sp.hstack((self.MeSigmaDeriv(u['e_pxSolution']).T, self.MeSigmaDeriv(u['e_pySolution']).T)) * v else: # Need a nE,2 matrix to be returned dMe_dsigV = np.hstack( (mkvc(self.MeSigmaDeriv(u['e_pxSolution']) * v, 2), mkvc(self.MeSigmaDeriv(u['e_pySolution']) * v, 2))) return 1j * omega(freq) * dMe_dsigV
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 _fastInnerProductDeriv(self, projType, prop, invProp=False, invMat=False): """ :param str projType: 'E' or 'F' :param TensorType tensorType: type of the tensor :param bool invProp: inverts the material property :param bool invMat: inverts the matrix :rtype: function :return: dMdmu, the derivative of the inner product matrix """ assert projType in ['F', 'E'], ("projType must be 'F' for faces or 'E'" " for edges") tensorType = Utils.TensorType(self, prop) dMdprop = None if invMat or invProp: MI = self._fastInnerProduct(projType, prop, invProp=invProp, invMat=invMat) # number of elements we are averaging (equals dim for regular # meshes, but for cyl, where we use symmetry, it is 1 for edge # variables and 2 for face variables) if self._meshType == 'CYL': n_elements = np.sum(getattr(self, 'vn'+projType).nonzero()) else: n_elements = self.dim if tensorType == 0: # isotropic, constant Av = getattr(self, 'ave'+projType+'2CC') V = Utils.sdiag(self.vol) ones = sp.csr_matrix((np.ones(self.nC), (range(self.nC), np.zeros(self.nC))), shape=(self.nC, 1)) if not invMat and not invProp: dMdprop = n_elements * Av.T * V * ones elif invMat and invProp: dMdprop = n_elements * (Utils.sdiag(MI.diagonal()**2) * Av.T * V * ones * Utils.sdiag(1./prop**2)) elif invProp: dMdprop = n_elements * Av.T * V * Utils.sdiag(- 1./prop**2) elif invMat: dMdprop = n_elements * (Utils.sdiag(- MI.diagonal()**2) * Av.T * V) elif tensorType == 1: # isotropic, variable in space Av = getattr(self, 'ave'+projType+'2CC') V = Utils.sdiag(self.vol) if not invMat and not invProp: dMdprop = n_elements * Av.T * V elif invMat and invProp: dMdprop = n_elements * (Utils.sdiag(MI.diagonal()**2) * Av.T * V * Utils.sdiag(1./prop**2)) elif invProp: dMdprop = n_elements * Av.T * V * Utils.sdiag(-1./prop**2) elif invMat: dMdprop = n_elements * (Utils.sdiag(- MI.diagonal()**2) * Av.T * V) elif tensorType == 2: # anisotropic Av = getattr(self, 'ave'+projType+'2CCV') V = sp.kron(sp.identity(self.dim), Utils.sdiag(self.vol)) if self._meshType == 'CYL': Zero = sp.csr_matrix((self.nC, self.nC)) Eye = sp.eye(self.nC) if projType == 'E': P = sp.hstack([Zero, Eye, Zero]) # print P.todense() elif projType == 'F': P = sp.vstack([sp.hstack([Eye, Zero, Zero]), sp.hstack([Zero, Zero, Eye])]) # print P.todense() else: P = sp.eye(self.nC*self.dim) if not invMat and not invProp: dMdprop = Av.T * P * V elif invMat and invProp: dMdprop = (Utils.sdiag(MI.diagonal()**2) * Av.T * P * V * Utils.sdiag(1./prop**2)) elif invProp: dMdprop = Av.T * P * V * Utils.sdiag(-1./prop**2) elif invMat: dMdprop = Utils.sdiag(- MI.diagonal()**2) * Av.T * P * V if dMdprop is not None: def innerProductDeriv(v=None): if v is None: warnings.warn("Depreciation Warning: " "TensorMesh.innerProductDeriv." " You should be supplying a vector. " "Use: sdiag(u)*dMdprop", FutureWarning) return dMdprop return Utils.sdiag(v) * dMdprop return innerProductDeriv else: return None
def _fastInnerProductDeriv(self, projType, prop, invProp=False, invMat=False): """ :param str projType: 'E' or 'F' :param TensorType tensorType: type of the tensor :param bool invProp: inverts the material property :param bool invMat: inverts the matrix :rtype: function :return: dMdmu, the derivative of the inner product matrix """ assert projType in ["F", "E"], "projType must be 'F' for faces or 'E'" " for edges" tensorType = Utils.TensorType(self, prop) dMdprop = None if invMat or invProp: MI = self._fastInnerProduct(projType, prop, invProp=invProp, invMat=invMat) # number of elements we are averaging (equals dim for regular # meshes, but for cyl, where we use symmetry, it is 1 for edge # variables and 2 for face variables) if self._meshType == "CYL": n_elements = np.sum(getattr(self, "vn" + projType).nonzero()) else: n_elements = self.dim if tensorType == 0: # isotropic, constant Av = getattr(self, "ave" + projType + "2CC") V = Utils.sdiag(self.vol) ones = sp.csr_matrix((np.ones(self.nC), (range(self.nC), np.zeros(self.nC))), shape=(self.nC, 1)) if not invMat and not invProp: dMdprop = n_elements * Av.T * V * ones elif invMat and invProp: dMdprop = n_elements * ( Utils.sdiag(MI.diagonal() ** 2) * Av.T * V * ones * Utils.sdiag(1.0 / prop ** 2) ) elif invProp: dMdprop = n_elements * Av.T * V * Utils.sdiag(-1.0 / prop ** 2) elif invMat: dMdprop = n_elements * (Utils.sdiag(-MI.diagonal() ** 2) * Av.T * V) elif tensorType == 1: # isotropic, variable in space Av = getattr(self, "ave" + projType + "2CC") V = Utils.sdiag(self.vol) if not invMat and not invProp: dMdprop = n_elements * Av.T * V elif invMat and invProp: dMdprop = n_elements * (Utils.sdiag(MI.diagonal() ** 2) * Av.T * V * Utils.sdiag(1.0 / prop ** 2)) elif invProp: dMdprop = n_elements * Av.T * V * Utils.sdiag(-1.0 / prop ** 2) elif invMat: dMdprop = n_elements * (Utils.sdiag(-MI.diagonal() ** 2) * Av.T * V) elif tensorType == 2: # anisotropic Av = getattr(self, "ave" + projType + "2CCV") V = sp.kron(sp.identity(self.dim), Utils.sdiag(self.vol)) if self._meshType == "CYL": Zero = sp.csr_matrix((self.nC, self.nC)) Eye = sp.eye(self.nC) if projType == "E": P = sp.hstack([Zero, Eye, Zero]) # print(P.todense()) elif projType == "F": P = sp.vstack([sp.hstack([Eye, Zero, Zero]), sp.hstack([Zero, Zero, Eye])]) # print(P.todense()) else: P = sp.eye(self.nC * self.dim) if not invMat and not invProp: dMdprop = Av.T * P * V elif invMat and invProp: dMdprop = Utils.sdiag(MI.diagonal() ** 2) * Av.T * P * V * Utils.sdiag(1.0 / prop ** 2) elif invProp: dMdprop = Av.T * P * V * Utils.sdiag(-1.0 / prop ** 2) elif invMat: dMdprop = Utils.sdiag(-MI.diagonal() ** 2) * Av.T * P * V if dMdprop is not None: def innerProductDeriv(v=None): if v is None: warnings.warn( "Depreciation Warning: " "TensorMesh.innerProductDeriv." " You should be supplying a vector. " "Use: sdiag(u)*dMdprop", FutureWarning, ) return dMdprop return Utils.sdiag(v) * dMdprop return innerProductDeriv else: return None
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)