Esempio n. 1
0
    def _getInnerProduct(self,
                         projType,
                         prop=None,
                         invProp=False,
                         invMat=False,
                         doFast=True):
        """
            :param str projType: 'F' for faces 'E' for edges
            :param numpy.array prop: material property (tensor properties are possible) at each cell center (nC, (1, 3, or 6))
            :param bool invProp: inverts the material property
            :param bool invMat: inverts the matrix
            :param bool doFast: do a faster implementation if available.
            :rtype: scipy.sparse.csr_matrix
            :return: M, the inner product matrix (nE, nE)
        """
        assert projType in [
            'F', 'E'
        ], "projType must be 'F' for faces or 'E' for edges"

        fast = None
        if hasattr(self, '_fastInnerProduct') and doFast:
            fast = self._fastInnerProduct(projType,
                                          prop=prop,
                                          invProp=invProp,
                                          invMat=invMat)
        if fast is not None:
            return fast

        if invProp:
            prop = invPropertyTensor(self, prop)

        tensorType = TensorType(self, prop)

        Mu = makePropertyTensor(self, prop)
        Ps = self._getInnerProductProjectionMatrices(projType, tensorType)
        A = np.sum([P.T * Mu * P for P in Ps])

        if invMat and tensorType < 3:
            A = sdInv(A)
        elif invMat and tensorType == 3:
            raise Exception('Solver needed to invert A.')

        return A
Esempio n. 2
0
	def fields(self, v):

		if self.bcflag =='up':
			self.mesh.setCellGradBC(['dirichlet', ['dirichlet', 'neumann']])
		elif self.bcflag =='left':
			self.mesh.setCellGradBC([['neumann', 'dirichlet'], ['dirichlet', 'neumann']])
		elif self.bcflag =='right':
			self.mesh.setCellGradBC([['dirichlet', 'neumann'], ['dirichlet', 'neumann']])

		Grad = self.mesh.cellGrad
		# Be careful about averaging operator
		AvF2CC = self.mesh.dim*self.mesh.aveF2CC
		AvF2CCv = self.mesh.aveF2CCV
		rho = 0.27*np.ones(self.mesh.nC)
		mu = rho*v**2
		Divvec = sp.block_diag((self.mesh.faceDivx, self.mesh.faceDivy))
		Mrhocc = sp.block_diag((sdiag(rho), sdiag(rho)))
		Mmuifvec = sdiag(AvF2CC.T*(1/mu))
		Msigf = sdiag(AvF2CCv.T*np.r_[self.sigx, self.sigy])
		Msigcc =  sp.block_diag((sdiag(self.sigx), sdiag(self.sigy)))
		MrhoccI = sdInv(Mrhocc)
		MmuifvecI = sdInv(Mmuifvec)
		Ivec = sp.hstack((sdiag(np.ones(self.mesh.nC)), sdiag(np.ones(self.mesh.nC))))

		if self.stability==False:
			raise Exception("Stability condition is not satisfied!!")
		elif self.sigx is False:
			print "Warning: Absorbing boundary condition was not set yet!!"
		start = clock()
		print ">> Start Computing Acoustic Wave"
		print (">> dt: %5.2e s")%(self.dt)
		print (">> Optimal dt: %5.2e s")%(self.topt)
		print (">> Main frequency, fmain: %5.2e Hz")%(self.fmain)
		print (">> Cell per wavelength (G): %5.2e")%(self.G)


		if self.storefield==True:
			Phi = []
			#TODO: parallize in terms of sources
			nsrc = len(self.survey.srcList)
			for isrc, src in enumerate(self.survey.srcList):
				print ("  Src at (%7.2f, %7.2f): %4i/%4i")%(src.loc[0], src.loc[0], isrc+1, nsrc)
				phi = np.zeros((self.mesh.nC, src.time.size))
				phin = np.zeros(self.mesh.nC*2)
				phi0 = np.zeros_like(phin)
				un = np.zeros(self.mesh.nF)
				u0 = np.zeros_like(un)
				time = src.time
				dt = src.dt
				q = src.getq(self.mesh)
				qvec = np.r_[q, q]*1/2

				for i in range(time.size-1):
					sn = src.Wave(i+1)
					s0 = src.Wave(i)
					phin = phi0-dt*(Msigcc*phi0)+dt*MrhoccI*(1/dt*(sn-s0)*qvec+Divvec*un)
					phi0 = phin.copy()
					un = u0 - dt*Msigf*u0 + dt*MmuifvecI*Grad*(Ivec*phi0)
					u0 = un.copy()
					phi[:,i+1] = Ivec*phi0
				Phi.append(phi)
			elapsed = clock()-start
			print (">>Elapsed time: %5.2e s")%(elapsed)

			return Phi

		elif self.storefield==False:

			Data = []

			nsrc = len(self.survey.srcList)
			for isrc, src in enumerate(self.survey.srcList):
				print ("  Src at (%7.2f, %7.2f): %4i/%4i")%(src.loc[0], src.loc[0], isrc+1, nsrc)
				phi = np.zeros((mesh.nC, time.size))
				phin = np.zeros(mesh.nC*2)
				phi0 = np.zeros_like(phin)
				un = np.zeros(mesh.nF)
				u0 = np.zeros_like(un)
				time = src.time
				dt = src.dt
				p = np.zeros((self.mesh.nC, time.size))
				q = src.getq(self.mesh)
				qvec = np.r_[q, q]*1/2
				for i in range(time.size-1):
					sn = src.Wave(i+1)
					s0 = src.Wave(i)
					phin = phi0-dt*(Msigcc*phi0)+dt*MrhoccI*(1/dt*(sn-s0)*qvec+Divvec*un)
					phi0 = phin.copy()
					un = u0 - dt*Msigf*u0 + dt*MmuifvecI*Grad*(Ivec*phi0)
					u0 = un.copy()
					data[i,:] =  Proj*(Ivec*phi0)

				Data.append(data)

			elapsed = clock()-start
			print (">>Elapsed time: %5.2e s")%(elapsed)

			return Data
Esempio n. 3
0
    def fields(self, epsilon, mu, sig0):

        Seps = sp.block_diag(
            [sdiag(epsilon * self.sy0),
             sdiag(epsilon * self.sx0)])
        SepsI = sp.block_diag([
            sdiag(1. / (epsilon * self.sy0)),
            sdiag(1. / (epsilon * self.sx0))
        ])
        Sepsisig = sp.block_diag([
            sdiag(sig0 * self.sigy * (1. / epsilon) * self.sy0),
            sdiag(sig0 * self.sigx * (1. / epsilon) * self.sx0)
        ])
        Ssig = sp.block_diag([
            sdiag((self.sigy + sig0) * self.sy0),
            sdiag((self.sigx + sig0) * self.sx0)
        ])
        Mesmuisigs = sdiag(self.mesh.aveE2CCV.T *
                           np.r_[self.sigs * self.sigy / epsilon * self.sy0,
                                 self.sigs * self.sigx / epsilon * self.sx0])
        Messigs = sdiag(
            self.mesh.aveE2CCV.T *
            np.r_[(self.sigs + self.sigy * mu / epsilon) * self.sy0,
                  (self.sigs + self.sigx * mu / epsilon) * self.sx0])
        Mesmu = sdiag(self.mesh.aveE2CCV.T *
                      np.r_[mu * self.sy0, mu * self.sx0])
        MesmuI = sdInv(Mesmu)
        Icc = sp.hstack((speye(self.mesh.nC), speye(self.mesh.nC)))
        curl = self.mesh.edgeCurl
        curlvec = sp.block_diag(
            (curl[:, :self.mesh.nEx], curl[:, self.mesh.nEx:]))

        if self.stability == False:
            raise Exception("Stability condition is not satisfied!!")
        elif self.sigx is False:
            print "Warning: Absorbing boundary condition was not set yet!!"
        start = clock()
        print ""
        print "***** Start Computing Electromagnetic Wave *****"
        print ""
        print(">> dt: %5.2e s") % (self.dt)
        print(">> Optimal dt: %5.2e s") % (self.topt)
        print(">> Main frequency, fmain: %5.2e Hz") % (self.fmain)
        print(">> Cell per wavelength (G): %5.2e") % (self.G)

        if self.storefield == True:
            self._Fields = {}
            #TODO: parallize in terms of sources
            nsrc = len(self.survey.srcList)
            for isrc, src in enumerate(self.survey.srcList):
                print("  Src at (%7.2f, %7.2f): %4i/%4i") % (
                    src.loc[0], src.loc[0], isrc + 1, nsrc)
                h0 = np.zeros(self.mesh.nE)
                h1 = np.zeros(self.mesh.nE)
                hI0 = np.zeros(self.mesh.nE)
                hI1 = np.zeros(self.mesh.nE)

                ed0 = np.zeros(2 * self.mesh.nC)
                ed1 = np.zeros(2 * self.mesh.nC)
                eId0 = np.zeros(2 * self.mesh.nC)
                eId1 = np.zeros(2 * self.mesh.nC)

                time = src.time
                dt = src.dt
                je, jm = src.getq(self.mesh)
                h = np.zeros((self.mesh.nE, time.size))
                e = np.zeros((self.mesh.nC, time.size))

                for i in range(time.size - 1):

                    eId0 = eId1.copy()
                    eId1 = eId0 + dt * ed0

                    ed1 = ed0 + SepsI * dt * (
                        curlvec *
                        (h1) - Ssig * ed0 - Sepsisig * eId1 - je * src.wave[i])
                    ed0 = ed1.copy()
                    e[:, i] = Icc * ed1

                    hI0 = hI1.copy()
                    hI1 = hI0 + dt * h0
                    h1 = h0 - MesmuI * dt * (curl.T * (Icc * ed0) +
                                             Messigs * h0 + Mesmuisigs * hI1 +
                                             jm * src.wave[i])
                    h0 = h1.copy()
                    h[:, i] = h1

                self._Fields['E', src] = e
                self._Fields['H', src] = h

            elapsed = clock() - start
            print(">>Elapsed time: %5.2e s") % (elapsed)

            return self._Fields

        elif self.storefield == False:
            Data = {}
            nsrc = len(self.survey.srcList)
            for isrc, src in enumerate(self.survey.srcList):
                print("  Src at (%7.2f, %7.2f): %4i/%4i") % (
                    src.loc[0], src.loc[0], isrc + 1, nsrc)
                h0 = np.zeros(mesh.nE)
                h1 = np.zeros(mesh.nE)
                hI0 = np.zeros(mesh.nE)
                hI1 = np.zeros(mesh.nE)

                ed0 = np.zeros(2 * mesh.nC)
                ed1 = np.zeros(2 * mesh.nC)
                eId0 = np.zeros(2 * mesh.nC)
                eId1 = np.zeros(2 * mesh.nC)

                time = src.time
                dt = src.dt
                je, jm = src.getq(self.mesh)
                h = np.zeros((mesh.nE, time.size))
                e = np.zeros((mesh.nC, time.size))

                for i in range(time.size - 1):
                    eId0 = eId1.copy()
                    eId1 = eId0 + dt * ed0

                    ed1 = ed0 + SepsI * dt * (curlvec * (h1) - Ssig * ed0 -
                                              Sepsisig * eId1 - je * wave[i])
                    ed0 = ed1.copy()
                    e[:, i] = Icc * ed1

                    hI0 = hI1.copy()
                    hI1 = hI0 + dt * h0
                    h1 = h0 - MesmuI * dt * (curl.T *
                                             (Icc * ed0) + Messigs * h0 +
                                             Mesmuisigs * hI1 + jm * wave[i])
                    h0 = h1.copy()
                    h[:, i] = h1

                for rx in src.rxList:
                    Proj = rx.getP(self.mesh)
                    if rx.rxtype.find('E') >= 0:
                        flag = 'E'
                        Data[src, rx] = (Proj * e)
                    elif rx.rxtype.find('H') >= 0:
                        flag = 'H'
                        Data[src, rx] = (Proj * h)

            elapsed = clock() - start
            print(">>Elapsed time: %5.2e s") % (elapsed)

            return Data
Esempio n. 4
0
    def fields(self, epsilon, mu, sig0):

        Smu = sp.block_diag([sdiag(mu*self.sy0), sdiag(mu*self.sx0)])
        SmuI = sp.block_diag([sdiag(1./(mu*self.sy0)), sdiag(1./(mu*self.sx0))])
        Smuisig = sp.block_diag([sdiag(self.sigs*self.sigy*(1./epsilon)*self.sy0), sdiag(self.sigs*self.sigx*(1./epsilon)*self.sx0)])
        Ssig = sp.block_diag([sdiag((self.sigy*mu/epsilon+self.sigs)*self.sy0), sdiag((self.sigx*mu/epsilon+self.sigs)*self.sx0)])
        Mesepsisig = sdiag(self.mesh.aveE2CCV.T*np.r_[1./epsilon*sig0*self.sigy*self.sy0, 1./epsilon*sig0*self.sigx*self.sx0])
        Messig = sdiag(self.mesh.aveE2CCV.T*np.r_[(sig0+self.sigy)*self.sy0, (sig0+self.sigx)*self.sx0])
        Meseps = sdiag(self.mesh.aveE2CCV.T*np.r_[epsilon*self.sy0, epsilon*self.sx0])
        MesepsI = sdInv(Meseps)
        Icc = sp.hstack((speye(self.mesh.nC), speye(self.mesh.nC)))
        curl = self.mesh.edgeCurl
        curlvec = sp.block_diag((curl[:,:self.mesh.nEx], curl[:,self.mesh.nEx:]))

        if self.stability==False:
            raise Exception("Stability condition is not satisfied!!")
        elif self.sigx is False:
            print "Warning: Absorbing boundary condition was not set yet!!"
        start = clock()
        print ""
        print "***** Start Computing Electromagnetic Wave *****"
        print ""
        print (">> dt: %5.2e s")%(self.dt)
        print (">> Optimal dt: %5.2e s")%(self.topt)
        print (">> Main frequency, fmain: %5.2e Hz")%(self.fmain)
        print (">> Cell per wavelength (G): %5.2e")%(self.G)


        if self.storefield==True:
            self._Fields ={}
            #TODO: parallize in terms of sources
            nsrc = len(self.survey.srcList)
            for isrc, src in enumerate(self.survey.srcList):
                print ("  Src at (%7.2f, %7.2f): %4i/%4i")%(src.loc[0], src.loc[0], isrc+1, nsrc)
                hd0 = np.zeros(2*self.mesh.nC)
                hd1 = np.zeros(2*self.mesh.nC)
                hId0 = np.zeros(2*self.mesh.nC)
                hId1 = np.zeros(2*self.mesh.nC)
                e0 = np.zeros(self.mesh.nE)
                e1 = np.zeros(self.mesh.nE)
                eI0 = np.zeros(self.mesh.nE)
                eI1 = np.zeros(self.mesh.nE)
                time = src.time
                dt = src.dt
                jm, je = src.getq(self.mesh)
                h = np.zeros((self.mesh.nC, time.size))
                e = np.zeros((self.mesh.nE, time.size))

                for i in range(time.size-1):
                    eI0 = eI1.copy()
                    eI1 = eI0 + dt*e0
                    e1 = e0 + MesepsI*dt*(curl.T*(Icc*hd1)-Messig*e0-Mesepsisig*eI1-je*src.wave[i])
                    e0 = e1.copy()
                    e[:,i] = e1
                    hId0 = hId1.copy()
                    hId1 = hId0 + dt*hd0
                    hd1 = hd0 - SmuI*dt*(curlvec*e0+Ssig*hd0+Smuisig*hId1+jm*src.wave[i]*0.5)
                    hd0 = hd1.copy()
                    h[:,i] = Icc*hd1

                self._Fields['E', src]= e
                self._Fields['H', src]= h
            elapsed = clock()-start
            print (">>Elapsed time: %5.2e s")%(elapsed)

            return self._Fields


        elif self.storefield==False:
            Data = {}
            nsrc = len(self.survey.srcList)
            for isrc, src in enumerate(self.survey.srcList):
                print ("  Src at (%7.2f, %7.2f): %4i/%4i")%(src.loc[0], src.loc[0], isrc+1, nsrc)
                hd0 = np.zeros(2*mesh.nC)
                hd1 = np.zeros(2*mesh.nC)
                hId0 = np.zeros(2*mesh.nC)
                hId1 = np.zeros(2*mesh.nC)
                e0 = np.zeros(mesh.nE)
                e1 = np.zeros(mesh.nE)
                eI0 = np.zeros(mesh.nE)
                eI1 = np.zeros(mesh.nE)
                time = src.time
                dt = src.dt
                jm, je = src.getq(self.mesh)
                h = np.zeros((mesh.nC, time.size))
                e = np.zeros((mesh.nE, time.size))

                for i in range(time.size-1):
                    eI0 = eI1.copy()
                    eI1 = eI0 + dt*e0
                    e1 = e0 + MesepsI*dt*(curl.T*(Icc*hd1)-Messig*e0-Mesepsisig*eI1-je*src.wave[i])
                    e0 = e1.copy()
                    e[:,i] = e1
                    hId0 = hId1.copy()
                    hId1 = hId0 + dt*hd0
                    hd1 = hd0 - SmuI*dt*(curlvec*e0+Ssig*hd0+Smuisig*hId1+jm*src.wave[i])
                    hd0 = hd1.copy()
                    h[:,i] = Icc*hd1

                for rx in src.rxList:
                    Proj = rx.getP(self.mesh)
                    if rx.rxtype.find('E') >= 0:
                        flag = 'E'
                        Data[src, rx] = (Proj*e)
                    elif rx.rxtype.find('H') >= 0:
                        flag = 'H'
                        Data[src, rx] = (Proj*h)

            elapsed = clock()-start
            print (">>Elapsed time: %5.2e s")%(elapsed)

            return Data
Esempio n. 5
0
    def fields(self, v):

        if self.bcflag == 'up':
            self.mesh.setCellGradBC(['dirichlet', ['dirichlet', 'neumann']])
        elif self.bcflag == 'left':
            self.mesh.setCellGradBC([['neumann', 'dirichlet'],
                                     ['dirichlet', 'neumann']])
        elif self.bcflag == 'right':
            self.mesh.setCellGradBC([['dirichlet', 'neumann'],
                                     ['dirichlet', 'neumann']])

        Grad = self.mesh.cellGrad
        # Be careful about averaging operator
        AvF2CC = self.mesh.dim * self.mesh.aveF2CC
        AvF2CCv = self.mesh.aveF2CCV
        rho = 0.27 * np.ones(self.mesh.nC)
        mu = rho * v**2
        Divvec = sp.block_diag((self.mesh.faceDivx, self.mesh.faceDivy))
        Mrhocc = sp.block_diag((sdiag(rho), sdiag(rho)))
        Mmuifvec = sdiag(AvF2CC.T * (1 / mu))
        Msigf = sdiag(AvF2CCv.T * np.r_[self.sigx, self.sigy])
        Msigcc = sp.block_diag((sdiag(self.sigx), sdiag(self.sigy)))
        MrhoccI = sdInv(Mrhocc)
        MmuifvecI = sdInv(Mmuifvec)
        Ivec = sp.hstack(
            (sdiag(np.ones(self.mesh.nC)), sdiag(np.ones(self.mesh.nC))))

        if self.stability == False:
            raise Exception("Stability condition is not satisfied!!")
        elif self.sigx is False:
            print "Warning: Absorbing boundary condition was not set yet!!"
        start = clock()
        print ">> Start Computing Acoustic Wave"
        print(">> dt: %5.2e s") % (self.dt)
        print(">> Optimal dt: %5.2e s") % (self.topt)
        print(">> Main frequency, fmain: %5.2e Hz") % (self.fmain)
        print(">> Cell per wavelength (G): %5.2e") % (self.G)

        if self.storefield == True:
            Phi = []
            #TODO: parallize in terms of sources
            nsrc = len(self.survey.srcList)
            for isrc, src in enumerate(self.survey.srcList):
                print("  Src at (%7.2f, %7.2f): %4i/%4i") % (
                    src.loc[0], src.loc[0], isrc + 1, nsrc)
                phi = np.zeros((self.mesh.nC, src.time.size))
                phin = np.zeros(self.mesh.nC * 2)
                phi0 = np.zeros_like(phin)
                un = np.zeros(self.mesh.nF)
                u0 = np.zeros_like(un)
                time = src.time
                dt = src.dt
                q = src.getq(self.mesh)
                qvec = np.r_[q, q] * 1 / 2

                for i in range(time.size - 1):
                    sn = src.Wave(i + 1)
                    s0 = src.Wave(i)
                    phin = phi0 - dt * (Msigcc * phi0) + dt * MrhoccI * (
                        1 / dt * (sn - s0) * qvec + Divvec * un)
                    phi0 = phin.copy()
                    un = u0 - dt * Msigf * u0 + dt * MmuifvecI * Grad * (Ivec *
                                                                         phi0)
                    u0 = un.copy()
                    phi[:, i + 1] = Ivec * phi0
                Phi.append(phi)
            elapsed = clock() - start
            print(">>Elapsed time: %5.2e s") % (elapsed)

            return Phi

        elif self.storefield == False:

            Data = []

            nsrc = len(self.survey.srcList)
            for isrc, src in enumerate(self.survey.srcList):
                print("  Src at (%7.2f, %7.2f): %4i/%4i") % (
                    src.loc[0], src.loc[0], isrc + 1, nsrc)
                phi = np.zeros((mesh.nC, time.size))
                phin = np.zeros(mesh.nC * 2)
                phi0 = np.zeros_like(phin)
                un = np.zeros(mesh.nF)
                u0 = np.zeros_like(un)
                time = src.time
                dt = src.dt
                p = np.zeros((self.mesh.nC, time.size))
                q = src.getq(self.mesh)
                qvec = np.r_[q, q] * 1 / 2
                for i in range(time.size - 1):
                    sn = src.Wave(i + 1)
                    s0 = src.Wave(i)
                    phin = phi0 - dt * (Msigcc * phi0) + dt * MrhoccI * (
                        1 / dt * (sn - s0) * qvec + Divvec * un)
                    phi0 = phin.copy()
                    un = u0 - dt * Msigf * u0 + dt * MmuifvecI * Grad * (Ivec *
                                                                         phi0)
                    u0 = un.copy()
                    data[i, :] = Proj * (Ivec * phi0)

                Data.append(data)

            elapsed = clock() - start
            print(">>Elapsed time: %5.2e s") % (elapsed)

            return Data
Esempio n. 6
0
class ProblemATEMIP_b(BaseATEMIPProblem_b):
    """
        Time-Domain EM-IP problem - B-formulation
        TDEM_b treats the following discretization of Maxwell's equations

    """

    store_fields = False  # Only store magnetic field
    sigmaHatDict = {}

    def __init__(self, mesh, mapping=None, **kwargs):
        BaseATEMIPProblem_b.__init__(self, mesh, mapping=mapping, **kwargs)

    solType = 'b'  #: Type of the solution, in this case the 'b' field
    surveyPair = SurveyTDEM
    _FieldsForward_pair = FieldsATEMIP_store_bej  #: used for the forward calculation only

    ####################################################
    # Internal Methods
    ####################################################

    def sigmaHat(self, t, ColeColefunc=ColeCole):
        etc = np.c_[self.curModel.eta, self.curModel.tau, self.curModel.c]
        unqEtc, uETCind, invInd = uniqueRows(etc)

        sigmaHat = []
        for (ev, tv, cv) in unqEtc:
            if ev == 0.:
                sigmaHat.append(0.)
            else:

                key = '%.5e_%.5f_%.5e_%.5f' % (t, ev, tv, cv)
                if self.sigmaHatDict.has_key(key):
                    val = self.sigmaHatDict[key]
                else:
                    if t == 0:
                        # val = transFilt(F,1e-6)
                        val = ev / (tv * (1. - ev))
                    else:
                        F = lambda frq: (1j * 2 * np.pi * frq) * ColeColefunc(
                            frq, sigmaInf=1., eta=ev, tau=tv, c=cv)
                        val = transFilt(F, t)
                    self.sigmaHatDict[key] = val
                sigmaHat.append(val)

        sigmaHat = self.curModel.sigmaInf * np.array(sigmaHat)[invInd]
        return sigmaHat

    @property
    def MeSigmaInf(self):
        if getattr(self, '_MeSigmaInf', None) is None:
            self._MeSigmaInf = self.mesh.getEdgeInnerProduct(
                self.curModel.sigmaInf)
        return self._MeSigmaInf

    @property
    def MeI(self):
        if getattr(self, '_MeI', None) is None:
            self._MeI = self.mesh.getEdgeInnerProduct(invMat=True)
        return self._MeI

    def MeAc(self, dt):
        gamma = self.getGamma(dt)
        val = self.curModel.sigmaInf - gamma
        return self.mesh.getEdgeInnerProduct(val)

    MeAcI = lambda self, dt: sdInv(self.MeAc(dt))

    def MeCnk(self, n, k):
        tn = self.times[n]
        tk = self.times[k]
        val = self.sigmaHat(tn - tk)
        return self.mesh.getEdgeInnerProduct(val)

    _nJpLast = None
    _JpLast = None

    def getJp(self, tInd, F):
        """
    		Computation of polarization currents
    	"""
        # It calls twice !!!
        # a) getRHS
        # b) updateFields

        if tInd == self._nJpLast:
            # print ">> Curious when self._nJpLast is used:", self._nJpLast
            jp = self._JpLast
        else:
            dt = self.timeSteps[tInd]
            kappa = self.getKappa(dt)
            MeK = self.mesh.getEdgeInnerProduct(kappa)
            jp = MeK * F[:, 'e', tInd]
            for k in range(tInd):
                dt = self.timeSteps[k]
                jp += (dt / 2) * self.MeCnk(tInd + 1, k) * F[:, 'e', k + 1]
                jp += (dt / 2) * self.MeCnk(tInd + 1, k + 1) * F[:, 'e', k + 1]
            self._nJpLast = tInd
            self._JpLast = jp
        return jp

    def getA(self, tInd):
        """
            :param int tInd: Time index
            :rtype: scipy.sparse.csr_matrix
            :return: A
        """
        dt = self.timeSteps[tInd]
        return self.MfMui * self.mesh.edgeCurl * self.MeAcI(
            dt) * self.mesh.edgeCurl.T * self.MfMui + self.MfMui * (1.0 / dt)

    def getRHS(self, tInd, F):
        dt = self.timeSteps[tInd]
        B_last = F[:, 'b', tInd]
        RHS = self.MfMui*(1/dt)*B_last \
            - self.MfMui*self.mesh.edgeCurl*self.MeAcI(dt)*self.getJp(tInd, F)
        if self.waveformType != "STEPOFF":
            RHS += self.MfMui * self.mesh.edgeCurl * self.MeAcI(
                dt) * self.MeS * self.current[tInd + 1]
        return RHS

    def updateFields(self, bn, tInd, F):
        dt = self.timeSteps[tInd]
        jp = self.getJp(tInd, F)
        en = self.MeAcI(dt)*self.mesh.edgeCurl.T*self.MfMui*bn \
           + self.MeAcI(dt)*jp
        if self.waveformType != "STEPOFF":
            en -= self.MeAcI(dt) * self.MeS * self.current[tInd + 1]
        jn = self.MeI * (self.MeAc(dt) * en - jp)
        return en, jn

    def getKappa(self, dt):
        setc = np.c_[self.curModel.sigmaInf, self.curModel.eta,
                     self.curModel.tau, self.curModel.c]
        unqEtc, uETCind, invInd = uniqueRows(setc)
        kappaVals = []
        for (sv, ev, tv, cv) in unqEtc:
            if ev == 0:
                kappaVal = 0.
            elif cv == 1.:
                kappaVal = (dt / 2.) * sv * ev / ((1. - ev) * tv)
            else:
                m, d = self.getMD(dt, sv, ev, tv, cv)
                kappaVal = (m * dt**cv) / (cv + 1) + d * dt / 2
            kappaVals.append(kappaVal)
        kappa = np.array(kappaVals)[invInd]
        return kappa

    def getGamma(self, dt):
        setc = np.c_[self.curModel.sigmaInf, self.curModel.eta,
                     self.curModel.tau, self.curModel.c]
        unqEtc, uETCind, invInd = uniqueRows(setc)
        gammaVals = []
        for (sv, ev, tv, cv) in unqEtc:
            if ev == 0:
                gammaVal = 0.
            elif cv == 1.:
                gammaVal = (dt / 2.) * sv * ev / ((1. - ev) * tv)
            else:
                m, d = self.getMD(dt, sv, ev, tv, cv)
                gammaVal = (m * dt**cv) / (cv * (cv + 1)) + d * dt / 2.
            gammaVals.append(gammaVal)
        gamma = np.array(gammaVals)[invInd]
        return gamma

    def getMD(self, dt, sv, ev, tv, cv):
        def CCTF(t, sigmaInf, eta, tau, c):
            F = lambda frq: (1j * 2 * np.pi * frq) * ColeCole(
                frq, sigmaInf=sigmaInf, eta=eta, tau=tau, c=c)
            return transFilt(F, t)

        t = np.r_[1e-20, dt]

        y = CCTF(t, sv, ev, tv, cv)
        x = t**(cv - 1)
        m = (y[0] - y[1]) / (x[0] - x[1])
        d = y[1] - m * x[1]
        return m, d