Пример #1
0
def interpolateEscriptData(domain, data):
    """
    esys.weipa does not support the function spaces Solution and
    ReducedSolution. This function interpolates Data defined on those function
    spaces to compatible alternatives.
    """
    from esys.escript import Solution, ReducedSolution
    from esys.escript import ContinuousFunction, ReducedContinuousFunction
    from esys.escript.util import interpolate
    
    new_data={}
    for n,d in sorted(list(data.items()), key=lambda x: x[0]):
        if not d.isEmpty():
            fs=d.getFunctionSpace()
            if domain is None:
                domain=fs.getDomain()
            elif domain != fs.getDomain():
                raise ValueError("weipa: All Data must be on the same domain!")
            new_data[n]=d
            try:
                if fs == Solution(domain):
                    new_data[n]=interpolate(d, ContinuousFunction(domain))
                elif domain.getDescription().startswith("speckley"):
                    new_data[n]=interpolate(d, ContinuousFunction(domain))
                elif fs == ReducedSolution(domain):
                    new_data[n]=interpolate(d, ReducedContinuousFunction(domain))
            except RuntimeError as e:
                if str(e).startswith("FunctionSpaceException"):
                    pass
                else:
                    raise e

    return domain,new_data
Пример #2
0
def interpolateEscriptData(domain, data):
    """
    esys.weipa does not support the function spaces Solution and
    ReducedSolution. This function interpolates Data defined on those function
    spaces to compatible alternatives.
    """
    from esys.escript import Solution, ReducedSolution
    from esys.escript import ContinuousFunction, ReducedContinuousFunction
    from esys.escript.util import interpolate
    
    new_data={}
    for n,d in sorted(list(data.items()), key=lambda x: x[0]):
        if not d.isEmpty():
            fs=d.getFunctionSpace()
            if domain is None:
                domain=fs.getDomain()
            elif domain != fs.getDomain():
                raise ValueError("weipa: All Data must be on the same domain!")
            new_data[n]=d
            try:
                if fs == Solution(domain):
                    new_data[n]=interpolate(d, ContinuousFunction(domain))
                elif domain.getDescription().startswith("speckley"):
                    new_data[n]=interpolate(d, ContinuousFunction(domain))
                elif fs == ReducedSolution(domain):
                    new_data[n]=interpolate(d, ReducedContinuousFunction(domain))
            except RuntimeError as e:
                if str(e).startswith("FunctionSpaceException"):
                    pass
                else:
                    raise e

    return domain,new_data
Пример #3
0
 def solve(self, globalIter=10, solidIter=50):
     """
   solve the coupled PDE using fixed-stress split method,
   call solveSolid to get displacement
   """
     rtol = self.__rtol
     x_safe = self.__domain.getX()
     k = util.kronecker(self.__domain)
     kdr = util.inner(k, util.tensor_mult(self.__S, k)) / 4.
     n = self.getEquivalentPorosity()
     perm = self.__permeability * n**3 / (1. - n)**2 * k
     kf = self.__bulkFluid
     dt = self.__dt
     self.__ppde.setValue(A=perm,
                          D=(n / kf + 1. / kdr) / dt,
                          Y=(n / kf + 1. / kdr) / dt * self.__pgauss -
                          self.__meanStressRate / kdr)
     p_iter_old = self.__ppde.getSolution()
     p_iter_gauss = util.interpolate(p_iter_old,
                                     escript.Function(self.__domain))
     u_old, D, sig, s, scene = self.solveSolid(p_iter_gauss=p_iter_gauss,
                                               iter_max=solidIter)
     converge = False
     iterate = 0
     while (not converge) and (iterate < globalIter):
         iterate += 1
         self.__ppde.setValue(Y=n / kf / dt * self.__pgauss +
                              1. / kdr / dt * p_iter_gauss -
                              util.trace(D) / dt)
         p_iter = self.__ppde.getSolution()
         p_err = util.L2(p_iter - p_iter_old) / util.L2(p_iter)
         p_iter_old = p_iter
         p_iter_gauss = util.interpolate(p_iter,
                                         escript.Function(self.__domain))
         u, D, sig, s, scene = self.solveSolid(p_iter_gauss=p_iter_gauss,
                                               iter_max=solidIter)
         u_err = util.L2(u - u_old) / util.L2(u)
         u_old = u
         converge = (u_err <= rtol and p_err <= rtol * .1)
     self.__meanStressRate = (util.trace(sig - self.__stress) / 2. -
                              p_iter_gauss + self.__pgauss) / dt
     self.__pore = p_iter_old
     self.__pgauss = p_iter_gauss
     self.__domain.setX(x_safe + u_old)
     self.__strain += D
     self.__stress = sig
     self.__S = s
     self.__scenes = scene
     return u_old
Пример #4
0
    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
Пример #5
0
 def solve(self, globalIter=10, solidIter=50):
    """
    solve the coupled PDE using fixed-stress split method,
    call solveSolid to get displacement
    """
    rtol=self.__rtol
    x_safe=self.__domain.getX()
    k=util.kronecker(self.__domain)
    kdr=util.inner(k,util.tensor_mult(self.__S,k))/4.
    n=self.getEquivalentPorosity()
    perm=self.__permeability*n**3/(1.-n)**2*k
    kf=self.__bulkFluid
    dt=self.__dt
    self.__ppde.setValue(A=perm,D=(n/kf+1./kdr)/dt,Y=(n/kf+1./kdr)/dt*self.__pgauss-self.__meanStressRate/kdr)
    p_iter_old=self.__ppde.getSolution()
    p_iter_gauss=util.interpolate(p_iter_old,escript.Function(self.__domain))
    u_old,D,sig,s,scene=self.solveSolid(p_iter_gauss=p_iter_gauss,iter_max=solidIter)
    converge=False
    iterate=0
    while (not converge) and (iterate<globalIter):
       iterate += 1
       self.__ppde.setValue(Y=n/kf/dt*self.__pgauss+1./kdr/dt*p_iter_gauss-util.trace(D)/dt)
       p_iter=self.__ppde.getSolution()
       p_err=util.L2(p_iter-p_iter_old)/util.L2(p_iter)
       p_iter_old=p_iter
       p_iter_gauss=util.interpolate(p_iter,escript.Function(self.__domain))
       u,D,sig,s,scene=self.solveSolid(p_iter_gauss=p_iter_gauss,iter_max=solidIter)
       u_err=util.L2(u-u_old)/util.L2(u)
       u_old=u
       converge=(u_err<=rtol and p_err <= rtol*.1)
    self.__meanStressRate=(util.trace(sig-self.__stress)/2.-p_iter_gauss+self.__pgauss)/dt
    self.__pore=p_iter_old
    self.__pgauss=p_iter_gauss
    self.__domain.setX(x_safe+u_old)
    self.__strain+=D
    self.__stress=sig
    self.__S=s
    self.__scenes=scene
    return u_old
Пример #6
0
 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()
    try:
          self.__upde.getSolverOptions().setSolverMethod(SolverOptions.DIRECT)
          self.__ppde.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.__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,list(range(ng)))
    st = self.__pool.map(getStressAndTangent2D,self.__scenes)
    for i in range(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
Пример #7
0
def saveVoxet(filename, **data):
    """
    Writes `Data` objects to a file using the GOCAD Voxet file format as
    separate properties on the same grid.
    At the moment only Data on a `ripley` domain can be saved in this format.
    Note that this function will produce one header file (ending in .vo) and
    a separate property file for each `Data` object.

    :param filename: name of the output file ('.vo' is added if required)
    :type filename: ``str``
    :note: All data objects have to be defined on the same ripley domain and
           either defined on reduced Function or on a `FunctionSpace` that
           allows interpolation to reduced Function.
    """

    from esys.escript import ReducedFunction
    from esys.escript.util import interpolate
    from esys.ripley.ripleycpp import DATATYPE_FLOAT32, BYTEORDER_BIG_ENDIAN

    new_data={}
    domain=None
    for n,d in sorted(data.items(), key=lambda x: x[0]):
        if d.isEmpty():
            continue
        fs=d.getFunctionSpace()
        if domain is None:
            domain=fs.getDomain()
        elif domain != fs.getDomain():
            raise ValueError("saveVoxet: All Data must be on the same domain!")

        try:
            nd=interpolate(d, ReducedFunction(domain))
        except:
            raise ValueError("saveVoxet: Unable to interpolate all Data to reduced Function!")
        new_data[n]=nd

    if filename[-3:]=='.vo':
        fileprefix=filename[:-3]+"_"
    else:
        fileprefix=filename+"_"
        filename=filename+'.vo'

    origin, spacing, NE = domain.getGridParameters()

    # Voxet "origin" actually refers to centre of first cell so shift:
    origin = tuple([ origin[i] + spacing[i]/2. for i in range(len(origin)) ])

    # flip vertical origin
    origin=origin[:-1]+(-origin[-1],)
    axis_max=NE[:-1]+(-NE[-1],)
    midpoint=tuple([n/2 for n in NE])

    if domain.getDim() == 2:
        origin=origin+(0.,)
        spacing=spacing+(1.,)
        NE=NE+(1,)
        midpoint=midpoint+(0,)
        axis_max=axis_max+(0,)

    mainvar=list(new_data.keys())[0]
    f=open(filename,'w')
    f.write("GOCAD Voxet 1\nHEADER {\nname: escriptdata\n")
    f.write("sections: 3 1 1 %d 2 1 %d 3 1 %d\n"%midpoint)
    f.write("painted: on\nascii: off\n*painted*variable: %s\n}"%mainvar)
    f.write("""
GOCAD_ORIGINAL_COORDINATE_SYSTEM
NAME "gocad Local"
AXIS_NAME X Y Z
AXIS_UNIT m m m
ZPOSITIVE Depth
END_ORIGINAL_COORDINATE_SYSTEM\n""")

    f.write("AXIS_O %0.2f %0.2f %0.2f\n"%origin)
    f.write("AXIS_U %0.2f 0 0\n"%spacing[0])
    f.write("AXIS_V 0 %0.2f 0\n"%spacing[1])
    f.write("AXIS_W 0 0 %0.2f\n"%spacing[2])
    f.write("AXIS_MIN 0 0 0\n")
    f.write("AXIS_MAX %d %d %d\n"%axis_max)
    f.write("AXIS_N %d %d %d\n"%NE)
    f.write("\n")

    num=0
    for n,d in sorted(new_data.items(), key=lambda x: x[0]):
        num=num+1
        propfile=fileprefix+n
        domain.writeBinaryGrid(d, propfile, BYTEORDER_BIG_ENDIAN, DATATYPE_FLOAT32)
        f.write("\nPROPERTY %d %s\n"%(num, n))
        f.write("PROPERTY_SUBCLASS %d QUANTITY Float\n"%num)
        f.write("PROP_ESIZE %d 4\n"%num)
        f.write("PROP_ETYPE %d IEEE\n"%num)
        f.write("PROP_FORMAT %d RAW\n"%num)
        f.write("PROP_OFFSET %d 0\n"%num)
        f.write("PROP_FILE %d %s\n"%(num,propfile))
    f.close()
Пример #8
0
def saveVoxet(filename, **data):
    """
    Writes `Data` objects to a file using the GOCAD Voxet file format as
    separate properties on the same grid.
    At the moment only Data on a `ripley` domain can be saved in this format.
    Note that this function will produce one header file (ending in .vo) and
    a separate property file for each `Data` object.

    :param filename: name of the output file ('.vo' is added if required)
    :type filename: ``str``
    :note: All data objects have to be defined on the same ripley domain and
           either defined on reduced Function or on a `FunctionSpace` that
           allows interpolation to reduced Function.
    """

    from esys.escript import ReducedFunction
    from esys.escript.util import interpolate
    from esys.ripley.ripleycpp import DATATYPE_FLOAT32, BYTEORDER_BIG_ENDIAN

    new_data={}
    domain=None
    for n,d in sorted(data.items(), key=lambda x: x[0]):
        if d.isEmpty():
            continue
        fs=d.getFunctionSpace()
        if domain is None:
            domain=fs.getDomain()
        elif domain != fs.getDomain():
            raise ValueError("saveVoxet: All Data must be on the same domain!")

        try:
            nd=interpolate(d, ReducedFunction(domain))
        except:
            raise ValueError("saveVoxet: Unable to interpolate all Data to reduced Function!")
        new_data[n]=nd

    if filename[-3:]=='.vo':
        fileprefix=filename[:-3]+"_"
    else:
        fileprefix=filename+"_"
        filename=filename+'.vo'

    origin, spacing, NE = domain.getGridParameters()

    # Voxet "origin" actually refers to centre of first cell so shift:
    origin = tuple([ origin[i] + spacing[i]/2. for i in range(len(origin)) ])

    # flip vertical origin
    origin=origin[:-1]+(-origin[-1],)
    axis_max=NE[:-1]+(-NE[-1],)
    midpoint=tuple([n/2 for n in NE])

    if domain.getDim() == 2:
        origin=origin+(0.,)
        spacing=spacing+(1.,)
        NE=NE+(1,)
        midpoint=midpoint+(0,)
        axis_max=axis_max+(0,)

    mainvar=list(new_data.keys())[0]
    f=open(filename,'w')
    f.write("GOCAD Voxet 1\nHEADER {\nname: escriptdata\n")
    f.write("sections: 3 1 1 %d 2 1 %d 3 1 %d\n"%midpoint)
    f.write("painted: on\nascii: off\n*painted*variable: %s\n}"%mainvar)
    f.write("""
GOCAD_ORIGINAL_COORDINATE_SYSTEM
NAME "gocad Local"
AXIS_NAME X Y Z
AXIS_UNIT m m m
ZPOSITIVE Depth
END_ORIGINAL_COORDINATE_SYSTEM\n""")

    f.write("AXIS_O %0.2f %0.2f %0.2f\n"%origin)
    f.write("AXIS_U %0.2f 0 0\n"%spacing[0])
    f.write("AXIS_V 0 %0.2f 0\n"%spacing[1])
    f.write("AXIS_W 0 0 %0.2f\n"%spacing[2])
    f.write("AXIS_MIN 0 0 0\n")
    f.write("AXIS_MAX %d %d %d\n"%axis_max)
    f.write("AXIS_N %d %d %d\n"%NE)
    f.write("\n")

    num=0
    for n,d in sorted(new_data.items(), key=lambda x: x[0]):
        num=num+1
        propfile=fileprefix+n
        domain.writeBinaryGrid(d, propfile, BYTEORDER_BIG_ENDIAN, DATATYPE_FLOAT32)
        f.write("\nPROPERTY %d %s\n"%(num, n))
        f.write("PROPERTY_SUBCLASS %d QUANTITY Float\n"%num)
        f.write("PROP_ESIZE %d 4\n"%num)
        f.write("PROP_ETYPE %d IEEE\n"%num)
        f.write("PROP_FORMAT %d RAW\n"%num)
        f.write("PROP_OFFSET %d 0\n"%num)
        f.write("PROP_FILE %d %s\n"%(num,propfile))
    f.close()