def CylindricalGrid2D(dr=None, dz=None, nr=None, nz=None, Lr=None, Lz=None, dx=1., dy=1., nx=None, ny=None, Lx=None, Ly=None, origin=((0,),(0,)), overlap=2, communicator=parallelComm): r""" Factory function to select between CylindricalUniformGrid2D and CylindricalNonUniformGrid2D. If `Lx` is specified the length of the domain is always `Lx` regardless of `dx`. :Parameters: - `dr` or `dx`: grid spacing in the radial direction - `dz` or `dy`: grid spacing in the vertical direction - `nr` or `nx`: number of cells in the radial direction - `nz` or `ny`: number of cells in the vertical direction - `Lr` or `Lx`: the domain length in the radial direction - `Lz` or `Ly`: the domain length in the vertical direction - `origin` : position of the mesh's origin in the form ((x,),(y,)) - `overlap`: the number of overlapping cells for parallel simulations. Generally 2 is adequate. Higher order equations or discretizations require more. - `communicator`: either `fipy.tools.parallelComm` or `fipy.tools.serialComm`. Select `fipy.tools.serialComm` to create a serial mesh when running in parallel. Mostly used for test purposes. """ if dr is not None: dx = dr if dz is not None: dy = dz nx = nr or nx ny = nz or ny Lx = Lr or Lx Ly = Lz or Ly if numerix.getShape(dx) == () and numerix.getShape(dy) == (): dx, nx = _dnl(dx, nx, Lx) dy, ny = _dnl(dy, ny, Ly) from fipy.meshes.cylindricalUniformGrid2D import CylindricalUniformGrid2D return CylindricalUniformGrid2D(dx=dx, dy=dy, nx=nx or 1, ny=ny or 1, origin=origin, overlap=overlap, communicator=communicator) else: from fipy.meshes.cylindricalNonUniformGrid2D import CylindricalNonUniformGrid2D return CylindricalNonUniformGrid2D(dx=dx, dy=dy, nx=nx, ny=ny, origin=origin, overlap=overlap, communicator=communicator)
def _calcGeomCoeff(self, var): mesh = var.mesh if self.nthCoeff is not None: coeff = self.nthCoeff shape = numerix.getShape(coeff) if isinstance(coeff, FaceVariable): rank = coeff.rank else: rank = len(shape) if var.rank == 0: anisotropicRank = rank elif var.rank == 1: anisotropicRank = rank - 2 else: raise IndexError('the solution variable has the wrong rank') if anisotropicRank == 0 and self._treatMeshAsOrthogonal(mesh): if coeff.shape != () and not isinstance(coeff, FaceVariable): coeff = coeff[..., numerix.newaxis] tmpBop = (coeff * FaceVariable(mesh=mesh, value=mesh._faceAreas) / mesh._cellDistances)[numerix.newaxis, :] else: if anisotropicRank == 1 or anisotropicRank == 0: coeff = coeff * numerix.identity(mesh.dim) if anisotropicRank > 0: shape = numerix.getShape(coeff) if mesh.dim != shape[0] or mesh.dim != shape[1]: raise IndexError( 'diffusion coefficient tensor is not an appropriate shape for this mesh' ) faceNormals = FaceVariable(mesh=mesh, rank=1, value=mesh.faceNormals) rotationTensor = self.__getRotationTensor(mesh) rotationTensor[:, 0] = rotationTensor[:, 0] / mesh._cellDistances tmpBop = faceNormals.dot(coeff).dot( rotationTensor) * mesh._faceAreas return tmpBop else: return None
def Grid2D(dx=1., dy=1., nx=None, ny=None, Lx=None, Ly=None, overlap=2, communicator=parallelComm): r""" Factory function to select between UniformGrid2D and NonUniformGrid2D. If `Lx` is specified the length of the domain is always `Lx` regardless of `dx`. :Parameters: - `dx`: grid spacing in the horizontal direction - `dy`: grid spacing in the vertical direction - `nx`: number of cells in the horizontal direction - `ny`: number of cells in the vertical direction - `Lx`: the domain length in the horizontal direction - `Ly`: the domain length in the vertical direction - `overlap`: the number of overlapping cells for parallel simulations. Generally 2 is adequate. Higher order equations or discretizations require more. - `communicator`: either `fipy.tools.parallelComm` or `fipy.tools.serialComm`. Select `fipy.tools.serialComm` to create a serial mesh when running in parallel. Mostly used for test purposes. >>> print(Grid2D(Lx=3., nx=2).dx) 1.5 """ if numerix.getShape(dx) == () and numerix.getShape(dy) == (): dx, nx = _dnl(dx, nx, Lx) dy, ny = _dnl(dy, ny, Ly) from fipy.meshes.uniformGrid2D import UniformGrid2D return UniformGrid2D(dx=dx, dy=dy, nx=nx, ny=ny, overlap=overlap, communicator=communicator) else: from fipy.meshes.nonUniformGrid2D import NonUniformGrid2D return NonUniformGrid2D(dx=dx, dy=dy, nx=nx, ny=ny, overlap=overlap, communicator=communicator)
def _calcGeomCoeff(self, var): mesh = var.mesh if self.nthCoeff is not None: coeff = self.nthCoeff shape = numerix.getShape(coeff) if isinstance(coeff, FaceVariable): rank = coeff.rank else: rank = len(shape) if var.rank == 0: anisotropicRank = rank elif var.rank == 1: anisotropicRank = rank - 2 else: raise IndexError, 'the solution variable has the wrong rank' if anisotropicRank == 0 and self._treatMeshAsOrthogonal(mesh): if coeff.shape != () and not isinstance(coeff, FaceVariable): coeff = coeff[...,numerix.newaxis] tmpBop = (coeff * FaceVariable(mesh=mesh, value=mesh._faceAreas) / mesh._cellDistances)[numerix.newaxis, :] else: if anisotropicRank == 1 or anisotropicRank == 0: coeff = coeff * numerix.identity(mesh.dim) if anisotropicRank > 0: shape = numerix.getShape(coeff) if mesh.dim != shape[0] or mesh.dim != shape[1]: raise IndexError, 'diffusion coefficent tensor is not an appropriate shape for this mesh' faceNormals = FaceVariable(mesh=mesh, rank=1, value=mesh.faceNormals) rotationTensor = self.__getRotationTensor(mesh) rotationTensor[:,0] = rotationTensor[:,0] / mesh._cellDistances tmpBop = faceNormals.dot(coeff).dot(rotationTensor) * mesh._faceAreas return tmpBop else: return None
def setValue(self, value, unit=None, where=None): """ Set the value of the Variable. Can take a masked array. >>> a = Variable((1,2,3)) >>> a.setValue(5, where=(1, 0, 1)) >>> print a [5 2 5] >>> b = Variable((4,5,6)) >>> a.setValue(b, where=(1, 0, 1)) >>> print a [4 2 6] >>> print b [4 5 6] >>> a.setValue(3) >>> print a [3 3 3] >>> b = numerix.array((3,4,5)) >>> a.setValue(b) >>> a[:] = 1 >>> print b [3 4 5] >>> a.setValue((4,5,6), where=(1, 0)) Traceback (most recent call last): .... ValueError: shape mismatch: objects cannot be broadcast to a single shape """ if where is not None: tmp = numerix.empty(numerix.getShape(where), self.getsctype()) tmp[:] = value tmp = numerix.where(where, tmp, self.getValue()) else: if hasattr(value, 'copy'): tmp = value.copy() else: tmp = value value = self._makeValue(value=tmp, unit=unit, array=None) if numerix.getShape(self.value) == (): self.value.itemset(value) else: self.value[:] = value self._markFresh()
def Grid1D(dx=1., nx=None, Lx=None, overlap=2, communicator=parallelComm): r""" Factory function to select between UniformGrid1D and NonUniformGrid1D. If `Lx` is specified the length of the domain is always `Lx` regardless of `dx`. :Parameters: - `dx`: grid spacing in the horizonal direction - `nx`: number of cells in the horizonal direction - `Lx`: the domain length in the horizonal direction - `overlap`: the number of overlapping cells for parallel simulations. Generally 2 is adequate. Higher order equations or discretizations require more. - `communicator`: either `fipy.tools.parallelComm` or `fipy.tools.serialComm`. Select `fipy.tools.serialComm` to create a serial mesh when running in parallel. Mostly used for test purposes. """ if numerix.getShape(dx) == (): dx, nx = _dnl(dx, nx, Lx) from fipy.meshes.uniformGrid1D import UniformGrid1D return UniformGrid1D(dx=dx, nx=nx, overlap=overlap, communicator=communicator) else: from fipy.meshes.nonUniformGrid1D import NonUniformGrid1D return NonUniformGrid1D(dx=dx, nx=nx, overlap=overlap, communicator=communicator)
def __init__(self, dx=1., nx=None, overlap=2, communicator=parallel): self.args = { 'dx': dx, 'nx': nx, 'overlap': overlap } from fipy.tools.dimensions.physicalField import PhysicalField self.dx = PhysicalField(value=dx) scale = PhysicalField(value=1, unit=self.dx.getUnit()) self.dx /= scale nx = self._calcNumPts(d=self.dx, n=nx) (self.nx, self.overlap, self.offset) = self._calcParallelGridInfo(nx, overlap, communicator) if numerix.getShape(self.dx) is not (): Xoffset = numerix.sum(self.dx[0:self.offset]) self.dx = self.dx[self.offset:self.offset + self.nx] else: Xoffset = self.dx * self.offset vertices = self._createVertices() + ((Xoffset,),) self.numberOfVertices = len(vertices[0]) faces = self._createFaces() self.numberOfFaces = len(faces[0]) cells = self._createCells() Mesh1D.__init__(self, vertices, faces, cells, communicator=communicator) self.setScale(value = scale)
def _checkDt(self, dt): if dt is None: raise TypeError, "`dt` must be specified." if numerix.getShape(dt) != (): raise TypeError, "`dt` must be a single number, not a " + type( dt).__name__ return float(dt)
def Grid2D(dx=1., dy=1., nx=None, ny=None, overlap=2, communicator=parallel): from numMesh import uniformGrid2D from numMesh import grid2D from fipy.tools import numerix if numerix.getShape(dx) == () and numerix.getShape(dy) == (): if nx is None: nx = 1 if ny is None: ny = 1 return uniformGrid2D.UniformGrid2D(dx=dx, dy=dy, nx=nx, ny=ny, overlap=overlap, communicator=communicator) else: return grid2D.Grid2D(dx=dx, dy=dy, nx=nx, ny=ny, overlap=overlap, communicator=communicator)
def __buildMatrix(self, var, solver, boundaryConditions, dt): if numerix.sctype2char(var.getsctype()) not in numerix.typecodes['Float']: import warnings warnings.warn("""sweep() or solve() are likely to produce erroneous results when `var` does not contain floats.""", UserWarning, stacklevel=4) self._verifyCoeffType(var) if numerix.getShape(dt) != (): raise TypeError, "`dt` must be a single number, not a " + type(dt).__name__ dt = float(dt) if type(boundaryConditions) not in (type(()), type([])): boundaryConditions = (boundaryConditions,) for bc in boundaryConditions: bc._resetBoundaryConditionApplied() if os.environ.has_key('FIPY_DISPLAY_MATRIX'): if not hasattr(self, "_viewer"): from fipy.viewers.matplotlibViewer.matplotlibSparseMatrixViewer import MatplotlibSparseMatrixViewer Term._viewer = MatplotlibSparseMatrixViewer() matrix, RHSvector = self._buildMatrix(var, solver._getMatrixClass(), boundaryConditions, dt) solver._storeMatrix(var=var, matrix=matrix, RHSvector=RHSvector) if os.environ.has_key('FIPY_DISPLAY_MATRIX'): self._viewer.title = "%s %s" % (var.name, self.__class__.__name__) self._viewer.plot(matrix=matrix, RHSvector=RHSvector) from fipy import raw_input raw_input()
def calcDOffsets(ds, ns, offset): """ :Parameters: - `ds`: A list, e.g. [dx, dy] - `ns`: A list, e.g. [nx, ny, nz] - `offset` :Returns: - `offsetList`: a list which contains the analogous scalars to `XOffset`, `YOffset`, and `ZOffset`, whichever are applicable for the dimensionality. - `newDs`: a list containing proper [dx, [dy, ...]] values """ offsetList = [] newDs = [] if type(offset) in [int, float]: offset = [offset] for d, n, i in zip(ds, ns, list(range(len(ds)))): if numerix.getShape(d) is not (): offsetList.append(numerix.sum(d[0:offset[i]])) newDs.append(d[offset[i]:offset[i] + n]) else: if len(offset) == 1: offsetList.append(d * offset[0]) else: offsetList.append(d * offset[i]) newDs.append(d) return offsetList, newDs
def _shapeClassAndOther(self, opShape, operatorClass, other): """ Determine the shape of the result, the base class of the result, and (if necessary) a modified form of `other` that is suitable for the operation. By default, returns the result of the generic `Variable._shapeClassAndOther()`, but if that fails, and if each dimension of `other` is exactly the `Mesh` dimension, do what the user probably "meant" and project `other` onto the `Mesh`. >>> from fipy import * >>> mesh = Grid1D(nx=5) >>> A = numerix.arange(5) >>> B = Variable(1.) >>> import warnings >>> savedFilters = list(warnings.filters) >>> warnings.resetwarnings() >>> warnings.simplefilter("error", UserWarning, append=True) >>> C = CellVariable(mesh=mesh) * (A * B) Traceback (most recent call last): ... UserWarning: The expression `(multiply([0 1 2 3 4], Variable(value=array(1.0))))` has been cast to a constant `CellVariable` >>> warnings.filters = savedFilters """ otherShape = numerix.getShape(other) if (not isinstance(other, _MeshVariable) and otherShape is not () and otherShape[-1] == self._globalNumberOfElements): if (isinstance(other, Variable) and len(other.requiredVariables) > 0): import warnings warnings.warn( "The expression `%s` has been cast to a constant `%s`" % (repr(other), self._variableClass.__name__), UserWarning, stacklevel=4) other = self._variableClass(value=other, mesh=self.mesh) newOpShape, baseClass, newOther = Variable._shapeClassAndOther( self, opShape, operatorClass, other) if ((newOpShape is None or baseClass is None) and numerix.alltrue( numerix.array(numerix.getShape(other)) == self.mesh.dim)): newOpShape, baseClass, newOther = Variable._shapeClassAndOther( self, opShape, operatorClass, other[..., numerix.newaxis]) return (newOpShape, baseClass, newOther)
def setValue(self, value, unit = None, where = None): if where is not None: shape = numerix.getShape(where) if shape != self.shape \ and shape == self._getShapeFromMesh(mesh=self.getMesh()): for dim in self.elementshape: where = numerix.repeat(where[numerix.newaxis, ...], repeats=dim, axis=0) return Variable.setValue(self, value=value, unit=unit, where=where)
def _shapeClassAndOther(self, opShape, operatorClass, other): """ Determine the shape of the result, the base class of the result, and (if necessary) a modified form of `other` that is suitable for the operation. By default, returns the result of the generic `Variable._shapeClassAndOther()`, but if that fails, and if each dimension of `other` is exactly the `Mesh` dimension, do what the user probably "meant" and project `other` onto the `Mesh`. >>> from fipy import * >>> mesh = Grid1D(nx=5) >>> A = numerix.arange(5) >>> B = Variable(1.) >>> import warnings >>> savedFilters = list(warnings.filters) >>> warnings.resetwarnings() >>> warnings.simplefilter("error", UserWarning, append=True) >>> C = CellVariable(mesh=mesh) * (A * B) Traceback (most recent call last): ... UserWarning: The expression `(multiply([0 1 2 3 4], Variable(value=array(1.0))))` has been cast to a constant `CellVariable` >>> warnings.filters = savedFilters """ otherShape = numerix.getShape(other) if (not isinstance(other, _MeshVariable) and otherShape is not () and otherShape[-1] == self._globalNumberOfElements): if (isinstance(other, Variable) and len(other.requiredVariables) > 0): import warnings warnings.warn("The expression `%s` has been cast to a constant `%s`" % (repr(other), self._variableClass.__name__), UserWarning, stacklevel=4) other = self._variableClass(value=other, mesh=self.mesh) newOpShape, baseClass, newOther = Variable._shapeClassAndOther(self, opShape, operatorClass, other) if ((newOpShape is None or baseClass is None) and numerix.alltrue(numerix.array(numerix.getShape(other)) == self.mesh.dim)): newOpShape, baseClass, newOther = Variable._shapeClassAndOther(self, opShape, operatorClass, other[..., numerix.newaxis]) return (newOpShape, baseClass, newOther)
def Grid1D(dx=1., nx=None, overlap=2, parallelModule=parallel): from numMesh import uniformGrid1D from numMesh import grid1D from fipy.tools import numerix if numerix.getShape(dx) == (): if nx is None: nx = 1 return uniformGrid1D.UniformGrid1D(dx=dx, nx=nx, overlap=overlap, parallelModule=parallelModule) else: return grid1D.Grid1D(dx=dx, nx=nx, overlap=overlap, parallelModule=parallelModule)
def Grid3D(dx = 1., dy = 1., dz = 1., nx = None, ny = None, nz = None, overlap=2, parallelModule=parallel): from numMesh import uniformGrid3D from numMesh import grid3D from fipy.tools import numerix if numerix.getShape(dx) == () \ and numerix.getShape(dy) == () \ and numerix.getShape(dz) == (): if nx is None: nx = 1 if ny is None: ny = 1 if nz is None: nz = 1 return uniformGrid3D.UniformGrid3D(dx = dx, dy = dy, dz = dz, nx = nx or 1, ny = ny or 1, nz = nz or 1, overlap=overlap, parallelModule=parallelModule) else: return grid3D.Grid3D(dx = dx, dy = dy, dz = dz, nx = nx, ny = ny, nz = nz, overlap=overlap, parallelModule=parallelModule)
def setValue(self, value, unit=None, where=None): if where is not None: shape = numerix.getShape(where) if shape != self.shape \ and shape == self._getShapeFromMesh(mesh=self.mesh): for dim in self.elementshape: where = numerix.repeat(where[numerix.newaxis, ...], repeats=dim, axis=0) return Variable.setValue(self, value=value, unit=unit, where=where)
def CylindricalGrid1D(dr=None, nr=None, Lr=None, dx=1., nx=None, Lx=None, origin=(0, ), overlap=2, communicator=parallelComm): r""" Factory function to select between `CylindricalUniformGrid1D` and `CylindricalNonUniformGrid1D`. If `Lr` is specified the length of the domain is always `Lr` regardless of `dr`, unless `dr` is a list of spacings, in which case `Lr` will be the sum of `dr`. Parameters ---------- dr : float Grid spacing in the radial direction. Alternative: `dx`. nr : int Number of cells in the radial direction. Alternative: `nx`. Lr : float Domain length in the radial direction. Alternative: `Lx`. overlap : int the number of overlapping cells for parallel simulations. Generally 2 is adequate. Higher order equations or discretizations require more. communicator : ~fipy.tools.comms.commWrapper.CommWrapper Generally, `fipy.tools.serialComm` or `fipy.tools.parallelComm`. Select `~fipy.tools.serialComm` to create a serial mesh when running in parallel; mostly used for test purposes. """ if dr is not None: dx = dr nx = nr or nx Lx = Lr or Lx if numerix.getShape(dx) == (): dx, nx = _dnl(dx, nx, Lx) from fipy.meshes.cylindricalUniformGrid1D import CylindricalUniformGrid1D return CylindricalUniformGrid1D(dx=dx, nx=nx or 1, origin=origin, overlap=overlap, communicator=parallelComm) else: from fipy.meshes.cylindricalNonUniformGrid1D import CylindricalNonUniformGrid1D return CylindricalNonUniformGrid1D(dx=dx, nx=nx, origin=origin, overlap=overlap, communicator=parallelComm)
def CylindricalGrid1D(dr=None, nr=None, dx=1., nx=None): from numMesh import cylindricalUniformGrid1D from numMesh import cylindricalGrid1D from fipy.tools import numerix if dr is not None: dx = dr nx = nr or nx if numerix.getShape(dx) == (): return cylindricalUniformGrid1D.CylindricalUniformGrid1D(dx=dx, nx=nx or 1) else: return cylindricalGrid1D.CylindricalGrid1D(dx=dx, nx=nx)
def _calcGeomCoeff(self, mesh): if self.nthCoeff is not None: coeff = self.nthCoeff shape = numerix.getShape(coeff) from fipy.variables.faceVariable import FaceVariable if isinstance(coeff, FaceVariable): rank = coeff.getRank() else: rank = len(shape) if rank == 0 and self._treatMeshAsOrthogonal(mesh): tmpBop = (coeff * mesh._getFaceAreas() / mesh._getCellDistances())[numerix.newaxis, :] else: if rank == 1 or rank == 0: coeff = coeff * numerix.identity(mesh.getDim()) if rank > 0: shape = numerix.getShape(coeff) if mesh.getDim() != shape[0] or mesh.getDim() != shape[1]: raise IndexError, 'diffusion coefficent tensor is not an appropriate shape for this mesh' faceNormals = FaceVariable(mesh=mesh, rank=1, value=mesh._getFaceNormals()) rotationTensor = self._getRotationTensor(mesh) rotationTensor[:,0] = rotationTensor[:,0] / mesh._getCellDistances() tmpBop = faceNormals.dot(coeff).dot(rotationTensor) * mesh._getFaceAreas() return tmpBop else: return None
def _shapeClassAndOther(self, opShape, operatorClass, other): """ Determine the shape of the result, the base class of the result, and (if necessary) a modified form of `other` that is suitable for the operation. By default, returns the result of the generic `Variable._shapeClassAndOther()`, but if that fails, and if each dimension of `other` is exactly the `Mesh` dimension, do what the user probably "meant" and project `other` onto the `Mesh`. """ otherShape = numerix.getShape(other) if (not isinstance(other, _MeshVariable) and otherShape is not () and otherShape[-1] == self._getGlobalNumberOfElements()): other = self._getVariableClass()(value=other, mesh=self.getMesh()) newOpShape, baseClass, newOther = Variable._shapeClassAndOther(self, opShape, operatorClass, other) if ((newOpShape is None or baseClass is None) and numerix.alltrue(numerix.array(numerix.getShape(other)) == self.getMesh().getDim())): newOpShape, baseClass, newOther = Variable._shapeClassAndOther(self, opShape, operatorClass, other[..., numerix.newaxis]) return (newOpShape, baseClass, newOther)
def CylindricalGrid2D(dr=None, dz=None, nr=None, nz=None, dx=1., dy=1., nx=None, ny=None, parallelModule=parallel): from numMesh import cylindricalUniformGrid2D from numMesh import cylindricalGrid2D from fipy.tools import numerix if dr is not None: dx = dr if dz is not None: dy = dz nx = nr or nx ny = nz or ny if dx is None: dx = 1. if dy is None: dy = 1. if numerix.getShape(dx) == () and numerix.getShape(dy) == (): return cylindricalUniformGrid2D.CylindricalUniformGrid2D(dx=dx, dy=dy, nx=nx or 1, ny=ny or 1, parallelModule=parallelModule) else: return cylindricalGrid2D.CylindricalGrid2D(dx=dx, dy=dy, nx=nx, ny=ny, parallelModule=parallelModule)
def getShape(self): """ >>> Variable(value=3).shape () >>> Variable(value=(3,)).shape (1,) >>> Variable(value=(3,4)).shape (2,) >>> Variable(value="3 m").shape () >>> Variable(value=(3,), unit="m").shape (1,) >>> Variable(value=(3,4), unit="m").shape (2,) """ if self.value is not None: return numerix.getShape(self.value) else: return ()
def calcDOffsets(ds, ns, offset): """ Parameters ---------- ds : list Spacing in each grid direction, e.g. `[dx, dy]` ns : list Number of grid spacings in each direction, e.g. `[nx, ny]` offset : list Displacement of grid spacings, e.g., `[Ox, Oy]` Returns ------- offsetList : list Contains the analogous scalars to `XOffset`, `YOffset`, and `ZOffset`, whichever are applicable for the dimensionality. newDs : list proper `[dx, [dy, ...]]` values """ offsetList = [] newDs = [] if type(offset) in [int, float]: offset = [offset] for d, n, i in zip(ds, ns, list(range(len(ds)))): if numerix.getShape(d) is not (): offsetList.append(numerix.sum(d[0:offset[i]])) newDs.append(d[offset[i]:offset[i] + n]) else: if len(offset) == 1: offsetList.append(d * offset[0]) else: offsetList.append(d * offset[i]) newDs.append(d) return offsetList, newDs
def Grid1D(dx=1., nx=None, Lx=None, overlap=2, communicator=parallelComm): r""" Factory function to select between `UniformGrid1D` and `NonUniformGrid1D`. If `Lx` is specified the length of the domain is always `Lx` regardless of `dx`, unless `dx` is a list of spacings, in which case `Lx` will be the sum of `dx` and `nx` will be the count of `dx`. Parameters ---------- dx : float Grid spacing in the horizontal direction nx : int Number of cells in the horizontal direction Lx : float Domain length in the horizontal direction overlap : int Number of overlapping cells for parallel simulations. Generally 2 is adequate. Higher order equations or discretizations require more. communicator : ~fipy.tools.comms.commWrapper.CommWrapper Generally, `fipy.tools.serialComm` or `fipy.tools.parallelComm`. Select `~fipy.tools.serialComm` to create a serial mesh when running in parallel; mostly used for test purposes. """ if numerix.getShape(dx) == (): dx, nx = _dnl(dx, nx, Lx) from fipy.meshes.uniformGrid1D import UniformGrid1D return UniformGrid1D(dx=dx, nx=nx, overlap=overlap, communicator=communicator) else: from fipy.meshes.nonUniformGrid1D import NonUniformGrid1D return NonUniformGrid1D(dx=dx, nx=nx, overlap=overlap, communicator=communicator)
def __init__(self, mesh, name='', value=0., rank=None, elementshape=None, unit=None, cached=1): """ :Parameters: - `mesh`: the mesh that defines the geometry of this `Variable` - `name`: the user-readable name of the `Variable` - `value`: the initial value - `rank`: the rank (number of dimensions) of each element of this `Variable`. Default: 0 - `elementshape`: the shape of each element of this variable Default: `rank * (mesh.getDim(),)` - `unit`: the physical units of the `Variable` """ from fipy.tools import debug if isinstance(value, (list, tuple)): value = numerix.array(value) if isinstance(value, _MeshVariable): if mesh is None: mesh = value.mesh elif mesh != value.mesh: raise ValueError, "The new 'Variable' must use the same mesh as the supplied value" self.mesh = mesh value = self._globalToLocalValue(value) if value is None: array = None elif not isinstance(value, _Constant) and isinstance(value, Variable): name = name or value.name unit = None if isinstance(value, _MeshVariable): if not isinstance(value, self._getVariableClass()): raise TypeError, "A '%s' cannot be cast to a '%s'" % (value._getVariableClass().__name__, self._getVariableClass().__name__) if elementshape is not None and elementshape != value.shape[:-1]: raise ValueError, "'elementshape' != shape of elements of 'value'" if rank is not None and rank != value.getRank(): raise ValueError, "'rank' != rank of 'value'" elementshape = value.shape[:-1] array = None # value = value._copyValue() if elementshape is None: valueShape = numerix.getShape(value) if valueShape != () and valueShape[-1] == self._getShapeFromMesh(mesh)[-1]: if elementshape is not None and elementshape != valueShape[:-1]: raise ValueError, "'elementshape' != shape of elements of 'value'" if rank is not None and rank != len(valueShape[:-1]): raise ValueError, "'rank' != rank of 'value'" elementshape = valueShape[:-1] elif rank is None and elementshape is None: elementshape = valueShape if rank is None: if elementshape is None: elementshape = () elif elementshape is None: elementshape = rank * (mesh.getDim(),) elif len(elementshape) != rank: raise ValueError, 'len(elementshape) != rank' self.elementshape = elementshape if not locals().has_key("array"): if numerix._isPhysical(value): dtype = numerix.obj2sctype(value.value) else: dtype = numerix.obj2sctype(value) array = numerix.zeros(self.elementshape + self._getShapeFromMesh(mesh), dtype) if numerix._broadcastShape(array.shape, numerix.shape(value)) is None: if not isinstance(value, Variable): value = _Constant(value) value = value[..., numerix.newaxis] Variable.__init__(self, name=name, value=value, unit=unit, array=array, cached=cached)
def __init__(self, dx=1., dy=1., nx=None, ny=None, overlap=2, parallelModule=parallel): self.args = { 'dx': dx, 'dy': dy, 'nx': nx, 'ny': ny, 'overlap': overlap, 'parallelModule': parallelModule } self.dx = PhysicalField(value = dx) scale = PhysicalField(value=1, unit=self.dx.getUnit()) self.dx /= scale nx = self._calcNumPts(d=self.dx, n=nx, axis="x") self.dy = PhysicalField(value = dy) if self.dy.getUnit().isDimensionless(): self.dy = dy else: self.dy /= scale ny = self._calcNumPts(d=self.dy, n=ny, axis="y") (self.nx, self.ny, self.overlap, self.offset) = self._calcParallelGridInfo(nx, ny, overlap, parallelModule) if numerix.getShape(self.dx) is not (): Xoffset = numerix.sum(self.dx[0:self.offset[0]]) self.dx = self.dx[self.offset[0]:self.offset[0] + self.nx] else: Xoffset = 0 if numerix.getShape(self.dy) is not (): Yoffset = numerix.sum(self.dy[0:self.offset[1]]) self.dy = self.dy[self.offset[1]:self.offset[1] + self.ny] else: Yoffset = 0 if self.nx == 0: self.ny = 0 if self.ny == 0: self.nx = 0 if self.nx == 0 or self.ny == 0: self.numberOfHorizontalRows = 0 self.numberOfVerticalColumns = 0 else: self.numberOfHorizontalRows = (self.ny + 1) self.numberOfVerticalColumns = (self.nx + 1) self.numberOfVertices = self.numberOfHorizontalRows * self.numberOfVerticalColumns vertices = self._createVertices() + ((Xoffset,), (Yoffset,)) faces = self._createFaces() self.numberOfFaces = len(faces[0]) cells = self._createCells() Mesh2D.__init__(self, vertices, faces, cells) self.setScale(value = scale)
def _checkDt(self, dt): if dt is None: raise TypeError("`dt` must be specified.") if numerix.getShape(dt) != (): raise TypeError("`dt` must be a single number, not a " + type(dt).__name__) return float(dt)
def __init__(self, mesh, name='', value=0., rank=None, elementshape=None, unit=None, cached=1): """ :Parameters: - `mesh`: the mesh that defines the geometry of this `Variable` - `name`: the user-readable name of the `Variable` - `value`: the initial value - `rank`: the rank (number of dimensions) of each element of this `Variable`. Default: 0 - `elementshape`: the shape of each element of this variable Default: `rank * (mesh.dim,)` - `unit`: the physical units of the `Variable` """ if isinstance(value, (list, tuple)): value = numerix.array(value) if isinstance(value, _MeshVariable): if mesh is None: mesh = value.mesh elif mesh != value.mesh: raise ValueError, "The new 'Variable' must use the same mesh as the supplied value" self.mesh = mesh value = self._globalToLocalValue(value) if value is None: array = None elif not isinstance(value, _Constant) and isinstance(value, Variable): name = name or value.name unit = None if isinstance(value, _MeshVariable): if not isinstance(value, self._variableClass): raise TypeError, "A '%s' cannot be cast to a '%s'" % ( value._variableClass.__name__, self._variableClass.__name__) if elementshape is not None and elementshape != value.shape[: -1]: raise ValueError, "'elementshape' != shape of elements of 'value'" if rank is not None and rank != value.rank: raise ValueError, "'rank' != rank of 'value'" elementshape = value.shape[:-1] array = None # value = value._copyValue() if elementshape is None: valueShape = numerix.getShape(value) if valueShape != () and valueShape[-1] == self._getShapeFromMesh( mesh)[-1]: if elementshape is not None and elementshape != valueShape[:-1]: raise ValueError, "'elementshape' != shape of elements of 'value'" if rank is not None and rank != len(valueShape[:-1]): raise ValueError, "'rank' != rank of 'value'" elementshape = valueShape[:-1] elif rank is None and elementshape is None: elementshape = valueShape if rank is None: if elementshape is None: elementshape = () elif elementshape is None: elementshape = rank * (mesh.dim, ) elif len(elementshape) != rank: raise ValueError, 'len(elementshape) != rank' self.elementshape = elementshape if not "array" in locals(): if numerix._isPhysical(value): dtype = numerix.obj2sctype(value.value) else: dtype = numerix.obj2sctype(value) #print "meshvariable elshape: ",self.elementshape #print "meshvariable _getShapeFromMesh: ",self._getShapeFromMesh(mesh) array = numerix.zeros( self.elementshape + self._getShapeFromMesh(mesh), dtype) if numerix._broadcastShape(array.shape, numerix.shape(value)) is None: if not isinstance(value, Variable): value = _Constant(value) value = value[..., numerix.newaxis] Variable.__init__(self, name=name, value=value, unit=unit, array=array, cached=cached)
def __init__(self, dx = 1., dy = 1., dz = 1., nx = None, ny = None, nz = None, overlap=2, communicator=parallel): self.args = { 'dx': dx, 'dy': dy, 'dz' :dz, 'nx': nx, 'ny': ny, 'nz': nz, 'overlap': overlap, 'communicator': communicator } self.dx = PhysicalField(value = dx) scale = PhysicalField(value = 1, unit = self.dx.getUnit()) self.dx /= scale nx = self._calcNumPts(d = self.dx, n = nx, axis = "x") self.dy = PhysicalField(value = dy) if self.dy.getUnit().isDimensionless(): self.dy = dy else: self.dy /= scale ny = self._calcNumPts(d = self.dy, n = ny, axis = "y") self.dz = PhysicalField(value = dz) if self.dz.getUnit().isDimensionless(): self.dz = dz else: self.dz /= scale nz = self._calcNumPts(d = self.dz, n = nz, axis = "z") (self.nx, self.ny, self.nz, self.overlap, self.offset) = self._calcParallelGridInfo(nx, ny, nz, overlap, communicator) if numerix.getShape(self.dx) is not (): Xoffset = numerix.sum(self.dx[0:self.offset[0]]) self.dx = self.dx[self.offset[0]:self.offset[0] + self.nx] else: Xoffset = 0 if numerix.getShape(self.dy) is not (): Yoffset = numerix.sum(self.dy[0:self.offset[1]]) self.dy = self.dy[self.offset[1]:self.offset[1] + self.ny] else: Yoffset = 0 if numerix.getShape(self.dy) is not (): Zoffset = numerix.sum(self.dz[0:self.offset[2]]) self.dz = self.dz[self.offset[2]:self.offset[2] + self.nz] else: Zoffset = 0 if self.nx == 0 or self.ny == 0 or self.nz == 0: self.nx = 0 self.ny = 0 self.nz = 0 if self.nx == 0 or self.ny == 0 or self.nz == 0: self.numberOfHorizontalRows = 0 self.numberOfVerticalColumns = 0 self.numberOfLayersDeep = 0 else: self.numberOfHorizontalRows = (self.ny + 1) self.numberOfVerticalColumns = (self.nx + 1) self.numberOfLayersDeep = (self.nz + 1) self.numberOfVertices = self.numberOfHorizontalRows * self.numberOfVerticalColumns * self.numberOfLayersDeep vertices = self._createVertices() + ((Xoffset,), (Yoffset,), (Zoffset,)) faces = self._createFaces() cells = self._createCells() Mesh.__init__(self, vertices, faces, cells) self.setScale(value = scale)
def _checkVar(self, var): FaceTerm._checkVar(self, var) if not (isinstance(self.coeff, FaceVariable) and self.coeff.rank == 1): coeffShape = numerix.getShape(self.coeff) if (coeffShape is ()) or (coeffShape[0] != var.mesh.dim): raise VectorCoeffError
def Grid3D(dx=1., dy=1., dz=1., nx=None, ny=None, nz=None, Lx=None, Ly=None, Lz=None, overlap=2, communicator=parallelComm): r""" Factory function to select between `UniformGrid3D` and `NonUniformGrid3D`. If `L{x,y,z}` is specified, the length of the domain is always `L{x,y,z}` regardless of `d{x,y,z}`, unless `d{x,y,z}` is a list of spacings, in which case `L{x,y,z}` will be the sum of `d{x,y,z}` and `n{x,y,z}` will be the count of `d{x,y,z}`. Parameters ---------- dx : float Grid spacing in the horizontal direction dy : float Grid spacing in the vertical direction dz : float Grid spacing in the depth direction nx : int Number of cells in the horizontal direction ny : int Number of cells in the vertical direction nz : int Number of cells in the depth direction Lx : float Domain length in the horizontal direction Ly : float Domain length in the vertical direction Lz : float Domain length in the depth direction overlap : int Number of overlapping cells for parallel simulations. Generally 2 is adequate. Higher order equations or discretizations require more. communicator : ~fipy.tools.comms.commWrapper.CommWrapper Generally, `fipy.tools.serialComm` or `fipy.tools.parallelComm`. Select `~fipy.tools.serialComm` to create a serial mesh when running in parallel; mostly used for test purposes. """ if numerix.getShape(dx) == () \ and numerix.getShape(dy) == () \ and numerix.getShape(dz) == (): dx, nx = _dnl(dx, nx, Lx) dy, ny = _dnl(dy, ny, Ly) dz, nz = _dnl(dz, nz, Lz) from fipy.meshes.uniformGrid3D import UniformGrid3D return UniformGrid3D(dx=dx, dy=dy, dz=dz, nx=nx or 1, ny=ny or 1, nz=nz or 1, overlap=overlap, communicator=communicator) else: from fipy.meshes.nonUniformGrid3D import NonUniformGrid3D return NonUniformGrid3D(dx=dx, dy=dy, dz=dz, nx=nx, ny=ny, nz=nz, overlap=overlap, communicator=communicator)
def _verifyCoeffType(self, var): if not (isinstance(self.coeff, FaceVariable) and self.coeff.getRank() == 1) \ and numerix.getShape(self.coeff) != (var.getMesh().getDim(),): raise TypeError, "The coefficient must be a vector value."
def _broadcastShape(self, other): ignore, ignore, broadcastshape = numerix._broadcastShapes(self.shape, numerix.getShape(other)) return broadcastshape