def permeabiltyEngelhardtPitter(poro, q=3.5, s=5e-3, mesh=None, meshI=None): r""" For sand and sandstones .. math:: k & = 2\cdot 10^7 \frac{\phi^2}{(1-\phi)^2}* \frac{1}{S^2} \\ S & = q\cdot s \\ s & = \sum_{i=1}(\frac{P_i}{r_i}) * :math:`\phi` - poro 0.0 --1.0 * :math:`S` - in cm^-1 specific surface in cm^2/cm^3 * :math:`q` - (3 for spheres, > 3 shape differ from sphere) 3.5 sand * :math:`s` - in cm^-1 (s = 1/r for particles with homogeneous radii r) * :math:`P_i` - Particle ration with radii :math:`r_i` on 1cm^3 Sample Returns ------- k : in Darcy """ poro = parseArgToArray(poro, mesh.cellCount(), mesh) q = parseArgToArray(q, mesh.cellCount(), mesh) s = parseArgToArray(s, mesh.cellCount(), mesh) S = q * s k = 2e7 * (poro**2 / (1.0-poro)**2) * 1.0/S**2 * physics.constants.Darcy if meshI: k = pg.interpolate(mesh, k, meshI.cellCenters()) k = pg.solver.fillEmptyToCellArray(meshI, k) return k
def density(poro, densMatrix=2510, densFluid=1000, satur=1, mesh=None): r""" densMatrix, densFluid in kg/m^3 """ poro = parseArgToArray(poro, mesh.cellCount(), mesh) densMatrix = parseArgToArray(densMatrix, mesh.cellCount(), mesh) densFluid = parseArgToArray(densFluid, mesh.cellCount(), mesh) satur = parseArgToArray(satur, mesh.cellCount(), mesh) dens = np.array(densMatrix * (1. - poro)) + densFluid * poro * satur return dens
def hydraulicConductivity(perm, visc=1.0, dens=1.0, mesh=None, meshI=None): perm = parseArgToArray(perm, mesh.cellCount(), mesh) visc = parseArgToArray(visc, mesh.cellCount(), mesh) dens = parseArgToArray(dens, mesh.cellCount(), mesh) k = perm * dens / visc * pg.physics.constants.g if meshI: k = pg.interpolate(mesh, k, meshI.cellCenters()) k = pg.solver.fillEmptyToCellArray(meshI, k) return k
def density(poro, densMatrix=2510, densFluid=1000, satur=1, mesh=None): r""" densMatrix, densFluid in kg/m^3 """ poro = parseArgToArray(poro, mesh.cellCount(), mesh) densMatrix = parseArgToArray(densMatrix, mesh.cellCount(), mesh) densFluid = parseArgToArray(densFluid, mesh.cellCount(), mesh) satur = parseArgToArray(satur, mesh.cellCount(), mesh) dens = np.array(densMatrix * (1.-poro)) + densFluid * poro * satur return dens
def hydraulicConductivity(perm, visc=1.0, dens=1.0, mesh=None, meshI=None): perm = parseArgToArray(perm, mesh.cellCount(), mesh) visc = parseArgToArray(visc, mesh.cellCount(), mesh) dens = parseArgToArray(dens, mesh.cellCount(), mesh) k = perm * dens/visc * pg.physics.constants.g if meshI: k = pg.interpolate(mesh, k, meshI.cellCenters()) k = pg.solver.fillEmptyToCellArray(meshI, k) return k
def velocityVp(porosity, vMatrix=5000, vFluid=1442, S=1, mesh=None): r"""Compute velocity from porosity.""" porosity = parseArgToArray(porosity, mesh.cellCount(), mesh) vMatrix = parseArgToArray(vMatrix, mesh.cellCount(), mesh) vFluid = parseArgToArray(vFluid, mesh.cellCount(), mesh) S = parseArgToArray(S, mesh.cellCount(), mesh) vAir = 343.0 # better use petrophysics module vel = 1. / (np.array( (1. - porosity) / vMatrix) + porosity * S / vFluid + porosity * (1. - S) / vAir) return vel
def velocityVp(porosity, vMatrix=5000, vFluid=1442, S=1, mesh=None): r""" """ porosity = parseArgToArray(porosity, mesh.cellCount(), mesh) vMatrix = parseArgToArray(vMatrix, mesh.cellCount(), mesh) vFluid = parseArgToArray(vFluid, mesh.cellCount(), mesh) S = parseArgToArray(S, mesh.cellCount(), mesh) vAir = 343.0 vel = 1./(np.array((1.-porosity)/vMatrix) + \ porosity * S / vFluid + \ porosity * (1.-S)/vAir) return vel
def velocityVp(porosity, vMatrix=5000, vFluid=1442, S=1, mesh=None): r"""Compute velocity from porosity.""" porosity = parseArgToArray(porosity, mesh.cellCount(), mesh) vMatrix = parseArgToArray(vMatrix, mesh.cellCount(), mesh) vFluid = parseArgToArray(vFluid, mesh.cellCount(), mesh) S = parseArgToArray(S, mesh.cellCount(), mesh) vAir = 343.0 # better use petrophysics module vel = 1./(np.array((1.-porosity)/vMatrix) + porosity * S / vFluid + porosity * (1.-S)/vAir) return vel
def resistivityArchie(rBrine, porosity, a=1.0, m=2.0, S=1.0, n=2.0, mesh=None, meshI=None): """ .. math:: \rho = a\rho_{\text{Brine}}\phi^{-m}\S_w^{-n} * :math:`\rho` - the electrical conductivity of the fluid saturated rock * :math:`\rho_{\text{Brine}}` - electrical conductivity of the brine * :math:`\phi` - porosity 0.0 --1.0 * :math:`a` - tortuosity factor. (common 1) * :math:`m` - cementation exponent of the rock (usually in the range 1.3 -- 2.5 for sandstones) * :math:`n` - is the saturation exponent (usually close to 2) """ rB = None if rBrine.ndim == 1: rB = pg.RMatrix(1, len(rBrine)) rB[0] = parseArgToArray(rBrine, mesh.cellCount(), mesh) elif rBrine.ndim == 2: rB = pg.RMatrix(len(rBrine), len(rBrine[0])) for i in range(len(rBrine)): rB[i] = rBrine[i] porosity = parseArgToArray(porosity, mesh.cellCount(), mesh) a = parseArgToArray(a, mesh.cellCount(), mesh) m = parseArgToArray(m, mesh.cellCount(), mesh) S = parseArgToArray(S, mesh.cellCount(), mesh) n = parseArgToArray(n, mesh.cellCount(), mesh) r = pg.RMatrix(len(rBrine), len(rBrine[0])) for i in range(len(r)): r[i] = rB[i] * a * porosity**(-m) * S**(-n) rI = pg.RMatrix(len(r), meshI.cellCount()) if meshI: pg.interpolate(mesh, r, meshI.cellCenters(), rI) for i in range(len(rI)): rI[i] = pg.solver.fillEmptyToCellArray(meshI, rI[i]) return rI
def solveFiniteVolume(mesh, a=1.0, f=0.0, fn=0.0, vel=0.0, u0=None, times=None, uL=None, relax=1.0, ws=None, scheme='CDS', **kwargs): """ """ # The Workspace is to hold temporary data or preserve matrix rebuild swatch = pg.core.Stopwatch(True) sparse = True workspace = WorkSpace() if ws: workspace = ws a = solver.parseArgToArray(a, [mesh.cellCount(), mesh.boundaryCount()]) f = solver.parseArgToArray(f, mesh.cellCount()) fn = solver.parseArgToArray(fn, mesh.cellCount()) boundsDirichlet = None boundsNeumann = None if not hasattr(workspace, 'S'): if 'uBoundary' in kwargs: boundsDirichlet = pg.solver.parseArgToBoundaries( kwargs['uBoundary'], mesh) if 'duBoundary' in kwargs: boundsNeumann = pg.solver.parseArgToBoundaries( kwargs['duBoundary'], mesh) workspace.S, workspace.rhsBCScales = diffusionConvectionKernel( mesh=mesh, a=a, f=f, uBoundaries=boundsDirichlet, duBoundaries=boundsNeumann, u0=u0, fn=fn, vel=vel, scheme=scheme, sparse=sparse, userData=kwargs.pop('userData', None)) print('FVM kernel 1:', swatch.duration(True)) dof = len(workspace.rhsBCScales) # workspace.uDir = np.zeros(dof) # if u0 is not None: # workspace.uDir = np.array(u0) # # if len(boundsDirichlet): # for boundary, val in boundsDirichlet.items(): # workspace.uDir[boundary.leftCell().id()] = val workspace.ap = np.zeros(dof) # for nonlinears if uL is not None: for i in range(dof): val = 0.0 if sparse: val = workspace.S.getVal(i, i) / relax workspace.S.setVal(i, i, val) # workspace.S[i, i] /= relax # workspace.ap[i] = workspace.S[i, i] else: val = workspace.S[i, i] / relax workspace.S[i, i] = val workspace.ap[i] = val print('FVM kernel 2:', swatch.duration(True)) # endif: not hasattr(workspace, 'S'): workspace.rhs = np.zeros(len(workspace.rhsBCScales)) workspace.rhs[0:mesh.cellCount()] = f # * mesh.cellSizes() # if len(workspace.uDir): workspace.rhs += workspace.rhsBCScales # for nonlinear: relax progress with scaled last result if uL is not None: workspace.rhs += (1. - relax) * workspace.ap * uL # print('FVM: Prep:', swatch.duration(True)) if not hasattr(times, '__len__'): if sparse and not hasattr(workspace, 'solver'): Sm = pg.matrix.SparseMatrix(workspace.S) # hold Sm until we have reference counting, # loosing Sm here will kill LinSolver later workspace.Sm = Sm workspace.solver = pg.core.LinSolver(Sm, True) u = None if sparse: u = workspace.solver.solve(workspace.rhs) else: u = np.linalg.solve(workspace.S, workspace.rhs) print('FVM solve:', swatch.duration(True)) return u[0:mesh.cellCount():1] else: theta = kwargs.pop('theta', 0.5) verbose = kwargs.pop('verbose', False) if sparse: I = solver.identity(len(workspace.rhs)) else: I = np.diag(np.ones(len(workspace.rhs))) print("solve cN") return solver.crankNicolson(times, theta, workspace.S, I, f=workspace.rhs, u0=u0, verbose=verbose)
def solveFiniteVolume(mesh, a=1.0, f=0.0, fn=0.0, vel=0.0, u0=None, times=None, uL=None, relax=1.0, ws=None, scheme='CDS', **kwargs): """ """ # The Workspace is to hold temporary data or preserve matrix rebuild swatch = pg.Stopwatch(True) sparse = True workspace = WorkSpace() if ws: workspace = ws a = solver.parseArgToArray(a, [mesh.cellCount(), mesh.boundaryCount()]) f = solver.parseArgToArray(f, mesh.cellCount()) fn = solver.parseArgToArray(fn, mesh.cellCount()) boundsDirichlet = None boundsNeumann = None if not hasattr(workspace, 'S'): if 'uBoundary' in kwargs: boundsDirichlet = pg.solver.parseArgToBoundaries( kwargs['uBoundary'], mesh) if 'duBoundary' in kwargs: boundsNeumann = pg.solver.parseArgToBoundaries( kwargs['duBoundary'], mesh) workspace.S, workspace.rhsBCScales = diffusionConvectionKernel( mesh=mesh, a=a, f=f, uBoundaries=boundsDirichlet, duBoundaries=boundsNeumann, u0=u0, fn=fn, vel=vel, scheme=scheme, sparse=sparse, userData=kwargs.pop('userData', None)) print('FVM kernel 1:', swatch.duration(True)) dof = len(workspace.rhsBCScales) # workspace.uDir = np.zeros(dof) # if u0 is not None: # workspace.uDir = np.array(u0) # # if len(boundsDirichlet): # for boundary, val in boundsDirichlet.items(): # workspace.uDir[boundary.leftCell().id()] = val workspace.ap = np.zeros(dof) # for nonlinears if uL is not None: for i in range(dof): val = 0.0 if sparse: val = workspace.S.getVal(i, i) / relax workspace.S.setVal(i, i, val) # workspace.S[i, i] /= relax # workspace.ap[i] = workspace.S[i, i] else: val = workspace.S[i, i] / relax workspace.S[i, i] = val workspace.ap[i] = val print('FVM kernel 2:', swatch.duration(True)) # endif: not hasattr(workspace, 'S'): workspace.rhs = np.zeros(len(workspace.rhsBCScales)) workspace.rhs[0:mesh.cellCount()] = f # * mesh.cellSizes() # if len(workspace.uDir): workspace.rhs += workspace.rhsBCScales # for nonlinear: relax progress with scaled last result if uL is not None: workspace.rhs += (1. - relax) * workspace.ap * uL # print('FVM: Prep:', swatch.duration(True)) if not hasattr(times, '__len__'): if sparse and not hasattr(workspace, 'solver'): Sm = pg.RSparseMatrix(workspace.S) # hold Sm until we have reference counting, # loosing Sm here will kill LinSolver later workspace.Sm = Sm workspace.solver = pg.LinSolver(Sm, True) u = None if sparse: u = workspace.solver.solve(workspace.rhs) else: u = np.linalg.solve(workspace.S, workspace.rhs) print('FVM solve:', swatch.duration(True)) return u[0:mesh.cellCount():1] else: theta = kwargs.pop('theta', 0.5) verbose = kwargs.pop('verbose', False) if sparse: I = solver.identity(len(workspace.rhs)) else: I = np.diag(np.ones(len(workspace.rhs))) print("solve cN") return solver.crankNicolson(times, theta, workspace.S, I, f=workspace.rhs, u0=u0, verbose=verbose)