def __init__(self, domain, v_p, wavelet, source_tag, dt=None, p0=None, p0_t=None, absorption_zone=300 * U.m, absorption_cut=1e-2, lumping=True): """ initialize the sonic wave solver :param domain: domain of the problem :type domain: `Domain` :param v_p: p-velocity field :type v_p: `escript.Scalar` :param wavelet: wavelet to describe the time evolution of source term :type wavelet: `Wavelet` :param source_tag: tag of the source location :type source_tag: 'str' or 'int' :param dt: time step size. If not present a suitable time step size is calculated. :param p0: initial solution. If not present zero is used. :param p0_t: initial solution change rate. If not present zero is used. :param absorption_zone: thickness of absorption zone :param absorption_cut: boundary value of absorption decay factor :param lumping: if True mass matrix lumping is being used. This is accelerates the computing but introduces some diffusion. """ f = createAbsorptionLayerFunction( escript.Function(domain).getX(), absorption_zone, absorption_cut) v_p = v_p * f if p0 == None: p0 = escript.Scalar(0., escript.Solution(domain)) else: p0 = escript.interpolate(p0, escript.Solution(domain)) if p0_t == None: p0_t = escript.Scalar(0., escript.Solution(domain)) else: p0_t = escript.interpolate(p0_t, escript.Solution(domain)) if dt == None: dt = min(escript.inf((1. / 5.) * domain.getSize() / v_p), wavelet.getTimeScale()) super(SonicWave, self).__init__(dt, u0=p0, v0=p0_t, t0=0.) self.__wavelet = wavelet self.__mypde = lpde.LinearSinglePDE(domain) if lumping: self.__mypde.getSolverOptions().setSolverMethod( lpde.SolverOptions.HRZ_LUMPING) self.__mypde.setSymmetryOn() self.__mypde.setValue(D=1. / v_p**2) self.__source_tag = source_tag self.__r = escript.Scalar( 0., escript.DiracDeltaFunctions(self.__mypde.getDomain()))
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 __tagDomain(self, domain, X, tags, rho, maps): """ DESCRIPTION: ----------- Defines the conductivity model. Conductivities of tagged regions can be mapped via user-defined functions passed in 'maps'. If no user-defined functions are passed, a constant value is applied as provided in list 'rho' for each region. User-defined functions have 3 arguments: x-coordinate, z-coordinate, resistivity. ARGUMENTS: ---------- domain :: escript object of mesh X :: escript object with all coordinates tags :: list with domain tags rho :: list with domain resistivities maps :: list with user-defined resistivity mappings RETURNS: -------- sigma :: escript object of conductivity model """ # Setup the conductivity structure (acts on elements and can be discontinuous). sigma = escript.Scalar(0, escript.Function(domain)) # Setup conductivity domains. for i in range(len(tags)): # Default: assign conductivity which is the inverse of resistivity: m = 1.0 / rho[i] # Map a user-defined conductivity distribution if given: if maps is not None: # Guard against undefined elements: if maps[i] is not None: # Map the conductivity according to the defined functions: m = maps[i](X[0], X[1], rho[i]) # Tag the mesh with the conductivity distributions at each iteration: sigma += m * escript.insertTaggedValues( escript.Scalar(0, escript.Function(domain)), **{tags[i]: 1}) if self._debug == True: sigma.expand() mydir = os.getcwd() dbgfl = mydir + os.sep + "mt2d_sigma_dbg.silo" print("") print("DEBUG: writing SILO debug output of conductivity model:") print(dbgfl) print("") weipa.saveSilo(dbgfl, sigma=sigma) # All done: return sigma
def test_replaceNaNTagged(self): dom=self.domain sigma = es.Scalar(0,es.FunctionOnBoundary(dom)) dat=(sigma*0)/0 sigma.setTaggedValue(1 , es.Lsup(dat)) sigma.replaceNaN(10) self.assertEqual(es.Lsup(sigma), 10) sigma = es.Scalar(0,es.FunctionOnBoundary(dom)) sigma.promote() dat=(sigma*0)/0 sigma.setTaggedValue(1 , es.Lsup(dat)) sigma.replaceNaN(3+4j) self.assertEqual(es.Lsup(sigma), 5)
def test_replaceNaNExpanded(self): dom=self.domain scl=es.Scalar(0,es.ContinuousFunction(dom)) scl.expand() sclNaN=scl/0 self.assertTrue(sclNaN.hasNaN(),"sclNaN should contain NaN but its doesn't") sclNaN.replaceNaN(15.0) self.assertEqual(es.Lsup(sclNaN), 15.0) scl=es.Scalar(0,es.ContinuousFunction(dom)) scl.expand() scl.promote() if not es.getEscriptParamInt('AUTOLAZY')==1: sclNaN=scl/0 self.assertTrue(sclNaN.hasNaN(),"sclNaN should contain NaN but its doesn't") sclNaN.replaceNaN(3+4j) self.assertEqual(es.Lsup(sclNaN), 5.0)
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 test_replaceInfExpanded(self): dom=self.domain scl=es.Scalar(1,es.ContinuousFunction(dom)) scl.expand() sclNaN=scl/0 self.assertTrue(sclNaN.hasInf(),"sclNaN should contain Inf but its doesn't") sclNaN.replaceNaN(17.0) # Make sure it is distinguishing between NaN and Inf sclNaN.replaceInf(15.0) self.assertEqual(es.Lsup(sclNaN), 15.0) scl=es.Scalar(10,es.ContinuousFunction(dom)) scl.expand() scl.promote() if not es.getEscriptParamInt('AUTOLAZY')==1: sclNaN=scl/0 self.assertTrue(sclNaN.hasInf(),"sclNaN should contain Inf but its doesn't") sclNaN.replaceInf(3+4j) sclNaN.replaceNaN(3+19j) # Make sure it is distinguishing between NaN and Inf self.assertEqual(es.Lsup(sclNaN), 5.0)
def __setOutput(self): x = self.domain.getX() self.__location_of_constraint = es.Scalar(0, x.getFunctionSpace()) if self.domain.getDim() == 3: vertex = [es.inf(x[0]), es.inf(x[1]), es.inf(x[2])] else: vertex = [es.inf(x[0]), es.inf(x[1])] self.__location_of_constraint = es.whereZero(es.length(x - vertex), self.tol) if not self.value is None: self.__value_of_constraint = self.__location_of_constraint * self.value
def getGradientAtPoint(self): """ returns the gradient of the cost function J with respect to m. :note: This implementation returns Y_k=dPsi/dm_k and X_kj=dPsi/dm_kj """ # Using cached values m = self.__pre_input grad_m = self.__pre_args mu = self.__mu mu_c = self.__mu_c DIM = self.getDomain().getDim() numLS = self.getNumLevelSets() grad_m = escript.grad(m, escript.Function(m.getDomain())) if self.__w0 is not None: Y = m * self.__w0 * mu else: if numLS == 1: Y = escript.Scalar(0, grad_m.getFunctionSpace()) else: Y = escript.Data(0, (numLS, ), grad_m.getFunctionSpace()) if self.__w1 is not None: if numLS == 1: X = grad_m * self.__w1 * mu else: X = grad_m * self.__w1 for k in range(numLS): X[k, :] *= mu[k] else: X = escript.Data(0, grad_m.getShape(), grad_m.getFunctionSpace()) # cross gradient terms: if numLS > 1: for k in range(numLS): grad_m_k = grad_m[k, :] l2_grad_m_k = escript.length(grad_m_k)**2 for l in range(k): grad_m_l = grad_m[l, :] l2_grad_m_l = escript.length(grad_m_l)**2 grad_m_lk = inner(grad_m_l, grad_m_k) f = mu_c[l, k] * self.__wc[l, k] X[l, :] += f * (l2_grad_m_k * grad_m_l - grad_m_lk * grad_m_k) X[k, :] += f * (l2_grad_m_l * grad_m_k - grad_m_lk * grad_m_l) return pdetools.ArithmeticTuple(Y, X)
def __init__(self, domain, reference=CartesianReferenceSystem()): """ set up the orthogonal coordinate transformation. :param domain: domain in the domain of the coordinate transformation :type domain: `esys.escript.AbstractDomain` :param reference: the reference system :type reference: `ReferenceSystem` """ self.__domain = domain self.__reference_system = reference self._volumefactor = esc.Scalar(1., esc.Function(domain)) self._scaling_factors = esc.Vector(1., esc.Function(domain))
def __setOutput(self): x = self.domain.getX() self.__location_of_constraint = es.Scalar(0, x.getFunctionSpace()) if self.domain.getDim() == 3: x0, x1, x2 = x[0], x[1], x[2] d = max( es.sup(x0) - es.inf(x0), sup(x1) - es.inf(x1), sup(x2) - es.inf(x2)) if self.left: self.__location_of_constraint += es.whereZero( x0 - es.inf(x0), self.tol * d) if self.right: self.__location_of_constraint += es.whereZero( x0 - es.sup(x0), self.tol * d) if self.front: self.__location_of_constraint += es.whereZero( x1 - es.inf(x1), self.tol * d) if self.back: self.__location_of_constraint += es.whereZero( x1 - es.sup(x1), self.tol * d) if self.bottom: self.__location_of_constraint += es.whereZero( x2 - es.inf(x2), self.tol * d) if self.top: self.__location_of_constraint += es.whereZero( x2 - es.sup(x2), self.tol * d) else: x0, x1 = x[0], x[1] d = max(es.sup(x0) - es.inf(x0), es.sup(x1) - es.inf(x1)) if self.left: self.__location_of_constraint += es.whereZero( x0 - es.inf(x0), self.tol * d) if self.right: self.__location_of_constraint += es.whereZero( x0 - es.sup(x0), self.tol * d) if self.bottom: self.__location_of_constraint += es.whereZero( x1 - es.inf(x1), self.tol * d) if self.top: self.__location_of_constraint += es.whereZero( x1 - es.sup(x1), self.tol * d) if not self.value is None: self.__value_of_constraint = self.__location_of_constraint * self.value
def getLocalAvgRotation(self): rot=escript.Scalar(0,escript.Function(self.__domain)) r = self.__pool.map(avgRotation2D,self.__scenes) for i in range(self.__numGaussPoints): rot.setValueOfDataPoint(i,r[i]) return rot
def getEquivalentPorosity(self): porosity=escript.Scalar(0,escript.Function(self.__domain)) p = self.__pool.map(getEquivalentPorosity,self.__scenes) for i in range(self.__numGaussPoints): porosity.setValueOfDataPoint(i,p[i]) return porosity
def __init__(self, domain, omega, x, Z, eta=None, w0=1., mu=4 * math.pi * 1e-7, sigma0=0.01, airLayerLevel=None, fixAirLayer=False, coordinates=None, tol=1e-8, saveMemory=False, directSolver=True): """ initializes a new forward model. :param domain: domain of the model :type domain: `Domain` :param omega: frequency :type omega: positive ``float`` :param x: coordinates of measurements :type x: ``list`` of ``tuple`` with ``float`` :param Z: measured impedance (possibly scaled) :type Z: ``list`` of ``complex`` :param eta: spatial confidence radius :type eta: positive ``float`` or ``list`` of positive ``float`` :param w0: confidence factors for meassurements. :type w0: ``None`` or a list of positive ``float`` :param mu: permeability :type mu: ``float`` :param sigma0: background conductivity :type sigma0: ``float`` :param airLayerLevel: position of the air layer from to bottom of the domain. If not set the air layer starts at the top of the domain :type airLayerLevel: ``float`` or ``None`` :param fixAirLayer: fix air layer (TM mode) :type fixAirLayer: ``bool`` :param coordinates: defines coordinate system to be used (not supported yet) :type coordinates: `ReferenceSystem` or `SpatialCoordinateTransformation` :param tol: tolerance of underlying PDE :type tol: positive ``float`` :param saveMemory: if true stiffness matrix is deleted after solution of the PDE to minimize memory use. This will require more compute time as the matrix needs to be reallocated at each iteration. :type saveMemory: ``bool`` :param directSolver: if true a direct solver (rather than an iterative solver) will be used to solve the PDE :type directSolver: ``bool`` """ super(MT2DBase, self).__init__() self.__trafo = coords.makeTransformation(domain, coordinates) if not self.getCoordinateTransformation().isCartesian(): raise ValueError( "Non-Cartesian coordinates are not supported yet.") if len(x) != len(Z): raise ValueError( "Number of data points and number of impedance values don't match." ) if eta is None: eta = escript.sup(domain.getSize()) * 0.45 if isinstance(eta, float) or isinstance(eta, int): eta = [float(eta)] * len(Z) elif not len(eta) == len(Z): raise ValueError( "Number of confidence radii and number of impedance values don't match." ) if isinstance(w0, float) or isinstance(w0, int): w0 = [float(w0)] * len(Z) elif not len(w0) == len(Z): raise ValueError( "Number of confidence factors and number of impedance values don't match." ) self.__domain = domain self._omega_mu = omega * mu self._ks = escript.sqrt(self._omega_mu * sigma0 / 2.) xx = escript.Function(domain).getX() totalS = 0 self._Z = [ escript.Scalar(0., escript.Function(domain)), escript.Scalar(0., escript.Function(domain)) ] self._weight = escript.Scalar(0., escript.Function(domain)) for s in range(len(Z)): chi = self.getWeightingFactor(xx, 1., x[s], eta[s]) f = escript.integrate(chi) if f < eta[s]**2 * 0.01: raise ValueError( "Zero weight (almost) for data point %s. Change eta or refine mesh." % (s, )) w02 = w0[s] / f totalS += w02 self._Z[0] += chi * Z[s].real self._Z[1] += chi * Z[s].imag self._weight += chi * w02 / (abs(Z[s])**2) if not totalS > 0: raise ValueError( "Scaling of weight factors failed as sum is zero.") DIM = domain.getDim() z = domain.getX()[DIM - 1] self._ztop = escript.sup(z) self._zbottom = escript.inf(z) if airLayerLevel is None: airLayerLevel = self._ztop self._airLayerLevel = airLayerLevel # botton: mask0 = escript.whereZero(z - self._zbottom) r = mask0 * [ escript.exp(self._ks * (self._zbottom - airLayerLevel)) * escript.cos(self._ks * (self._zbottom - airLayerLevel)), escript.exp(self._ks * (self._zbottom - airLayerLevel)) * escript.sin(self._ks * (self._zbottom - airLayerLevel)) ] #top: if fixAirLayer: mask1 = escript.whereNonNegative(z - airLayerLevel) r += mask1 * [1, 0] else: mask1 = escript.whereZero(z - self._ztop) r += mask1 * [ self._ks * (self._ztop - airLayerLevel) + 1, self._ks * (self._ztop - airLayerLevel) ] self._q = (mask0 + mask1) * [1, 1] self._r = r #==================================== self.__tol = tol self._directSolver = directSolver self._saveMemory = saveMemory self.__pde = None if not saveMemory: self.__pde = self.setUpPDE()
def getLocalDebondNum(self): num=escript.Scalar(0,escript.Function(self.__domain)) n = self.__pool.map(DebondNum,self.__scenes) for i in xrange(self.__numGaussPoints): num.setValueOfDataPoint(i,n[i]) return num
def getLocalVoidRatio(self): void = escript.Scalar(0, escript.Function(self.__domain)) e = self.__pool.map(getVoidRatio, self.__scenes) for i in xrange(self.__numGaussPoints): void.setValueOfDataPoint(i, e[i]) return void
domain = finley.ReadGmsh(mesh_file, 3) mesh_tags = escript.getTagNames(domain) directionVector = [1, 0] # ------------------------------------------------------------------------------------------------- # Define the primary and secondary resistivity model. # ------------------------------------------------------------------------------------------------- #<Note>: the mesh was created with domains, which were all 'tagged' with unique id-s; # based on the tagged domain id-s, the conductivity values are assigned to the domains. #<Note>: the primary conductivity is the conductivity in the vicinity of the electrodes; # the secondary conductivity is defined as the difference between primary and the # actual input conductivity. # Setup primary and secondary conductivity objects: sig_p = escript.Scalar(0, escript.ContinuousFunction(domain)) sig_s = escript.Scalar(0, escript.ContinuousFunction(domain)) # Cycle tag_values dictionary and assign conductivity values; # this is done for both, primary and secondary, potentials as # both dictionaries are setup with identical dictionary-keys: for tag in tag_p: # All initially defined tags must be in the tag list. # Print an error if it doesn't and exit the program. if tag in mesh_tags: # Assign value: sig_p.setTaggedValue(tag, tag_p[tag]) sig_s.setTaggedValue(tag, tag_s[tag]) else: print("Error: the defined tag is not defined in the mesh: " & tag) sys.exit()