def getPotentialNumeric(self): """ Returns 3 list each made up of a number of list containing primary, secondary and total potentials diferences. Each of the lists contain a list for each value of n. """ primCon=self.primaryConductivity coords=self.domain.getX() tol=1e-8 pde=LinearPDE(self.domain, numEquations=1) pde.getSolverOptions().setTolerance(tol) pde.setSymmetryOn() primaryPde=LinearPDE(self.domain, numEquations=1) primaryPde.getSolverOptions().setTolerance(tol) primaryPde.setSymmetryOn() DIM=self.domain.getDim() x=self.domain.getX() q=es.whereZero(x[DIM-1]-es.inf(x[DIM-1])) for i in xrange(DIM-1): xi=x[i] q+=es.whereZero(xi-es.inf(xi))+es.whereZero(xi-es.sup(xi)) A = self.secondaryConductivity * es.kronecker(self.domain) APrimary = self.primaryConductivity * es.kronecker(self.domain) pde.setValue(A=A,q=q) primaryPde.setValue(A=APrimary,q=q) delPhiSecondaryList = [] delPhiPrimaryList = [] delPhiTotalList = [] for i in range(1,self.n+1): # 1 to n maxR = self.numElectrodes - 1 - (2*i) #max amount of readings that will fit in the survey delPhiSecondary = [] delPhiPrimary = [] delPhiTotal = [] for j in range(maxR): y_dirac=es.Scalar(0,es.DiracDeltaFunctions(self.domain)) y_dirac.setTaggedValue(self.electrodeTags[j],self.current) y_dirac.setTaggedValue(self.electrodeTags[j + ((2*i) + 1)],-self.current) self.sources.append([self.electrodeTags[j], self.electrodeTags[j + ((2*i) + 1)]]) primaryPde.setValue(y_dirac=y_dirac) numericPrimaryPot = primaryPde.getSolution() X=(primCon-self.secondaryConductivity) * es.grad(numericPrimaryPot) pde.setValue(X=X) u=pde.getSolution() loc=Locator(self.domain,[self.electrodes[j+i],self.electrodes[j+i+1]]) self.samples.append([self.electrodeTags[j+i],self.electrodeTags[j+i+1]]) valPrimary=loc.getValue(numericPrimaryPot) valSecondary=loc.getValue(u) delPhiPrimary.append(valPrimary[1]-valPrimary[0]) delPhiSecondary.append(valSecondary[1]-valSecondary[0]) delPhiTotal.append(delPhiPrimary[j]+delPhiSecondary[j]) delPhiPrimaryList.append(delPhiPrimary) delPhiSecondaryList.append(delPhiSecondary) delPhiTotalList.append(delPhiTotal) self.delPhiPrimaryList=delPhiPrimaryList self.delPhiSecondaryList=delPhiSecondaryList self.delPhiTotalList = delPhiTotalList return [delPhiPrimaryList, delPhiSecondaryList, delPhiTotalList]
def __init__(self, domain, pore0=0., perm=1.e-5, kf=2.2e9, dt=0.001, ng=1, useMPI=False, np=1, rtol=1.e-2): """ initialization of the problem, i.e. model constructor :param domain: type Domain, domain of the problem :param pore0: type float, initial pore pressure :param perm: type float, d^2/(150 mu_f) in KC equation :param kf: type float, bulk modulus of the fluid :param dt: type float, time step for calculation :param ng: type integer, number of Gauss points :param useMPI: type boolean, use MPI or not :param np: type integer, number of processors :param rtol: type float, relevative tolerance for global convergence """ self.__domain = domain self.__upde = LinearPDE(domain, numEquations=domain.getDim(), numSolutions=domain.getDim()) self.__ppde = LinearPDE(domain, numEquations=1, numSolutions=1) # use reduced interpolation for pore pressure self.__ppde.setReducedOrderOn() self.__upde.getSolverOptions().setSolverMethod(SolverOptions.DIRECT) self.__ppde.getSolverOptions().setSolverMethod(SolverOptions.DIRECT) self.__upde.setSymmetryOn() self.__ppde.setSymmetryOn() self.__dt = dt self.__bulkFluid = kf self.__numGaussPoints = ng self.__rtol = rtol self.__stress = escript.Tensor(0, escript.Function(domain)) self.__S = escript.Tensor4(0, escript.Function(domain)) self.__pool = get_pool(mpi=useMPI, threads=np) self.__scenes = self.__pool.map(initLoad, range(ng)) st = self.__pool.map(getStressAndTangent2D, self.__scenes) for i in xrange(ng): self.__stress.setValueOfDataPoint(i, st[i][0]) self.__S.setValueOfDataPoint(i, st[i][1]) self.__strain = escript.Tensor(0, escript.Function(domain)) self.__pore = escript.Scalar(pore0, escript.ReducedSolution(domain)) self.__pgauss = util.interpolate(pore0, escript.Function(domain)) self.__permeability = perm self.__meanStressRate = escript.Scalar(0, escript.Function(domain)) self.__r = escript.Vector( 0, escript.Solution(domain)) #Dirichlet BC for u
def __init__(self, domain, debug=False): super(StokesProblem, self).__init__(self, debug) self.domain = domain self.__pde_u = LinearPDE(domain, numEquations=self.domain.getDim(), numSolutions=self.domain.getDim()) self.__pde_u.setSymmetryOn() self.__pde_p = LinearPDE(domain) self.__pde_p.setReducedOrderOn() self.__pde_p.setSymmetryOn()
def __init__(self, domain): super(SimpleStokesProblem, self).__init__(self) self.__pde_u = LinearPDE(domain) self.__pde_u.setSymmetryOn() self.__pde_u.setValue(A=identityTensor4(dom)) self.__pde_p = LinearPDE(domain) self.__pde_p.setReducedOrderOn() self.__pde_p.setSymmetryOn() self.__pde_p.setValue(D=1.)
def test_PDE2D(self): dx_tests = 0.1 sigma0 = 1. electrodes = [(0.5 - 2 * dx_tests, 1.), (0.5 - dx_tests, 1.), (0.5 + dx_tests, 1.), (0.5 + 2 * dx_tests, 1.)] domain = finRectangle(20, 20, d1=mpisize, diracPoints=electrodes, diracTags=["sl0", "sl1", "sr0", "sr1"]) loc = Locator(domain, electrodes[2:]) # this creates some reference Data: x = domain.getX() q = whereZero(x[0] - inf(x[0])) + whereZero( x[0] - sup(x[0])) + whereZero(x[1] - inf(x[1])) ppde = LinearPDE(domain, numEquations=1) s = Scalar(0., DiracDeltaFunctions(domain)) s.setTaggedValue("sl0", 1.) s.setTaggedValue("sl1", -1.) ppde.setValue(A=kronecker(2) * sigma0, q=q, y_dirac=s) pp = ppde.getSolution() uu = loc(pp) # arguments for DcRes current = 10. sourceInfo = ["sl0", "sl1"] sampleTags = [("sr0", "sr1")] sigmaPrimary = 7. phiPrimary = pp * current * sigma0 / sigmaPrimary uuscale = 1 - current * sigma0 / sigmaPrimary delphi_in = [(uu[1] - uu[0]) * uuscale] acw = DcRes(domain, loc, delphi_in, sampleTags, phiPrimary, sigmaPrimary) self.assertLess(Lsup(phiPrimary - acw.getPrimaryPotential()), 1.e-10 * Lsup(acw.getPrimaryPotential())) SIGMA = 10. # matches current args0 = acw.getArguments(SIGMA) p = args0[0] u = args0[1] # true secondary potential pps = pp - phiPrimary self.assertLess(Lsup(p - pps), 1.e-6 * Lsup(pps)) # test return values at electrodes: self.assertLess(abs(u[0] - uu[0] * uuscale), 1.e-6 * abs(uu[0] * uuscale)) self.assertLess(abs(u[1] - uu[1] * uuscale), 1.e-6 * abs(uu[1] * uuscale)) # this sould be zero dd = acw.getDefect(SIGMA, *args0) self.assertTrue(dd >= 0.) self.assertTrue(dd <= 1e-7)
def __init__(self, domain, pml_condition=None, frequency=None, vp=None, fix_boundary=True): """ Initialise the class with domain, boundary conditions and frequency. Setup PDE :param domain: the domain : setup with Dirac points :type domain: `Domain` :param pml_condition: :type pml_condition: :param frequency: :type frequency: :param vp: velocity field :type vp: `Data` :param fix_boundary: if true fix all the boundaries except the top :type fix_boundary: `bool` """ Dim=domain.getDim() self.pde=LinearPDE(domain, numEquations=1, numSolutions=1, isComplex=True) self.pde.getSolverOptions().setSolverMethod(SolverOptions.DIRECT) self.pml=pml_condition if not self.pml: self.pde.setValue(A=kronecker(domain)) self.J=1. if fix_boundary: x=domain.getX() q=whereZero(x[Dim-1]-inf(x[Dim-1])) for i in range(Dim-1): q+=whereZero(x[i]-inf(x[i]))+whereZero(x[i]-sup(x[i])) self.pde.setValue(q=q) self.setFrequency(frequency) self.setVp(vp)
def setUpPDE(self): """ Return the underlying PDE. :rtype: `LinearPDE` """ if self.__pde is None: dom = self.__domain x = dom.getX() DIM = dom.getDim() q = whereZero(x[DIM - 1] - inf(x[DIM - 1])) for i in range(DIM - 1): xi = x[i] q += whereZero(xi - inf(xi)) + whereZero(xi - sup(xi)) pde = LinearPDE(dom, numEquations=1) pde.getSolverOptions().setTolerance(self.__tol) pde.setSymmetryOn() A = pde.createCoefficient('A') X = pde.createCoefficient('X') pde.setValue(A=A, X=X, q=q) else: pde = self.__pde pde.resetRightHandSideCoefficients() return pde
def __init__(self, domain): super(SlippingFault, self).__init__(self) self.domain = domain self.__pde_u = LinearPDE(domain, numEquations=self.domain.getDim(), numSolutions=self.domain.getDim()) self.__pde_u.setSymmetryOn()
def getPDE(self, system, iscomplex=False): dim = self.domain.getDim() if system: pde=LinearPDE(self.domain, numEquations=dim, isComplex=iscomplex) else: pde=LinearPDE(self.domain, numEquations=1, isComplex=iscomplex) self.setCoefficients(pde, system) so = pde.getSolverOptions() so.setPackage(self.package) so.setSolverMethod(self.method) so.setPreconditioner(self.preconditioner) so.setTolerance(self.SOLVER_TOL) so.setVerbosity(self.SOLVER_VERBOSE) pde.setSolverOptions(so) return pde, self.getSolution(system), self.getGrad(system)
def doInitialization(self): """ initialize model """ if not self.displacement: self.displacement = Vector(0., ContinuousFunction(self.domain)) if not self.velocity: self.velocity = Vector(0., ContinuousFunction(self.domain)) if not self.stress: self.stress = Tensor(0., ContinuousFunction(self.domain)) if not self.internal_force: self.internal_force = Data() if not self.external_force: self.external_force = Data() if not self.prescribed_velocity: self.prescribed_velocity = Data() if not self.location_prescribed_velocity: self.location_prescribed_velocity = Data() # save the old values: self.__stress_safe = self.stress self.__temperature_safe = self.temperature self.__displacement_safe = self.displacement self.__velocity_safe = self.velocity self.__velocity_old = None self.__old_dt = None self.__very_old_dt = None # get node cooridnates and apply initial displacement self.__x = self.domain.getX() self.domain.setX(self.__x + self.displacement) # open PDE: self.__pde = LinearPDE(self.domain) self.__pde.setSolverMethod(self.__pde.DIRECT) self.__solver_options = self.__pde.getSolverOptions() self.__solver_options.setSolverMethod(self.__solver_options.DIRECT) self.__solver_options.setVerbosity(self.debug)
def wavePropagation(domain, h, tend, lam, mu, rho, xc, src_radius, U0): # lists to collect displacement at point source ts, u_pc0, u_pc1, u_pc2 = [], [], [], [] x = domain.getX() # ... open new PDE ... mypde = LinearPDE(domain) mypde.getSolverOptions().setSolverMethod(SolverOptions.HRZ_LUMPING) kron = kronecker(mypde.getDim()) dunit = numpy.array([1., 0., 0.]) # defines direction of point source mypde.setValue(D=kron * rho, q=whereNegative(length(x - xc) - src_radius) * dunit) # ... set initial values .... n = 0 # for first two time steps u = Vector(0., Solution(domain)) u_last = Vector(0., Solution(domain)) t = 0 # define the location of the point source L = Locator(domain, xc) # find potential at point source u_pc = L.getValue(u) print("u at point charge = %s" % u_pc) ts.append(t) u_pc0.append(u_pc[0]), u_pc1.append(u_pc[1]), u_pc2.append(u_pc[2]) while t < tend: t += h # ... get current stress .... g = grad(u) stress = lam * trace(g) * kron + mu * (g + transpose(g)) # ... get new acceleration .... amplitude = U0 * (4 * (t - t0)**3 / alpha**3 - 6 * (t - t0) / alpha) * sqrt(2.) / alpha**2 * exp( 1. / 2. - (t - t0)**2 / alpha**2) mypde.setValue(X=-stress, r=dunit * amplitude) a = mypde.getSolution() # ... get new displacement ... u_new = 2 * u - u_last + h**2 * a # ... shift displacements .... u_last = u u = u_new n += 1 print("time step %d, t = %s" % (n, t)) u_pc = L.getValue(u) print("u at point charge = %s" % u_pc) ts.append(t) u_pc0.append(u_pc[0]), u_pc1.append(u_pc[1]), u_pc2.append(u_pc[2]) # ... save current acceleration in units of gravity and displacements if n == 1 or n % 10 == 0: saveVTK("./data/usoln.%i.vtu" % (n / 10), acceleration=length(a) / 9.81, displacement=length(u), tensor=stress, Ux=u[0]) return ts, u_pc0, u_pc1, u_pc2
def __init__(self,domain,dim,ng=1,useMPI=False,np=1,rho=2.35e3,mIds=False,\ FEDENodeMap=False,DE_ext=False,FEDEBoundMap=False,conf=False): """ initialization of the problem, i.e. model constructor :param domain: type Domain, domain of the problem :param ng: type integer, number of Gauss points :param useMPI: type boolean, use MPI or not :param np: type integer, number of processors :param rho: type float, density of material :param mIds: a list contains membrane node IDs :param FEDENodeMap: a dictionary with FE and DE boundary node IDs in keys and values :param DE_ext: name of file which saves initial state of exterior DE domain :param FEDEBoundMap: a dictionary with FE and DE boundary element IDs in keys and values (deprecated) :param conf: type float, conf pressure on membrane """ self.__domain = domain self.__pde = LinearPDE(self.__domain, numEquations=dim, numSolutions=dim) self.__pde.getSolverOptions().setSolverMethod( SolverOptions.HRZ_LUMPING) self.__pde.setSymmetryOn() self.__numGaussPoints = ng self.__rho = rho self.__mIds = mIds self.__FEDENodeMap = FEDENodeMap self.__FEDEBoundMap = FEDEBoundMap self.__conf = conf self.__pool = get_pool(mpi=useMPI, threads=np) self.__scenes = self.__pool.map(initLoad, range(ng)) self.__strain = escript.Tensor(0, escript.Function(self.__domain)) self.__stress = escript.Tensor(0, escript.Function(self.__domain)) self.__u = escript.Vector(0, escript.Solution(self.__domain)) self.__u_last = escript.Vector(0, escript.Solution(self.__domain)) self.__u_t = escript.Vector(0, escript.Solution(self.__domain)) self.__dt = 0 # ratio between timesteps in internal DE and FE domain self.__nsOfDE_int = 1 # if FEDENodeMap is given, employ exterior DE domain if self.__FEDENodeMap: self.__sceneExt = self.__pool.apply(initLoadExt, (DE_ext, )) # ratio between timesteps in external DE and FE domain self.__nsOfDE_ext = 1 # get interface nodal forces as boundary condition self.__FEf = self.__pool.apply( initNbc, (self.__sceneExt, self.__conf, mIds, FEDENodeMap)) """ # get interface nodal tractions as boundary condition (deprecated) self.__Nbc=escript.Vector(0,escript.Solution(self.__domain)) FENbc = self.__pool.apply(initNbc,(self.__sceneExt,self.__conf,mIds,FEDENodeMap)) for FEid in FENbc.keys(): self.__Nbc.setValueOfDataPoint(FEid,FENbc[FEid]) """ # get stress tensor at material points s = self.__pool.map(getStress2D, self.__scenes) for i in xrange(ng): self.__stress.setValueOfDataPoint(i, s[i])
def getPotential(self): """ returns a list containing 3 lists one for each the primary, secondary and total potential. """ primCon=self.primaryConductivity coords=self.domain.getX() pde=LinearPDE(self.domain, numEquations=1) tol=1e-8 pde.getSolverOptions().setTolerance(tol) pde.setSymmetryOn() DIM=self.domain.getDim() x=self.domain.getX() q=es.whereZero(x[DIM-1]-es.inf(x[DIM-1])) for i in xrange(DIM-1): xi=x[i] q+=es.whereZero(xi-es.inf(xi))+es.whereZero(xi-es.sup(xi)) A = self.secondaryConductivity * es.kronecker(self.domain) pde.setValue(A=A,q=q) delPhiSecondary = [] delPhiPrimary = [] delPhiTotal = [] if(len(self.electrodes[0])==3): for i in range(self.numElectrodes-1): analyticRs=es.Data(0,(3,),es.ContinuousFunction(self.domain)) analyticRs[0]=(coords[0]-self.electrodes[i][0]) analyticRs[1]=(coords[1]-self.electrodes[i][1]) analyticRs[2]=(coords[2]) rsMag=(analyticRs[0]**2+analyticRs[1]**2+analyticRs[2]**2)**0.5 analyticPrimaryPot=(self.current*(1./primCon))/(2*pi*(rsMag+(es.whereZero(rsMag)*0.0000001))) #the magic number 0.0000001 is to avoid devide by 0 analyticRsPolePower=(analyticRs[0]**2+analyticRs[1]**2+analyticRs[2]**2)**1.5 analyticRsPolePower = analyticRsPolePower+(es.whereZero(analyticRsPolePower)*0.0000001) gradUPrimary = es.Data(0,(3,),es.ContinuousFunction(self.domain)) gradUPrimary[0] =(self.current/(2*pi*primCon)) * (analyticRs[0]/analyticRsPolePower) gradUPrimary[1] =(self.current/(2*pi*primCon)) * (analyticRs[1]/analyticRsPolePower) gradUPrimary[2] =(self.current/(2*pi*primCon)) * (analyticRs[2]/analyticRsPolePower) gradUPrimary=-gradUPrimary X=(primCon-self.secondaryConductivity) * gradUPrimary pde.setValue(X=X) u=pde.getSolution() loc=Locator(self.domain,self.electrodes[i+1]) delPhiSecondary.append(loc.getValue(u)) delPhiPrimary.append(loc.getValue(analyticPrimaryPot)) else: raise NotImplementedError("2d forward model is not yet implemented") self.delPhiSecondary = delPhiSecondary self.delPhiPrimary = delPhiPrimary for i in range(len(delPhiPrimary)): delPhiTotal.append(delPhiPrimary[i] + delPhiSecondary[i]) self.delPhiTotal=delPhiTotal return [delPhiPrimary, delPhiSecondary, delPhiTotal]
def __init__(self, domain, phi_f=None, phi=None, L_g=None, perm_f_0=None, perm_f_1=None, perm_f_2=None, k_w =None, k_g=None, mu_w =None, mu_g =None, rho_w =None, rho_g=None, sigma=0, A_mg=0, f_rg=1., wells=[], g=9.81*U.m/U.sec**2): """ set up :param domain: domain :type domain: `esys.escript.Domain` :param phi_f: porosity of the fractured rock as function of the gas pressure :type phi_f: `MaterialPropertyWithDifferential` :param phi: total porosity if None phi=1. :type phi: scalar or None :param L_g: gas adsorption as function of gas pressure :type L_g: `MaterialPropertyWithDifferential` :param S_fg: gas saturation in the fractured rock as function of the capillary pressure p_fc=S_fg- p_f :type S_fg: `MaterialPropertyWithDifferential` :param perm_f_0: permeability in the x_0 direction in the fractured media :type perm_f_0: scalar :param perm_f_1: permeability in the x_1 direction in the fractured media :type perm_f_1: scalar :param perm_f_2: permeability in the x_2 direction in the fractured media :type perm_f_2: scalar :param k_w: relative permeability of water as function of water saturation :type k_w: `MaterialProperty` :param k_g: relative permeability of gas as function of gas saturation :type k_g: `MaterialProperty` :param mu_w: viscosity of water as function of water pressure :type mu_w: `MaterialProperty` :param mu_g: viscosity of gas as function of gas pressure :type mu_g: `MaterialProperty` :param rho_w: density of water as function of water pressure :type rho_w: `MaterialPropertyWithDifferential` :param rho_g: density of gas as function of gas pressure :type rho_g: `MaterialPropertyWithDifferential` :param wells : list of wells :type wells: list of `Well` :param sigma: shape factor for gas matrix diffusion :param A_mg: diffusion constant for gas adsorption :param f_rg: gas re-adsorption factor """ DualPorosity.__init__(self, domain, phi_f=phi_f, phi_m=None, phi=phi, S_fg=None, S_mg=None, perm_f_0=perm_f_0, perm_f_1=perm_f_1, perm_f_2=perm_f_2, perm_m_0=None , perm_m_1=None, perm_m_2=None, k_w =k_w, k_g=k_g, mu_w =mu_w, mu_g =mu_g, rho_w =rho_w, rho_g=rho_g, wells=wells, g=g) self.L_g=L_g self.sigma = sigma self.A_mg = A_mg self.f_rg = f_rg self.__pde=LinearPDE(self.domain, numEquations=3, numSolutions =3)
def __update(self, tag, tag_value, value): if self.__pde == None: self.__pde = LinearPDE(self.domain, numSolutions=1) mask = Scalar(0., Function(self.domain)) mask.setTaggedValue(tag, 1.) self.__pde.setValue(Y=mask) mask = wherePositive(abs(self.__pde.getRightHandSide())) value *= (1. - mask) value += tag_value * mask return value
def __init__(self, domain, ng=1, useMPI=False, np=1, random=False, rtol=1.e-2, verbose=False): """ initialization of the problem, i.e. model constructor :param domain: type Domain, domain of the problem :param ng: type integer, number of Gauss points :param useMPI: type boolean, use MPI or not :param np: type integer, number of processors :param random: type boolean, if or not use random density field :param rtol: type float, relevant tolerance for global convergence :param verbose: type boolean, if or not print messages during calculation """ self.__domain = domain self.__pde = LinearPDE(domain, numEquations=self.__domain.getDim(), numSolutions=self.__domain.getDim()) try: self.__pde.getSolverOptions().setSolverMethod(SolverOptions.DIRECT) except: #import time print( "=======================================================================" ) print( "For better performance compile python-escript with direct solver method" ) print( "=======================================================================" ) input("Press Enter to continue...") #time.sleep(5) self.__pde.setSymmetryOn() #self.__pde.getSolverOptions().setTolerance(rtol**2) #self.__pde.getSolverOptions().setPackage(SolverOptions.UMFPACK) self.__numGaussPoints = ng self.__rtol = rtol self.__verbose = verbose self.__pool = get_pool(mpi=useMPI, threads=np) self.__scenes = self.__pool.map(initLoad, list(range(ng))) self.__strain = escript.Tensor(0, escript.Function(self.__domain)) self.__stress = escript.Tensor(0, escript.Function(self.__domain)) self.__S = escript.Tensor4(0, escript.Function(self.__domain)) st = self.__pool.map(getStressAndTangent, self.__scenes) for i in range(ng): self.__stress.setValueOfDataPoint(i, st[i][0]) self.__S.setValueOfDataPoint(i, st[i][1])
def __init__(self, domain, ng=1, useMPI=False, np=1, random=False, rtol=1.e-2, usePert=False, pert=-2.e-6, verbose=False): """ initialization of the problem, i.e. model constructor :param domain: type Domain, domain of the problem :param ng: type integer, number of Gauss points :param useMPI: type boolean, use MPI or not :param np: type integer, number of processors :param random: type boolean, if or not use random density field :param rtol: type float, relevative tolerance for global convergence :param usePert: type boolean, if or not use perturbation method :param pert: type float, perturbated strain applied to DEM to obtain tangent operator :param verbose: type boolean, if or not print messages during calculation """ self.__domain = domain self.__pde = LinearPDE(domain, numEquations=self.__domain.getDim(), numSolutions=self.__domain.getDim()) self.__pde.getSolverOptions().setSolverMethod(SolverOptions.DIRECT) self.__pde.setSymmetryOn() #self.__pde.getSolverOptions().setTolerance(rtol**2) #self.__pde.getSolverOptions().setPackage(SolverOptions.UMFPACK) self.__numGaussPoints = ng self.__rtol = rtol self.__usepert = usePert self.__pert = pert self.__verbose = verbose self.__pool = get_pool(mpi=useMPI, threads=np) self.__scenes = self.__pool.map(initLoad, range(ng)) self.__strain = escript.Tensor(0, escript.Function(self.__domain)) self.__stress = escript.Tensor(0, escript.Function(self.__domain)) self.__S = escript.Tensor4(0, escript.Function(self.__domain)) if self.__usepert: s = self.__pool.map(getStressTensor, self.__scenes) t = self.__pool.map(getTangentOperator, zip(self.__scenes, repeat(pert))) for i in xrange(ng): self.__stress.setValueOfDataPoint(i, s[i]) self.__S.setValueOfDataPoint(i, t[i]) else: st = self.__pool.map(getStressAndTangent2D, self.__scenes) for i in xrange(ng): self.__stress.setValueOfDataPoint(i, st[i][0]) self.__S.setValueOfDataPoint(i, st[i][1])
def runTest(dom, n=1, a=0, b=0): print("================== TEST : n= %s a=%s b=%s ================" % (n, a, b)) DIM = dom.getDim() normal = dom.getNormal() mypde = LinearPDE(dom, numEquations=n, numSolutions=n) x = dom.getX() A = mypde.createCoefficient("A") D = mypde.createCoefficient("D") Y = mypde.createCoefficient("Y") y = mypde.createCoefficient("y") q = mypde.createCoefficient("q") if n == 1: u_ref = Scalar(0., Solution(dom)) for j in range(DIM): q += whereZero(x[j]) A[j, j] = 1 y += sin(sqrt(2.)) * normal[0] Y += b * x[0] * sin(sqrt(2.)) D += b u_ref = x[0] * sin(sqrt(2.)) else: u_ref = Data(0., (n, ), Solution(dom)) for i in range(n): for j in range(DIM): q[i] += whereZero(x[j]) A[i, j, i, j] = 1 if j == i % DIM: y[i] += sin(i + sqrt(2.)) * normal[j] for j in range(n): if i == j: D[i, i] = b + (n - 1) * a Y[i] += b * x[i % DIM] * sin(i + sqrt(2.)) else: D[i, j] = -a Y[i] += a * (x[i % DIM] * sin(i + sqrt(2.)) - x[j % DIM] * sin(j + sqrt(2.))) u_ref[i] = x[i % DIM] * sin(i + sqrt(2.)) # - u_{j,ii} + b*u_i+ a*sum_{k<>j} (u_i-u_k) = F_j mypde.setValue(A=A, D=D, y=y, q=q, r=u_ref, Y=Y) mypde.getSolverOptions().setVerbosityOn() mypde.getSolverOptions().setTolerance(TOL) mypde.setSymmetryOn() u = mypde.getSolution() error = Lsup(u - u_ref) / Lsup(u_ref) print("error = ", error) if error > 10 * TOL: print( "XXXXXXXXXX Error to large ! XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX")
def getMaxEigenvalue(self): """ return the max eigenvalue of the model type: float """ dom = self.getDomain() dim = dom.getDim() pdeKu_P = LinearPDE(dom, numEquations=dim, numSolutions=dim) T = self.getCurrentTangent() pdeKu_P.setValue(A=T) pdeKu_P.getOperator().saveMM('tempMTX.mtx') mtx = mmread('tempMTX.mtx') maxEigVal = max(eigs(mtx, k=1, return_eigenvectors=False, which='LR')) return maxEigVal.real
def gzpot(p, y, x, *args): #rho, rhox, rhoy, R = p rhox = args[0] / 2. rhoy = args[1] / 2. rho, R, z = p #Domain related. mx = args[0] my = args[1] #PDE related G = 6.67300 * 10E-11 #DOMAIN CONSTRUCTION domain = ReadGmsh('data/example10m/example10m.msh', 2) domx = Solution(domain).getX() mask = wherePositive(R - length(domx - rholoc)) rhoe = rho * mask kro = kronecker(domain) q = whereZero(domx[1] - my) + whereZero(domx[1]) + whereZero( domx[0]) + whereZero(domx[0] - mx) #ESCRIPT PDE CONSTRUCTION mypde = LinearPDE(domain) mypde.setValue(A=kro, Y=4. * np.pi * G * rhoe, q=q, r=0.0) mypde.setSymmetryOn() sol = mypde.getSolution() g_field = grad(sol) #The graviational accelleration g. g_fieldz = g_field * [0, 1] #The vertical component of the g field. gz = length(g_fieldz) #The magnitude of the vertical component. #MODEL SIZE SAMPLING sol_escgz = [] sol_escx = [] for i in range(0, len(x)): sol_escgz.append([x[i], rhoy + z]) sample = [] # array to hold values rec = Locator(gz.getFunctionSpace(), sol_escgz) #location to record psol = rec.getValue(gz) err = np.sum((np.array(y) - np.array(psol))**2.) print("Lsup= ", Lsup(np.array(psol) - np.array(sol_angz)) / Lsup(np.array(psol))) return err
def __init__(self,domain,ng=1,np=1,random=False,rtol=1.e-2,usePert=False,pert=-2.e-6,verbose=False): """ initialization of the problem, i.e. model constructor :param domain: type Domain, domain of the problem :param ng: type integer, number of Gauss points :param np: type integer, number of processors :param random: type boolean, if or not use random density field :param rtol: type float, relevative tolerance for global convergence :param usePert: type boolean, if or not use perturbation method :param pert: type float, perturbated strain applied to DEM to obtain tangent operator :param verbose: type boolean, if or not print messages during calculation """ self.__domain=domain self.__pde=LinearPDE(domain,numEquations=self.__domain.getDim(),numSolutions=self.__domain.getDim()) self.__pde.getSolverOptions().setSolverMethod(SolverOptions.DIRECT) #self.__pde.getSolverOptions().setTolerance(rtol**2) #self.__pde.getSolverOptions().setPackage(SolverOptions.UMFPACK) self.__numGaussPoints=ng self.__rtol=rtol self.__usepert=usePert self.__pert=pert self.__verbose=verbose self.__pool=Pool(processes=np) self.__scenes=self.__pool.map(initLoad,range(ng))#where is initLoad???from simDEM.py,to load RVEs; map(function, iterable) self.__strain=escript.Tensor(0,escript.Function(self.__domain)) '''Tensor(value=0., what=FunctionSpace(), expanded=False) returns a Data object of shape (d,d) in the FunctionSpace what, where d is the spatial dimension of the Domain of what. Values are initialized with value, a double precision quantity(here is 0). If expanded is True the Data object is represented in expanded form. ''' self.__stress=escript.Tensor(0,escript.Function(self.__domain)) #Function(domain): returns the general FunctionSpace on the Domain domain. Data objects in this type of general FunctionSpace are defined over the whole geometric region defined by domain. self.__S=escript.Tensor4(0,escript.Function(self.__domain)) #Tensor4 is similar to Tensor, which returns a Data object of shape (d,d,d,d) #simDEM part if self.__usepert: #here usepert=false, so this is not invoked. s = self.__pool.map(getStressTensor,self.__scenes) #getstresstensor is defined in simDEM, but here it is not invoked. t = self.__pool.map(getTangentOperator,zip(self.__scenes,repeat(pert)))#to get initial D and sigma for i in xrange(ng): self.__stress.setValueOfDataPoint(i,s[i]) self.__S.setValueOfDataPoint(i,t[i]) else: st = self.__pool.map(getStressAndTangent2D,self.__scenes) for i in xrange(ng): self.__stress.setValueOfDataPoint(i,st[i][0]) self.__S.setValueOfDataPoint(i,st[i][1])
def getPotential(self): """ Returns 3 list each made up of a number of list containing primary, secondary and total potentials diferences. Each of the lists contain a list for each value of n. """ primCon=self.primaryConductivity coords=self.domain.getX() pde=LinearPDE(self.domain, numEquations=1) tol=1e-8 pde.getSolverOptions().setTolerance(tol) pde.setSymmetryOn() DIM=self.domain.getDim() x=self.domain.getX() q=es.whereZero(x[DIM-1]-es.inf(x[DIM-1])) for i in xrange(DIM-1): xi=x[i] q+=es.whereZero(xi-es.inf(xi))+es.whereZero(xi-es.sup(xi)) A = self.secondaryConductivity * es.kronecker(self.domain) pde.setValue(A=A,q=q) delPhiSecondaryList = [] delPhiPrimaryList = [] delPhiTotalList = [] for i in range(1,self.n+1): # 1 to n maxR = self.numElectrodes - 1 - i #max amount of readings that will fit in the survey delPhiSecondary = [] delPhiPrimary = [] delPhiTotal = [] for j in range(maxR): analyticRs=es.Data(0,(3,),es.ContinuousFunction(self.domain)) analyticRs[0]=(coords[0]-self.electrodes[j][0]) analyticRs[1]=(coords[1]-self.electrodes[j][1]) analyticRs[2]=(coords[2]) rsMag=(analyticRs[0]**2+analyticRs[1]**2+analyticRs[2]**2)**0.5 analyticPrimaryPot=(self.current*(1./primCon))/(2*pi*(rsMag+(es.whereZero(rsMag)*0.0000001))) #the magic number 0.0000001 is to avoid devide by 0 analyticRsPolePower=(analyticRs[0]**2+analyticRs[1]**2+analyticRs[2]**2)**1.5 analyticRsPolePower = analyticRsPolePower+(es.whereZero(analyticRsPolePower)*0.0000001) gradUPrimary = es.Data(0,(3,),es.ContinuousFunction(self.domain)) gradUPrimary[0] =(self.current/(2*pi*primCon)) * (analyticRs[0]/analyticRsPolePower) gradUPrimary[1] =(self.current/(2*pi*primCon)) * (analyticRs[1]/analyticRsPolePower) gradUPrimary[2] =(self.current/(2*pi*primCon)) * (analyticRs[2]/analyticRsPolePower) gradUPrimary=-gradUPrimary X=(primCon-self.secondaryConductivity) * gradUPrimary pde.setValue(X=X) u=pde.getSolution() loc=Locator(self.domain,[self.electrodes[i+j],self.electrodes[i+j+1]]) valPrimary=loc.getValue(analyticPrimaryPot) valSecondary=loc.getValue(u) delPhiPrimary.append(valPrimary[1]-valPrimary[0]) delPhiSecondary.append(valSecondary[1]-valSecondary[0]) delPhiTotal.append(delPhiPrimary[j]+delPhiSecondary[j]) delPhiPrimaryList.append(delPhiPrimary) delPhiSecondaryList.append(delPhiSecondary) delPhiTotalList.append(delPhiTotal) self.delPhiPrimaryList=delPhiPrimaryList self.delPhiSecondaryList=delPhiSecondaryList self.delPhiTotalList = delPhiTotalList return [delPhiPrimaryList, delPhiSecondaryList, delPhiTotalList]
save_path = os.path.join("data", "example10") #ensure the dir exists mkDir(save_path) ####################################################DOMAIN CONSTRUCTION domain = Rectangle(l0=mx, l1=my, n0=ndx, n1=ndy) x = Solution(domain).getX() mask = wherePositive(10 - length(x - rholoc)) rho = rho * mask kro = kronecker(domain) q = whereZero(x[1] - my) + whereZero(x[1]) + whereZero( x[0]) + whereZero(x[0] - mx) ###############################################ESCRIPT PDE CONSTRUCTION mypde = LinearPDE(domain) mypde.setValue(A=kro, Y=4. * 3.1415 * G * rho) mypde.setValue(q=q, r=0) mypde.setSymmetryOn() sol = mypde.getSolution() g_field = grad(sol) #The gravitational acceleration g. g_fieldz = g_field * [0, 1] #The vertical component of the g field. gz = length(g_fieldz) #The magnitude of the vertical component. # Save the output to file. saveVTK(os.path.join(save_path,"ex10a.vtu"),\ grav_pot=sol,g_field=g_field,g_fieldz=g_fieldz,gz=gz) ##################################################REGRIDDING & PLOTTING xi, yi, zi = toRegGrid(sol, nx=50, ny=50)
tend = 0.5 * day # - time to end simulation outputs = 200 # number of time steps required. h = (tend - t) / outputs #size of time step #user warning statement print("Expected Number of time outputs is: ", (tend - t) / h) i = 0 #loop counter #the folder to put our outputs in, leave blank "" for script path save_path = os.path.join("data", "example02") #ensure the dir exists mkDir(save_path, os.path.join(save_path, "tempT")) ####################################################DOMAIN CONSTRUCTION rod = Rectangle(l0=mx, l1=my, n0=ndx, n1=ndy) x = Solution(rod).getX() ###############################################ESCRIPT PDE CONSTRUCTION mypde = LinearPDE(rod) A = zeros((2, 2)) A[0, 0] = kappa q = whereZero(x[0]) mypde.setValue(A=A, D=rhocp / h, q=q, r=T0) # ... set initial temperature .... T = T0 * whereZero(x[0]) + Tref * (1 - whereZero(x[0])) # ... open a collector for the time marks and corresponding total energy t_list = [] E_list = [] # ... convert solution points for plotting plx = x.toListOfTuples() plx = np.array(plx) #convert to tuple to numpy array plx = plx[:, 0] #extract x locations ########################################################START ITERATION
x = domain.getX() # get the locations of the nodes in the domain lam = Scalar(0, Function(domain)) mu = Scalar(0, Function(domain)) rho = Scalar(0, Function(domain)) #Setting parameters for each layer in the model. for i in range(0, nlayers): rho.setTaggedValue("volume_%d" % i, rhoc + i * 100.) lamc = (vel + i * 100.)**2. * (rhoc + i * 100.) / 2. muc = (vel + i * 100.)**2. * (rhoc + i * 100.) / 4. lam.setTaggedValue("volume_%d" % i, lamc) mu.setTaggedValue("volume_%d" % i, muc) ##########################################################ESTABLISH PDE mypde = LinearPDE(domain) # create pde mypde.setSymmetryOn() # turn symmetry on # turn lumping on for more efficient solving #mypde.getSolverOptions().setSolverMethod(SolverOptions.HRZ_LUMPING) kmat = kronecker( domain) # create the kronecker delta function of the domain mypde.setValue(D=rho * kmat) #set the general form value D ############################################FIRST TIME STEPS AND SOURCE # define small radius around point xc src_rad = 20 print("src radius= ", src_rad) # set initial values for first two time steps with source terms xb = FunctionOnBoundary(domain).getX() yx = (cos(length(xb - xc) * 3.1415 / src_rad) + 1) * whereNegative(length(xb - xc) - src_rad)
mydomain = Rectangle(l0=1., l1=1., n0=16, n1=16) # n1 need to be multiple of 4!!! # .. create the fault system fs = FaultSystem(dim=2) fs.addFault(V0=[0.5, 0.25], strikes=90 * DEG, ls=0.5, tag=1) # ... create a slip distribution on the fault: p, m = fs.getParametrization(mydomain.getX(), tag=1) p0, p1 = fs.getW0Range(tag=1) s = m * (p - p0) * (p1 - p) / ((p1 - p0) / 2)**2 * slip_max * [0., 1.] # ... calculate stress according to slip: D = symmetric(grad(s)) chi, d = fs.getSideAndDistance(D.getFunctionSpace().getX(), tag=1) sigma_s = (mu * D + lam * trace(D) * kronecker(mydomain)) * chi #... open symmetric PDE ... mypde = LinearPDE(mydomain) mypde.setSymmetryOn() #... set coefficients ... C = Tensor4(0., Function(mydomain)) for i in range(mydomain.getDim()): for j in range(mydomain.getDim()): C[i, i, j, j] += lam C[j, i, j, i] += mu C[j, i, i, j] += mu # ... fix displacement in normal direction x = mydomain.getX() msk=whereZero(x[0])*[1.,0.] + whereZero(x[0]-1.)*[1.,0.] \ +whereZero(x[1])*[0.,1.] + whereZero(x[1]-1.)*[0.,1.] mypde.setValue(A=C, X=-0.5 * sigma_s, q=msk) #... solve pde ... mypde.getSolverOptions().setVerbosityOn()
def wavePropagation(dom, rho, mu, lmbd, eta): x = Function(dom).getX() # ... open new PDE ... mypde = LinearPDE(dom) mypde.setSolverMethod(LinearPDE.LUMPING) k = kronecker(Function(dom)) mypde.setValue(D=k * rho) dt = (1. / 5.) * inf(dom.getSize() / sqrt((2 * mu + lmbd) / rho)) if output: print("time step size = ", dt) # ... set initial values .... n = 0 t = 0 t_write = 0. n_write = 0 # initial value of displacement at point source is constant (U0=0.01) # for first two time steps u = Vector(0., Solution(dom)) v = Vector(0., Solution(dom)) a = Vector(0., Solution(dom)) a2 = Vector(0., Solution(dom)) v = Vector(0., Solution(dom)) if not os.path.isdir(WORKDIR): os.mkdir(WORKDIR) starttime = time.clock() while t < t_end and n < n_end: if output: print(n + 1, "-th time step t ", t + dt, " max u and F: ", Lsup(u), end=' ') # prediction: u_pr = u + dt * v + (dt**2 / 2) * a + (dt**3 / 6) * a2 v_pr = v + dt * a + (dt**2 / 2) * a2 a_pr = a + dt * a2 # ... get current stress .... eps = symmetric(grad(u_pr)) stress = lmbd * trace(eps) * k + 2 * mu * eps # ... force due to event: if abs(t - tc) < 5 * tc_length: F = exp(-((t - tc) / tc_length)**2) * exp(-(length(x - xc) / src_radius)**2) * event if output: print(Lsup(F)) else: if output: print(0.) # ... get new acceleration .... mypde.setValue(X=-stress, Y=F - eta * v_pr) a = mypde.getSolution() # ... get new displacement ... da = a - a_pr u = u_pr + (dt**2 / 12.) * da v = v_pr + (5 * dt / 12.) * da a2 += da / dt # ... save current acceleration in units of gravity and displacements if output: if t >= t_write: saveVTK(os.path.join(WORKDIR, "disp.%i.vtu" % n_write), displacement=u, amplitude=length(u)) t_write += dt_write n_write += 1 t += dt n += 1 endtime = time.clock() totaltime = endtime - starttime global netotal print(">>number of elements: %s, total time: %s, per time step: %s <<" % (netotal, totaltime, totaltime / n))
def getPotentialAnalytic(self): """ Returns 3 list each made up of a number of list containing primary, secondary and total potentials diferences. Each of the lists contain a list for each value of n. """ coords=self.domain.getX() pde=LinearPDE(self.domain, numEquations=1) tol=1e-8 pde.getSolverOptions().setTolerance(tol) pde.setSymmetryOn() primCon=self.primaryConductivity DIM=self.domain.getDim() x=self.domain.getX() q=es.whereZero(x[DIM-1]-es.inf(x[DIM-1])) for i in xrange(DIM-1): xi=x[i] q+=es.whereZero(xi-es.inf(xi))+es.whereZero(xi-es.sup(xi)) A = self.secondaryConductivity * es.kronecker(self.domain) pde.setValue(A=A,q=q) delPhiSecondaryList = [] delPhiPrimaryList = [] delPhiTotalList = [] for i in range(1,self.n+1): # 1 to n maxR = self.numElectrodes - 1 - (2*i) #max amount of readings that will fit in the survey delPhiSecondary = [] delPhiPrimary = [] delPhiTotal = [] for j in range(maxR): analyticRsOne=es.Data(0,(3,),es.ContinuousFunction(self.domain)) analyticRsOne[0]=(coords[0]-self.electrodes[j][0]) analyticRsOne[1]=(coords[1]-self.electrodes[j][1]) analyticRsOne[2]=(coords[2]) rsMagOne=(analyticRsOne[0]**2+analyticRsOne[1]**2+analyticRsOne[2]**2)**0.5 analyticRsTwo=es.Data(0,(3,),es.ContinuousFunction(self.domain)) analyticRsTwo[0]=(coords[0]-self.electrodes[j + ((2*i) + 1)][0]) analyticRsTwo[1]=(coords[1]-self.electrodes[j + ((2*i) + 1)][1]) analyticRsTwo[2]=(coords[2]) rsMagTwo=(analyticRsTwo[0]**2+analyticRsTwo[1]**2+analyticRsTwo[2]**2)**0.5 self.sources.append([self.electrodeTags[j], self.electrodeTags[j + ((2*i) + 1)]]) rsMagOne+=(es.whereZero(rsMagOne)*0.0000001) rsMagTwo+=(es.whereZero(rsMagTwo)*0.0000001) analyticPrimaryPot=(self.current/(2*pi*primCon*rsMagOne))-(self.current/(2*pi*primCon*rsMagTwo)) analyticRsOnePower=(analyticRsOne[0]**2+analyticRsOne[1]**2+analyticRsOne[2]**2)**1.5 analyticRsOnePower = analyticRsOnePower+(es.whereZero(analyticRsOnePower)*0.0001) analyticRsTwoPower=(analyticRsTwo[0]**2+analyticRsTwo[1]**2+analyticRsTwo[2]**2)**1.5 analyticRsTwoPower = analyticRsTwoPower+(es.whereZero(analyticRsTwoPower)*0.0001) gradAnalyticPrimaryPot = es.Data(0,(3,),es.ContinuousFunction(self.domain)) gradAnalyticPrimaryPot[0] =(self.current/(2*pi*primCon)) * ((-analyticRsOne[0]/analyticRsOnePower) + (analyticRsTwo[0]/analyticRsTwoPower)) gradAnalyticPrimaryPot[1] =(self.current/(2*pi*primCon)) * ((-analyticRsOne[1]/analyticRsOnePower) + (analyticRsTwo[1]/analyticRsTwoPower)) gradAnalyticPrimaryPot[2] =(self.current/(2*pi*primCon)) * ((-analyticRsOne[2]/analyticRsOnePower) + (analyticRsTwo[2]/analyticRsTwoPower)) X=(primCon-self.secondaryConductivity) * (gradAnalyticPrimaryPot) pde.setValue(X=X) u=pde.getSolution() loc=Locator(self.domain,[self.electrodes[j+i],self.electrodes[j+i+1]]) self.samples.append([self.electrodeTags[j+i],self.electrodeTags[j+i+1]]) valPrimary=loc.getValue(analyticPrimaryPot) valSecondary=loc.getValue(u) delPhiPrimary.append(valPrimary[1]-valPrimary[0]) delPhiSecondary.append(valSecondary[1]-valSecondary[0]) delPhiTotal.append(delPhiPrimary[j]+delPhiSecondary[j]) delPhiPrimaryList.append(delPhiPrimary) delPhiSecondaryList.append(delPhiSecondary) delPhiTotalList.append(delPhiTotal) self.delPhiPrimaryList=delPhiPrimaryList self.delPhiSecondaryList=delPhiSecondaryList self.delPhiTotalList = delPhiTotalList return [delPhiPrimaryList, delPhiSecondaryList, delPhiTotalList]
h=(tend-t)/outputs #size of time step #user warning print("Expected Number of Output Files is: ", outputs) print("Step size is: ", h/day, "days") i=0 #loop counter #the folder to put our outputs in, leave blank "" for script path save_path= os.path.join("data","example03") mkDir(save_path) ########## note this folder path must exist to work ################### ################################################ESTABLISHING PARAMETERS #generate domain using rectangle model = Rectangle(l0=mx,l1=my,n0=ndx, n1=ndy) #extract finite points - the solution points #create the PDE mypde=LinearPDE(model) #assigns a domain to our PDE mypde.setSymmetryOn() #set the fast solver on for symmetry #establish location of boundary between two materials x=Function(model).getX() bound = length(x-ic)-r #where the boundary will be located kappa = kappai*whereNegative(bound)+kappac*(1-whereNegative(bound)) rhocp = rhocpi*whereNegative(bound)+rhocpc*(1-whereNegative(bound)) #define our PDE coeffs mypde.setValue(A=kappa*kronecker(model),D=rhocp/h) #set initial temperature (make sure we use the right sample points) x=Solution(model).getX() bound = length(x-ic)-r #where the boundary will be located T= Ti*whereNegative(bound)+Tc*(1-whereNegative(bound)) ########################################################START ITERATION while t<=tend:
def getPotential(self): """ returns a list containing 3 lists one for each the primary, secondary and total potential. """ primCon=self.primaryConductivity coords=self.domain.getX() pde=LinearPDE(self.domain, numEquations=1) tol=1e-8 pde.getSolverOptions().setTolerance(tol) pde.setSymmetryOn() DIM=self.domain.getDim() x=self.domain.getX() q=es.whereZero(x[DIM-1]-es.inf(x[DIM-1])) for i in xrange(DIM-1): xi=x[i] q+=es.whereZero(xi-es.inf(xi))+es.whereZero(xi-es.sup(xi)) A = self.secondaryConductivity * es.kronecker(self.domain) pde.setValue(A=A,q=q) delPhiSecondary = [] delPhiPrimary = [] delPhiTotal = [] if(len(self.electrodes[0])==3): for i in range(self.numElectrodes-3): analyticRsOne=es.Data(0,(3,),es.ContinuousFunction(self.domain)) analyticRsOne[0]=(coords[0]-self.electrodes[i][0]) analyticRsOne[1]=(coords[1]-self.electrodes[i][1]) analyticRsOne[2]=(coords[2]) rsMagOne=(analyticRsOne[0]**2+analyticRsOne[1]**2+analyticRsOne[2]**2)**0.5 analyticRsTwo=es.Data(0,(3,),es.ContinuousFunction(self.domain)) analyticRsTwo[0]=(coords[0]-self.electrodes[i+3][0]) analyticRsTwo[1]=(coords[1]-self.electrodes[i+3][1]) analyticRsTwo[2]=(coords[2]) rsMagTwo=(analyticRsTwo[0]**2+analyticRsTwo[1]**2+analyticRsTwo[2]**2)**0.5 rsMagOne+=(es.whereZero(rsMagOne)*0.0000001) rsMagTwo+=(es.whereZero(rsMagTwo)*0.0000001) analyticPrimaryPot=(self.current/(2*pi*primCon*rsMagOne))-(self.current/(2*pi*primCon*rsMagTwo)) analyticRsOnePower=(analyticRsOne[0]**2+analyticRsOne[1]**2+analyticRsOne[2]**2)**1.5 analyticRsOnePower = analyticRsOnePower+(es.whereZero(analyticRsOnePower)*0.0001) analyticRsTwoPower=(analyticRsTwo[0]**2+analyticRsTwo[1]**2+analyticRsTwo[2]**2)**1.5 analyticRsTwoPower = analyticRsTwoPower+(es.whereZero(analyticRsTwoPower)*0.0001) gradAnalyticPrimaryPot = es.Data(0,(3,),es.ContinuousFunction(self.domain)) gradAnalyticPrimaryPot[0] =(self.current/(2*pi*primCon)) \ * ((-analyticRsOne[0]/analyticRsOnePower) \ + (analyticRsTwo[0]/analyticRsTwoPower)) gradAnalyticPrimaryPot[1] =(self.current/(2*pi*primCon)) \ * ((-analyticRsOne[1]/analyticRsOnePower) \ + (analyticRsTwo[1]/analyticRsTwoPower)) gradAnalyticPrimaryPot[2] =(self.current/(2*pi*primCon)) \ * ((-analyticRsOne[2]/analyticRsOnePower) + (analyticRsTwo[2]/analyticRsTwoPower)) X=(primCon-self.secondaryConductivity) * (gradAnalyticPrimaryPot) pde.setValue(X=X) u=pde.getSolution() loc=Locator(self.domain,[self.electrodes[i+1],self.electrodes[i+2]]) valPrimary=loc.getValue(analyticPrimaryPot) valSecondary=loc.getValue(u) delPhiPrimary.append(valPrimary[1]-valPrimary[0]) delPhiSecondary.append(valSecondary[1]-valSecondary[0]) delPhiTotal.append(delPhiPrimary[i]+delPhiSecondary[i]) else: raise NotImplementedError("2d forward model is not yet implemented") self.delPhiSecondary = delPhiSecondary self.delPhiPrimary = delPhiPrimary self.delPhiTotal=delPhiTotal return [delPhiPrimary, delPhiSecondary, delPhiTotal]