def test_updateMultipliers(self): nP = 10 m = np.random.rand(nP) W1 = Utils.sdiag(np.random.rand(nP)) W2 = Utils.sdiag(np.random.rand(nP)) phi1 = ObjectiveFunction.L2ObjectiveFunction(W=W1) phi2 = ObjectiveFunction.L2ObjectiveFunction(W=W2) phi = phi1 + phi2 self.assertTrue(phi(m) == phi1(m) + phi2(m)) phi.multipliers[0] = Utils.Zero() self.assertTrue(phi(m) == phi2(m)) phi.multipliers[0] = 1. phi.multipliers[1] = Utils.Zero() self.assertTrue(len(phi.objfcts) == 2) self.assertTrue(len(phi.multipliers) == 2) self.assertTrue(len(phi) == 2) self.assertTrue(phi(m) == phi1(m))
def MccRhoiDeriv(self, u, v, adjoint=False): """ Derivative of :code:`MccRhoi` with respect to the model. """ if self.rhoMap is None: return Utils.Zero() if len(self.rho.shape) > 1: if self.rho.shape[1] > self.mesh.dim: raise NotImplementedError( "Full anisotropy is not implemented for MccRhoiDeriv.") if self.storeInnerProduct: if adjoint: return self.MccRhoiDerivMat.T * (Utils.sdiag(u) * v) else: return Utils.sdiag(u) * (self.MccRhoiDerivMat * v) else: vol = self.mesh.vol rho = self.rho if adjoint: return self.rhoDeriv.T * (Utils.sdiag(u * vol * (-1. / rho**2)) * v) else: return (Utils.sdiag(u * vol * (-1. / rho**2))) * (self.rhoDeriv * v)
def getAsubdiag(self, tInd): """ Matrix below the diagonal """ assert tInd >= 0 and tInd < self.nT return Utils.Zero()
def MeSigmaIDeriv(self, u, v, adjoint=False): """ Derivative of :code:`MeSigmaI` with respect to the model """ if self.sigmaMap is None: return Utils.Zero() if len(self.sigma.shape) > 1: if self.sigma.shape[1] > self.mesh.dim: raise NotImplementedError( "Full anisotropy is not implemented for MeSigmaIDeriv.") dMeSigmaI_dI = -self.MeSigmaI**2 if self.storeInnerProduct: if adjoint: return self.MeSigmaDerivMat.T * (Utils.sdiag(u) * (dMeSigmaI_dI.T * v)) else: return dMeSigmaI_dI * Utils.sdiag(u) * (self.MeSigmaDerivMat * v) else: dMe_dsig = self.mesh.getEdgeInnerProductDeriv(self.sigma)(u) if adjoint: return self.sigmaDeriv.T * (dMe_dsig.T * (dMeSigmaI_dI.T * v)) else: return dMeSigmaI_dI * (dMe_dsig * (self.sigmaDeriv * v))
def getJ_height(self, m): """ Compute d F / d height """ if self.hMap is None: return Utils.Zero() if self._Jmatrix_height is not None: return self._Jmatrix_height if self.verbose: print(">> Compute J height") self.model = m if self.parallel: pool = Pool(self.n_cpu) self._Jmatrix_height = pool.map(self.run_simulation, [ self.input_args(i, jac_switch="sensitivity_height") for i in range(self.n_sounding) ]) pool.close() pool.join() if self.parallel_jvec_jtvec is False: self._Jmatrix_height = sp.block_diag( self._Jmatrix_height).tocsr() else: self._Jmatrix_height = sp.block_diag([ self.run_simulation( self.input_args(i, jac_switch='sensitivity_height')) for i in range(self.n_sounding) ]).tocsr() return self._Jmatrix_height
def test_early_exits(self): nP = 10 m = np.random.rand(nP) v = np.random.rand(nP) W1 = Utils.sdiag(np.random.rand(nP)) phi1 = ObjectiveFunction.L2ObjectiveFunction(W=W1) phi2 = Error_if_Hit_ObjFct() objfct = phi1 + 0 * phi2 self.assertTrue(len(objfct) == 2) self.assertTrue(np.all(objfct.multipliers == np.r_[1, 0])) self.assertTrue(objfct(m) == phi1(m)) self.assertTrue(np.all(objfct.deriv(m) == phi1.deriv(m))) self.assertTrue(np.all(objfct.deriv2(m, v) == phi1.deriv2(m, v))) objfct.multipliers[1] = Utils.Zero() self.assertTrue(len(objfct) == 2) self.assertTrue(np.all(objfct.multipliers == np.r_[1, 0])) self.assertTrue(objfct(m) == phi1(m)) self.assertTrue(np.all(objfct.deriv(m) == phi1.deriv(m))) self.assertTrue(np.all(objfct.deriv2(m, v) == phi1.deriv2(m, v)))
def MeMuDeriv(self, u): """ Derivative of :code:`MeMu` with respect to the model. """ if self.muMap is None: return Utils.Zero() return (self.mesh.getEdgeInnerProductDeriv(self.mu)(u) * self.muDeriv)
def getRHSDeriv(self, src, v, adjoint=False): """ Derivative of the right hand side with respect to the model """ # TODO: add qDeriv for RHS depending on m # qDeriv = src.evalDeriv(self, adjoint=adjoint) # return qDeriv return Utils.Zero()
def _derivTheta_r(self, u): if self.theta_rMap is None: return Utils.Zero() theta_r, theta_s, alpha, beta = self._get_params() ddm = -alpha / (alpha + abs(u)**beta) + 1 ddm[u >= 0] = 0 dT = Utils.sdiag(ddm) * self.theta_rDeriv return dT
def _derivA(self, u): if self.AMap is None: return Utils.Zero() Ks, A, gamma = self._get_params() ddm = Ks / (A + abs(u)**gamma) - Ks * A / (A + abs(u)**gamma)**2 ddm[u >= 0] = 0 dA_dm = Utils.sdiag(ddm) * self.ADeriv return dA_dm
def _derivTheta_r(self, u): if self.theta_rMap is None: return Utils.Zero() theta_r, theta_s, alpha, n = self._get_params() ddm = -(abs(alpha * u)**n + 1.0)**(-1.0 + 1.0 / n) + 1 ddm[u >= 0] = 0 dT = Utils.sdiag(ddm) * self.theta_rDeriv return dT
def MccSigmaDeriv(self, u): """ Derivative of MccSigma with respect to the model """ if self.sigmaMap is None: return Utils.Zero() return (Utils.sdiag(u) * self.sigmaDeriv)
def getRHSDeriv(self, tInd, src, v, adjoint=False): """ Derivative of the RHS """ C = self.mesh.edgeCurl MeSigmaI = self.MeSigmaI def MeSigmaIDeriv(u): return self.MeSigmaIDeriv(u) MfMui = self.MfMui _, s_e = src.eval(self, self.times[tInd]) s_mDeriv, s_eDeriv = src.evalDeriv( self, self.times[tInd], adjoint=adjoint ) if adjoint: if self._makeASymmetric is True: v = self.MfMui * v if isinstance(s_e, Utils.Zero): MeSigmaIDerivT_v = Utils.Zero() else: MeSigmaIDerivT_v = MeSigmaIDeriv(s_e).T * C.T * v RHSDeriv = ( MeSigmaIDerivT_v + s_eDeriv( MeSigmaI.T * (C.T * v)) + s_mDeriv(v) ) return RHSDeriv if isinstance(s_e, Utils.Zero): MeSigmaIDeriv_v = Utils.Zero() else: MeSigmaIDeriv_v = MeSigmaIDeriv(s_e) * v RHSDeriv = ( C * MeSigmaIDeriv_v + C * MeSigmaI * s_eDeriv(v) + s_mDeriv(v) ) if self._makeASymmetric is True: return self.MfMui.T * RHSDeriv return RHSDeriv
def _derivGamma(self, u): if self.gammaMap is None: return Utils.Zero() Ks, A, gamma = self._get_params() ddm = -(A * Ks * np.log(abs(u)) * abs(u)**gamma) / (A + abs(u)**gamma)**2 ddm[u >= 0] = 0 dGamma_dm = Utils.sdiag(ddm) * self.gammaDeriv return dGamma_dm
def MfRhoDeriv(self, u): """ Derivative of :code:`MfRho` with respect to the model. """ if self.rhoMap is None: return Utils.Zero() return (self.mesh.getFaceInnerProductDeriv(self.rho)(u) * self.rhoDeriv)
def _derivBeta(self, u): if self.betaMap is None: return Utils.Zero() theta_r, theta_s, alpha, beta = self._get_params() ddm = -alpha * (-theta_r + theta_s) * np.log( abs(u)) * abs(u)**beta / (alpha + abs(u)**beta)**2 ddm[u >= 0] = 0 dN = Utils.sdiag(ddm) * self.betaDeriv return dN
def _derivAlpha(self, u): if self.alphaMap is None: return Utils.Zero() theta_r, theta_s, alpha, beta = self._get_params() ddm = -alpha * (-theta_r + theta_s) / (alpha + abs(u)**beta)**2 + ( -theta_r + theta_s) / (alpha + abs(u)**beta) ddm[u >= 0] = 0 dA = Utils.sdiag(ddm) * self.alphaDeriv return dA
def s_m(self, prob): """ Magnetic source term :param BaseFDEMProblem prob: FDEM Problem :rtype: numpy.ndarray :return: magnetic source term on mesh """ return Utils.Zero()
def MeSigmaInfDeriv(self, u): """ Derivative of MeSigmaInf with respect to the model """ if self.sigmaInfMap is None: return Utils.Zero() return (self.mesh.getEdgeInnerProductDeriv(self.sigmaInf)(u) * self.sigmaInfDeriv)
def s_e(self, prob): """ Electric source term :param BaseFDEMProblem prob: FDEM Problem :rtype: numpy.ndarray :return: electric source term on mesh """ return Utils.Zero()
def _derivTheta_s(self, u): if self.theta_sMap is None: return Utils.Zero() theta_r, theta_s, alpha, n = self._get_params() P_p, P_n = _get_projections(u) # Compute the positive/negative domains dT_p = P_p * self.theta_sDeriv dT_n = P_n * Utils.sdiag( (abs(alpha * u)**n + 1.0)**(-1.0 + 1.0 / n)) * self.theta_sDeriv return dT_p + dT_n
def getRHSDeriv(self, tInd, src, v, adjoint=False): C = self.mesh.edgeCurl MeSigmaI = self.MeSigmaI def MeSigmaIDeriv(u): return self.MeSigmaIDeriv(u) MfMui = self.MfMui _, s_e = src.eval(self, self.times[tInd]) s_mDeriv, s_eDeriv = src.evalDeriv(self, self.times[tInd], adjoint=adjoint) if adjoint: if self._makeASymmetric is True: v = self.MfMui * v if isinstance(s_e, Utils.Zero): MeSigmaIDerivT_v = Utils.Zero() else: MeSigmaIDerivT_v = MeSigmaIDeriv(s_e).T * C.T * v RHSDeriv = (MeSigmaIDerivT_v + s_eDeriv(MeSigmaI.T * (C.T * v)) + s_mDeriv(v)) return RHSDeriv if isinstance(s_e, Utils.Zero): MeSigmaIDeriv_v = Utils.Zero() else: MeSigmaIDeriv_v = MeSigmaIDeriv(s_e) * v temp = MeSigmaIDeriv_v + MeSigmaI * s_eDeriv(v) + s_mDeriv(v) # TODO: this is because Zero class, which need to be modified if isinstance(temp, Utils.Zero) is False: RHSDeriv = C * temp.astype(float) else: RHSDeriv = C * temp if self._makeASymmetric is True: return self.MfMui.T * RHSDeriv return RHSDeriv
def test_ZeroObjFct(self): # This is not a combo objective function, it will just give back an # L2 objective function. That might be ok? or should this be a combo # objective function? nP = 20 alpha = 2. phi = alpha * (ObjectiveFunction.L2ObjectiveFunction(W=sp.eye(nP)) + Utils.Zero() * ObjectiveFunction.L2ObjectiveFunction()) self.assertTrue(len(phi.objfcts) == 1) self.assertTrue(phi.test())
def _derivKs(self, u): if self.KsMap is None: return Utils.Zero() Ks, A, gamma = self._get_params() P_p, P_n = _get_projections(u) # Compute the positive/negative domains dKs_dm_p = P_p * self.KsDeriv dKs_dm_n = P_n * Utils.sdiag(A / (A + abs(u)**gamma)) * self.KsDeriv return dKs_dm_p + dKs_dm_n
def _derivI(self, u): if self.IMap is None: return Utils.Zero() Ks, alpha, I, n, m = self._get_params() ddm = Ks * (1.0 * (abs(alpha * u)**n + 1.0)**(-1.0 + 1.0 / n))**I * ( -(-(1.0 * (abs(alpha * u)**n + 1.0)**(-1.0 + 1.0 / n))** (1.0 / (1.0 - 1.0 / n)) + 1.0)**(1.0 - 1.0 / n) + 1.0)**2 * np.log(1.0 * (abs(alpha * u)**n + 1.0)**(-1.0 + 1.0 / n)) ddm[u >= 0] = 0 dI = Utils.sdiag(ddm) * self.IDeriv return dI
def _derivAlpha(self, u): if self.alphaMap is None: return Utils.Zero() theta_r, theta_s, alpha, n = self._get_params() ddm = n * u * (-1.0 + 1.0 / n) * (-theta_r + theta_s) * ( abs(alpha * u)**n + 1.0)**(-1.0 + 1.0 / n) * abs( alpha * u)**n * np.sign(alpha * u) / ( (abs(alpha * u)**n + 1.0) * abs(alpha * u)) ddm[u >= 0] = 0 dA = Utils.sdiag(ddm) * self.alphaDeriv return dA
def _derivKs(self, u): if self.KsMap is None: return Utils.Zero() Ks, alpha, I, n, m = self._get_params() P_p, P_n = _get_projections(u) # Compute the positive/negative domains theta_e = 1.0 / ((1.0 + abs(alpha * u)**n)**m) dKs_dm_p = P_p * self.KsDeriv dKs_dm_n = P_n * Utils.sdiag(theta_e**I * ( (1.0 - (1.0 - theta_e**(1.0 / m))**m)**2)) * self.KsDeriv return dKs_dm_p + dKs_dm_n
def _derivN(self, u): if self.nMap is None: return Utils.Zero() theta_r, theta_s, alpha, n = self._get_params() ddm = (-theta_r + theta_s) * ( (-1.0 + 1.0 / n) * np.log(abs(alpha * u)) * abs(alpha * u)**n / (abs(alpha * u)**n + 1.0) - 1.0 * np.log(abs(alpha * u)**n + 1.0) / n**2) * (abs(alpha * u)**n + 1.0)**(-1.0 + 1.0 / n) ddm[u >= 0] = 0 dN = Utils.sdiag(ddm) * self.nDeriv return dN
def s_eDeriv(self, prob, v, adjoint=False): """ Derivative of electric source term with respect to the inversion model :param BaseFDEMProblem prob: FDEM Problem :param numpy.ndarray v: vector to take product with :param bool adjoint: adjoint? :rtype: numpy.ndarray :return: product of electric source term derivative with a vector """ return Utils.Zero()
def getJ_height(self, m): """ Compute d F / d height """ if self.hMap is None: return Utils.Zero() if self._Jmatrix_height is not None: return self._Jmatrix_height if self.verbose: print(">> Compute J height") self.model = m if self.survey.__class__ == GlobalEM1DSurveyFD: run_simulation = run_simulation_FD else: run_simulation = run_simulation_TD if self.parallel: pool = Pool(self.n_cpu) self._Jmatrix_height = pool.map( run_simulation, [ self.input_args(i, jac_switch="sensitivity_height") for i in range(self.n_sounding) ] ) pool.close() pool.join() if self.parallel_jvec_jtvec is False: # self._Jmatrix_height = sp.block_diag(self._Jmatrix_height).tocsr() self._Jmatrix_height = np.hstack(self._Jmatrix_height) self._Jmatrix_height = sp.coo_matrix( (self._Jmatrix_height, self.IJHeight), dtype=float ).tocsr() else: # self._Jmatrix_height = sp.block_diag( # [ # run_simulation(self.input_args(i, jac_switch='sensitivity_height')) for i in range(self.n_sounding) # ] # ).tocsr() self._Jmatrix_height = [ run_simulation(self.input_args(i, jac_switch='sensitivity_height')) for i in range(self.n_sounding) ] self._Jmatrix_height = np.hstack(self._Jmatrix_height) self._Jmatrix_height = sp.coo_matrix( (self._Jmatrix_height, self.IJHeight), dtype=float ).tocsr() return self._Jmatrix_height