def evalDeriv(self, u, v=None, adjoint=False): assert v is not None, 'v to multiply must be provided.' if not adjoint: data = Survey.Data(self) for src in self.srcList: for rx in src.rxList: data[src, rx] = rx.evalDeriv(src, self.mesh, self.prob.timeMesh, u, v) return data else: f = FieldsTDEM(self.mesh, self) for src in self.srcList: for rx in src.rxList: Ptv = rx.evalDeriv(src, self.mesh, self.prob.timeMesh, u, v, adjoint=True) Ptv = Ptv.reshape((-1, self.prob.timeMesh.nN), order='F') if rx.projField not in f: # first time we are projecting f[src, rx.projField, :] = Ptv else: # there are already fields, so let's add to them! f[src, rx.projField, :] += Ptv return f
def _AhtVec(self, m, vec): """ :param numpy.array m: Conductivity model :param FieldsTDEM vec: Fields object :rtype: FieldsTDEM :return: f Multiply the matrix \\\(\\\hat{A}\\\) by a fields vector where .. math:: \mathbf{\hat{A}}^\\top = \left[ \\begin{array}{cccc} A & B & & \\\\ & \ddots & \ddots & \\\\ & & A & B \\\\ & & 0 & A \end{array} \\right] \\\\ \mathbf{A} = \left[ \\begin{array}{cc} \\frac{1}{\delta t} \MfMui & \MfMui\dcurl \\\\ \dcurl^\\top \MfMui & -\MeSig \end{array} \\right] \\\\ \mathbf{B} = \left[ \\begin{array}{cc} -\\frac{1}{\delta t} \MfMui & 0 \\\\ 0 & 0 \end{array} \\right] \\\\ """ self.curModel = m f = FieldsTDEM(self.mesh, self.survey) for i in range(self.nT): b = 1.0 / self.timeSteps[ i] * self.MfMui * vec[:, 'b', i + 1] + self.MfMui * ( self.mesh.edgeCurl * vec[:, 'e', i + 1]) if i < self.nT - 1: b = b - 1.0 / self.timeSteps[i + 1] * self.MfMui * vec[:, 'b', i + 2] f[:, 'b', i + 1] = b f[:, 'e', i + 1] = self.mesh.edgeCurl.T * ( self.MfMui * vec[:, 'b', i + 1]) - self.MeSigma * vec[:, 'e', i + 1] return f
def Gvec(self, m, vec, u=None): """ :param numpy.array m: Conductivity model :param numpy.array vec: vector (like a model) :param FieldsTDEM u: Fields resulting from m :rtype: FieldsTDEM :return: f Multiply G by a vector """ if u is None: u = self.fields(m) self.curModel = m # Note: Fields has shape (nF/E, nSrc, nT+1) # However, p will only really fill (:,:,1:nT+1) # meaning the 'initial fields' are zero (:,:,0) p = FieldsTDEM(self.mesh, self.survey) # 'b' at all times is zero. # However, to save memory we will **not** do: # # p[:, 'b', :] = 0.0 # fake initial 'e' fields p[:, 'e', 0] = 0.0 dMdsig = self.MeSigmaDeriv # self.mesh.getEdgeInnerProductDeriv(self.curModel.transform) # dsigdm_x_v = self.curModel.sigmaDeriv*vec # dsigdm_x_v = self.curModel.transformDeriv*vec for i in range(1, self.nT + 1): # TODO: G[1] may be dependent on the model # for a galvanic source (deriv of the dc problem) # # Do multiplication for all src in self.survey.srcList for src in self.survey.srcList: p[src, 'e', i] = -dMdsig(u[src, 'e', i]) * vec return p