class ConvectionTerm(FaceTerm): """ .. attention:: This class is abstract. Always create one of its subclasses. """ def __init__(self, coeff=1.0, diffusionTerm=None): """ Create a `ConvectionTerm` object. >>> from fipy.meshes.grid1D import Grid1D >>> from fipy.variables.cellVariable import CellVariable >>> from fipy.variables.faceVariable import FaceVariable >>> m = Grid1D(nx = 2) >>> cv = CellVariable(mesh = m) >>> fv = FaceVariable(mesh = m) >>> vcv = CellVariable(mesh=m, rank=1) >>> vfv = FaceVariable(mesh=m, rank=1) >>> __ConvectionTerm(coeff = cv) Traceback (most recent call last): ... TypeError: The coefficient must be a vector value. >>> __ConvectionTerm(coeff = fv) Traceback (most recent call last): ... TypeError: The coefficient must be a vector value. >>> __ConvectionTerm(coeff = vcv) __ConvectionTerm(coeff=_ArithmeticCellToFaceVariable(value=array([[ 0., 0., 0.]]), mesh=UniformGrid1D(dx=1.0, nx=2))) >>> __ConvectionTerm(coeff = vfv) __ConvectionTerm(coeff=FaceVariable(value=array([[ 0., 0., 0.]]), mesh=UniformGrid1D(dx=1.0, nx=2))) >>> __ConvectionTerm(coeff = (1,)) __ConvectionTerm(coeff=(1,)) >>> from fipy.terms.explicitUpwindConvectionTerm import ExplicitUpwindConvectionTerm >>> ExplicitUpwindConvectionTerm(coeff = (0,)).solve(var = cv) >>> ExplicitUpwindConvectionTerm(coeff = 1).solve(var = cv) Traceback (most recent call last): ... TypeError: The coefficient must be a vector value. >>> from fipy.meshes.grid2D import Grid2D >>> m2 = Grid2D(nx=2, ny=1) >>> cv2 = CellVariable(mesh=m2) >>> vcv2 = CellVariable(mesh=m2, rank=1) >>> vfv2 = FaceVariable(mesh=m2, rank=1) >>> __ConvectionTerm(coeff=vcv2) __ConvectionTerm(coeff=_ArithmeticCellToFaceVariable(value=array([[ 0., 0., 0., 0., 0., 0., 0.], [ 0., 0., 0., 0., 0., 0., 0.]]), mesh=UniformGrid2D(dx=1.0, nx=2, dy=1.0, ny=1))) >>> __ConvectionTerm(coeff=vfv2) __ConvectionTerm(coeff=FaceVariable(value=array([[ 0., 0., 0., 0., 0., 0., 0.], [ 0., 0., 0., 0., 0., 0., 0.]]), mesh=UniformGrid2D(dx=1.0, nx=2, dy=1.0, ny=1))) >>> ExplicitUpwindConvectionTerm(coeff = ((0,),(0,))).solve(var=cv2) >>> ExplicitUpwindConvectionTerm(coeff = (0,0)).solve(var=cv2) :Parameters: - `coeff` : The `Term`'s coefficient value. - `diffusionTerm` : **deprecated**. The Peclet number is calculated automatically. """ if self.__class__ is ConvectionTerm: raise NotImplementedError, "can't instantiate abstract base class" if diffusionTerm is not None: import warnings warnings.warn("The Peclet number is calculated automatically. diffusionTerm will be ignored.", DeprecationWarning, stacklevel=2) self.stencil = None if isinstance(coeff, _MeshVariable) and coeff.getRank() != 1: raise TypeError, "The coefficient must be a vector value." if isinstance(coeff, CellVariable): coeff = coeff.getArithmeticFaceValue() FaceTerm.__init__(self, coeff = coeff) def _calcGeomCoeff(self, mesh): if not isinstance(self.coeff, FaceVariable): self.coeff = FaceVariable(mesh=mesh, value=self.coeff, rank=1) projectedCoefficients = self.coeff * mesh._getOrientedAreaProjections() return projectedCoefficients.sum(0) def _getWeight(self, mesh, equation=None): if self.stencil is None: small = -1e-20 if equation is None: diffCoeff = small else: diffCoeff = equation._getDiffusiveGeomCoeff(mesh) if diffCoeff is None: diffCoeff = small else: diffCoeff = diffCoeff.getNumericValue() diffCoeff = (diffCoeff == 0) * small + diffCoeff alpha = self._Alpha(-self._getGeomCoeff(mesh) / diffCoeff) self.stencil = {'implicit' : {'cell 1 diag' : alpha, 'cell 1 offdiag' : (1-alpha), 'cell 2 diag' : -(1-alpha), 'cell 2 offdiag' : -alpha}} return self.stencil def _getDefaultSolver(self, solver, *args, **kwargs): if solver and not solver._canSolveAsymmetric(): import warnings warnings.warn("%s cannot solve assymetric matrices" % solver) return solver or DefaultAsymmetricSolver(*args, **kwargs) 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 __add__(self, other): if isinstance(other, ConvectionTerm): if other.__class__ != self.__class__: raise TypeError, "ConvectionTerms must use the same scheme: %s != %s" % (self.__class__.__name__, other.__class__.__name__) return self.__class__(coeff=self.coeff + other.coeff) else: return FaceTerm.__add__(self, other)