def __init__(self, heatSLE, rtolerance=1.0e-5, **kwargs): if not isinstance(heatSLE, uw.systems.SteadyStateHeat): raise TypeError("Provided system must be of 'SteadyStateHeat' class") self._heatSLE=heatSLE self._temperatureField=heatSLE._temperatureField if not isinstance( heatSLE._temperatureField, uw.mesh.MeshVariable): raise TypeError( "Provided 'temperatureField' must be of 'MeshVariable' class." ) # create solutions vector self._temperatureSol = sle.SolutionVector(heatSLE._temperatureField) if not isinstance(rtolerance, float): raise TypeError( "Provided 'rtolerance' must be of type 'float'" ) self._rtolerance=rtolerance self.options=OptionsGroup() super(HeatSolver, self).__init__(**kwargs)
def __init__(self, pressureField, fn_diffusivity, fn_bodyforce=None, voronoi_swarm=None, conditions=[], velocityField=None, swarmVarVelocity=None, _removeBCs=True, **kwargs): if not isinstance(pressureField, uw.mesh.MeshVariable): raise TypeError( "Provided 'pressureField' must be of 'MeshVariable' class.") self._pressureField = pressureField try: _fn_diffusivity = uw.function.Function.convert(fn_diffusivity) except Exception as e: raise uw._prepend_message_to_exception( e, "Exception encountered. Note that provided 'fn_diffusivity' must be of or convertible to 'Function' class.\nEncountered exception message:\n" ) if not fn_bodyforce: if pressureField.mesh.dim == 2: fn_bodyforce = (0., 0.) else: fn_bodyforce = (0., 0., 0.) try: _fn_bodyforce = uw.function.Function.convert(fn_bodyforce) except Exception as e: raise uw._prepend_message_to_exception( e, "Exception encountered. Note that provided 'fn_bodyforce' must be of or convertible to 'Function' class.\nEncountered exception message:\n" ) if voronoi_swarm and not isinstance(voronoi_swarm, uw.swarm.Swarm): raise TypeError("Provided 'swarm' must be of 'Swarm' class.") self._swarm = voronoi_swarm if len(numpy.unique(voronoi_swarm.owningCell.data[:])) != len( voronoi_swarm.owningCell.data[:]): import warnings warnings.warn( "It is not advised to fill any cell with more than one particle, as the Q1 shape function cannot capture material interfaces. Use at your own risk." ) if velocityField and not isinstance(velocityField, uw.mesh.MeshVariable): raise TypeError( "Provided 'velocityField' must be of 'MeshVariable' class.") self._velocityField = velocityField if swarmVarVelocity and not isinstance(swarmVarVelocity, uw.swarm.SwarmVariable): raise TypeError( "Provided 'swarmVarVelocity' must be of 'SwarmVariable' class." ) self._swarmVarVelocity = swarmVarVelocity if voronoi_swarm and pressureField.mesh.elementType == 'Q2': import warnings warnings.warn( "Voronoi integration may yield unsatisfactory results for Q2 element types. Q2 element types can also result in spurious velocity calculations." ) if not isinstance(_removeBCs, bool): raise TypeError("Provided '_removeBCs' must be of type bool.") self._removeBCs = _removeBCs # error check dcs 'dirichlet conditions' and ncs 'neumann cond.' FeMesh_IndexSets nbc = None mesh = pressureField.mesh if not isinstance(conditions, (list, tuple)): conditionslist = [] conditionslist.append(conditions) conditions = conditionslist for cond in conditions: if not isinstance(cond, uw.conditions.SystemCondition): raise TypeError( "Provided 'conditions' must be a list 'SystemCondition' objects." ) # set the bcs on here if type(cond) == uw.conditions.DirichletCondition: if cond.variable == pressureField: libUnderworld.StgFEM.FeVariable_SetBC( pressureField._cself, cond._cself) elif type(cond) == uw.conditions.NeumannCondition: nbc = cond else: raise RuntimeError("Can't decide on input condition") # build the equation numbering for the temperature field discretisation tEqNums = self._tEqNums = sle.EqNumber(pressureField, removeBCs=self._removeBCs) # create solutions vector self._solutionVector = sle.SolutionVector(pressureField, tEqNums) libUnderworld.StgFEM.SolutionVector_LoadCurrentFeVariableValuesOntoVector( self._solutionVector._cself) # create force vectors self._fvector = sle.AssembledVector(pressureField, tEqNums) # and matrices self._kmatrix = sle.AssembledMatrix(self._solutionVector, self._solutionVector, rhs=self._fvector) # we will use voronoi if that has been requested by the user, else use # gauss integration. if self._swarm: intswarm = self._swarm._voronoi_swarm # need to ensure voronoi is populated now, as assembly terms will call # initial test functions which may require a valid voronoi swarm self._swarm._voronoi_swarm.repopulate() else: intswarm = uw.swarm.GaussIntegrationSwarm(mesh) self._kMatTerm = sle.MatrixAssemblyTerm_NA_i__NB_i__Fn( integrationSwarm=intswarm, assembledObject=self._kmatrix, fn=_fn_diffusivity) self._forceVecTerm = sle.VectorAssemblyTerm_NA_i__Fn_i( integrationSwarm=intswarm, assembledObject=self._fvector, fn=fn_bodyforce * fn_diffusivity) # search for neumann conditions for cond in conditions: if isinstance(cond, uw.conditions.NeumannCondition): #NOTE many NeumannConditions can be used but the _sufaceFluxTerm only records the last ### -VE flux because of Energy_SLE_Solver ### negativeCond = uw.conditions.NeumannCondition( fn_flux=-1.0 * cond.fn_flux, variable=cond.variable, indexSetsPerDof=cond.indexSet) self._surfaceFluxTerm = sle.VectorSurfaceAssemblyTerm_NA__Fn__ni( assembledObject=self._fvector, surfaceGaussPoints=2, nbc=negativeCond) super(SteadyStateDarcyFlow, self).__init__(**kwargs)
def __init__(self, phiField, phiDotField, velocityField, fn_diffusivity, fn_sourceTerm=None, conditions=[], **kwargs): self._diffusivity = fn_diffusivity self._source = fn_sourceTerm if not isinstance(phiField, uw.mesh.MeshVariable): raise TypeError( "Provided 'phiField' must be of 'MeshVariable' class.") if phiField.data.shape[1] != 1: raise TypeError("Provided 'phiField' must be a scalar") self._phiField = phiField if not isinstance(phiDotField, (uw.mesh.MeshVariable, type(None))): raise TypeError( "Provided 'phiDotField' must be 'None' or of 'MeshVariable' class." ) if self._phiField.data.shape != phiDotField.data.shape: raise TypeError( "Provided 'phiDotField' is not the same shape as the provided 'phiField'" ) self._phiDotField = phiDotField # check compatibility of phiField and velocityField if velocityField.data.shape[1] != self._phiField.mesh.dim: raise TypeError( "Provided 'velocityField' must be the same dimensionality as the phiField's mesh" ) self._velocityField = velocityField if not isinstance(conditions, (list, tuple)): conditionslist = [] conditionslist.append(conditions) conditions = conditionslist # check input 'conditions' list is valid nbc = None for cond in conditions: if not isinstance(cond, uw.conditions.SystemCondition): raise TypeError( "Provided 'conditions' must be a list 'SystemCondition' objects." ) # set the bcs on here if type(cond) == uw.conditions.NeumannCondition: if nbc != None: # check only one nbc condition is given in 'conditions' list RuntimeError( "Provided 'conditions' can only accept one NeumannConditions condition object." ) elif type(cond) == uw.conditions.DirichletCondition: if cond.variable == self._phiField: libUnderworld.StgFEM.FeVariable_SetBC( self._phiField._cself, cond._cself) libUnderworld.StgFEM.FeVariable_SetBC( self._phiDotField._cself, cond._cself) else: raise RuntimeError("Input condition type not recognised.") self._conditions = conditions # force removal of BCs as SUPG cannot handle leaving them in self._eqNumPhi = sle.EqNumber(phiField, removeBCs=True) self._eqNumPhiDot = sle.EqNumber(phiDotField, removeBCs=True) self._phiSolution = sle.SolutionVector(phiField, self._eqNumPhi) self._phiDotSolution = sle.SolutionVector(phiDotField, self._eqNumPhiDot) # create force vectors self._residualVector = sle.AssembledVector(phiField, self._eqNumPhi) self._massVector = sle.AssembledVector(phiField, self._eqNumPhi) # create swarm self._gaussSwarm = uw.swarm.GaussIntegrationSwarm(self._phiField.mesh) super(AdvectionDiffusion, self).__init__(**kwargs) self._cself.phiVector = self._phiSolution._cself self._cself.phiDotVector = self._phiDotSolution._cself
def __init__(self, temperatureField, fn_diffusivity, fn_heating=0., voronoi_swarm=None, conditions=[], _removeBCs=True, **kwargs): if not isinstance(temperatureField, uw.mesh.MeshVariable): raise TypeError( "Provided 'temperatureField' must be of 'MeshVariable' class.") self._temperatureField = temperatureField try: _fn_diffusivity = uw.function.Function.convert(fn_diffusivity) except Exception as e: raise uw._prepend_message_to_exception( e, "Exception encountered. Note that provided 'fn_diffusivity' must be of or convertible to 'Function' class.\nEncountered exception message:\n" ) try: _fn_heating = uw.function.Function.convert(fn_heating) except Exception as e: raise uw._prepend_message_to_exception( e, "Exception encountered. Note that provided 'fn_heating' must be of or convertible to 'Function' class.\nEncountered exception message:\n" ) if voronoi_swarm and not isinstance(voronoi_swarm, uw.swarm.Swarm): raise TypeError("Provided 'swarm' must be of 'Swarm' class.") self._swarm = voronoi_swarm if voronoi_swarm and temperatureField.mesh.elementType == 'Q2': import warnings warnings.warn( "Voronoi integration may yield unsatisfactory results for Q2 element types." ) if not isinstance(_removeBCs, bool): raise TypeError("Provided '_removeBCs' must be of type bool.") self._removeBCs = _removeBCs # error check dcs 'dirichlet conditions' and ncs 'neumann cond.' FeMesh_IndexSets nbc = None mesh = temperatureField.mesh if not isinstance(conditions, (list, tuple)): conditionslist = [] conditionslist.append(conditions) conditions = conditionslist for cond in conditions: if not isinstance(cond, uw.conditions.SystemCondition): raise TypeError( "Provided 'conditions' must be a list 'SystemCondition' objects." ) # set the bcs on here if type(cond) == uw.conditions.DirichletCondition: if cond.variable == temperatureField: libUnderworld.StgFEM.FeVariable_SetBC( temperatureField._cself, cond._cself) elif type(cond) == uw.conditions.NeumannCondition: nbc = cond else: raise RuntimeError("Can't decide on input condition") # build the equation numbering for the temperature field discretisation tEqNums = self._tEqNums = sle.EqNumber(temperatureField, removeBCs=self._removeBCs) # create solutions vector self._solutionVector = sle.SolutionVector(temperatureField, tEqNums) libUnderworld.StgFEM.SolutionVector_LoadCurrentFeVariableValuesOntoVector( self._solutionVector._cself) # create force vectors self._fvector = sle.AssembledVector(temperatureField, tEqNums) # and matrices self._kmatrix = sle.AssembledMatrix(self._solutionVector, self._solutionVector, rhs=self._fvector) # we will use voronoi if that has been requested by the user, else use # gauss integration. if self._swarm: intswarm = self._swarm._voronoi_swarm # need to ensure voronoi is populated now, as assembly terms will call # initial test functions which may require a valid voronoi swarm self._swarm._voronoi_swarm.repopulate() else: intswarm = uw.swarm.GaussIntegrationSwarm(mesh) self._kMatTerm = sle.MatrixAssemblyTerm_NA_i__NB_i__Fn( integrationSwarm=intswarm, assembledObject=self._kmatrix, fn=_fn_diffusivity) self._forceVecTerm = sle.VectorAssemblyTerm_NA__Fn( integrationSwarm=intswarm, assembledObject=self._fvector, fn=fn_heating) # search for neumann conditions for cond in conditions: if isinstance(cond, uw.conditions.NeumannCondition): #NOTE many NeumannConditions can be used but the _sufaceFluxTerm only records the last ### -VE flux because of the FEM discretisation method of the initial equation negativeCond = uw.conditions.NeumannCondition( fn_flux=-1.0 * cond.fn_flux, variable=cond.variable, indexSetsPerDof=cond.indexSetsPerDof) self._surfaceFluxTerm = sle.VectorSurfaceAssemblyTerm_NA__Fn__ni( assembledObject=self._fvector, surfaceGaussPoints=2, nbc=negativeCond) super(SteadyStateHeat, self).__init__(**kwargs)
def __init__(self, temperatureField, fn_diffusivity=None, fn_heating=0., swarm=None, conditions=[], conductivityFn=None, heatingFn=None, rtolerance=None, **kwargs): if conductivityFn: raise RuntimeError( "Note that the 'conductivityFn' parameter has been renamed to 'fn_diffusivity'." ) if heatingFn: raise RuntimeError( "Note that the 'heatingFn' parameter has been renamed to 'fn_heating'." ) if rtolerance: raise RuntimeError("Note that the 'rtolerance' parameter has been removed.\n" \ "All solver functionality has been moved to underworld.systems.Solver.") if not isinstance(temperatureField, uw.mesh.MeshVariable): raise TypeError( "Provided 'temperatureField' must be of 'MeshVariable' class.") self._temperatureField = temperatureField if not fn_diffusivity: raise ValueError( "You must specify a diffusivity function via the 'fn_diffusivity' parameter." ) try: _fn_diffusivity = uw.function.Function._CheckIsFnOrConvertOrThrow( fn_diffusivity) except Exception as e: raise uw._prepend_message_to_exception( e, "Exception encountered. Note that provided 'fn_diffusivity' must be of or convertible to 'Function' class.\nEncountered exception message:\n" ) try: _fn_heating = uw.function.Function._CheckIsFnOrConvertOrThrow( fn_heating) except Exception as e: raise uw._prepend_message_to_exception( e, "Exception encountered. Note that provided 'fn_heating' must be of or convertible to 'Function' class.\nEncountered exception message:\n" ) if swarm and not isinstance(swarm, uw.swarm.Swarm): raise TypeError("Provided 'swarm' must be of 'Swarm' class.") self._swarm = swarm if not isinstance(conditions, (uw.conditions._SystemCondition, list, tuple)): raise TypeError( "Provided 'conditions' must be a list '_SystemCondition' objects." ) if len(conditions) > 1: raise ValueError( "Multiple conditions are not currently supported.") for cond in conditions: if not isinstance(cond, uw.conditions._SystemCondition): raise TypeError( "Provided 'conditions' must be a list '_SystemCondition' objects." ) # set the bcs on here.. will rearrange this in future. if cond.variable == self._temperatureField: libUnderworld.StgFEM.FeVariable_SetBC( self._temperatureField._cself, cond._cself) # ok, we've set some bcs, lets recreate eqnumbering libUnderworld.StgFEM._FeVariable_CreateNewEqnNumber( self._temperatureField._cself) self._conditions = conditions # create solutions vector self._temperatureSol = sle.SolutionVector(temperatureField) # create force vectors self._fvector = sle.AssembledVector(temperatureField) # and matrices self._kmatrix = sle.AssembledMatrix(temperatureField, temperatureField, rhs=self._fvector) # create swarm self._gaussSwarm = uw.swarm.GaussIntegrationSwarm( self._temperatureField.mesh) self._PICSwarm = None if self._swarm: self._PICSwarm = uw.swarm.PICIntegrationSwarm(self._swarm) swarmguy = self._PICSwarm if not swarmguy: swarmguy = self._gaussSwarm self._kMatTerm = sle.MatrixAssemblyTerm_NA_i__NB_i__Fn( integrationSwarm=swarmguy, assembledObject=self._kmatrix, fn=_fn_diffusivity) self._forceVecTerm = sle.VectorAssemblyTerm_NA__Fn( integrationSwarm=swarmguy, assembledObject=self._fvector, fn=fn_heating) super(SteadyStateHeat, self).__init__(**kwargs)
def __init__(self, velocityField, pressureField, fn_viscosity, fn_bodyforce=None, fn_one_on_lambda=None, fn_lambda=None, fn_source=None, voronoi_swarm=None, conditions=[], _removeBCs=True, _fn_viscosity2=None, _fn_director=None, fn_stresshistory=None, _fn_stresshistory=None, **kwargs): # DEPRECATION ERROR if fn_lambda != None: raise TypeError( "The parameter 'fn_lambda' has been deprecated. It has been replaced by 'fn_one_on_lambda', a simpler input parameter." ) if _fn_stresshistory: raise TypeError( "The parameter '_fn_stresshistory' has been updated to 'fn_stresshistory'." ) if not isinstance(velocityField, uw.mesh.MeshVariable): raise TypeError( "Provided 'velocityField' must be of 'MeshVariable' class.") if velocityField.nodeDofCount != velocityField.mesh.dim: raise ValueError( "Provided 'velocityField' must be a vector field of same dimensionality as its mesh." ) self._velocityField = velocityField if not isinstance(pressureField, uw.mesh.MeshVariable): raise TypeError( "Provided 'pressureField' must be of 'MeshVariable' class.") if pressureField.nodeDofCount != 1: raise ValueError( "Provided 'pressureField' must be a scalar field (ie pressureField.nodeDofCount==1)." ) self._pressureField = pressureField _fn_viscosity = uw.function.Function.convert(fn_viscosity) if not isinstance(_fn_viscosity, uw.function.Function): raise TypeError( "Provided 'fn_viscosity' must be of or convertible to 'Function' class." ) if _fn_viscosity2: _fn_viscosity2 = uw.function.Function.convert(_fn_viscosity2) if not isinstance(_fn_viscosity2, uw.function.Function): raise TypeError( "Provided 'fn_viscosity2' must be of or convertible to 'Function' class." ) if not isinstance(_removeBCs, bool): raise TypeError("Provided '_removeBCs' must be of type bool.") self._removeBCs = _removeBCs if _fn_director: _fn_director = uw.function.Function.convert(_fn_director) if not isinstance(_fn_director, uw.function.Function): raise TypeError( "Provided 'fn_director' must be of or convertible to 'Function' class." ) if fn_stresshistory: fn_stresshistory = uw.function.Function.convert(fn_stresshistory) if not isinstance(fn_stresshistory, uw.function.Function): raise TypeError( "Provided 'fn_stresshistory' must be of or convertible to 'Function' class." ) self._fn_minus_one_on_lambda = None if fn_one_on_lambda != None: self._fn_minus_one_on_lambda = uw.function.Function.convert( -1.0 * fn_one_on_lambda) if not isinstance(self._fn_minus_one_on_lambda, uw.function.Function): raise ValueError( "Provided 'fn_minus_one_on_lambda' must be of, or convertible to, the 'Function' class." ) if fn_source != None: self._fn_source = uw.function.Function.convert(fn_source) if not isinstance(self._fn_source, uw.function.Function): raise ValueError( "Provided 'fn_source' must be of, or convertible to, the 'Function' class." ) if not fn_bodyforce: if velocityField.mesh.dim == 2: fn_bodyforce = (0., 0.) else: fn_bodyforce = (0., 0., 0.) _fn_bodyforce = uw.function.Function.convert(fn_bodyforce) if voronoi_swarm and not isinstance(voronoi_swarm, uw.swarm.Swarm): raise TypeError( "Provided 'voronoi_swarm' must be of 'Swarm' class.") self._swarm = voronoi_swarm if voronoi_swarm and velocityField.mesh.elementType == 'Q2': import warnings warnings.warn( "Voronoi integration may yield unsatisfactory results for Q2 mesh." ) mesh = velocityField.mesh if not isinstance(conditions, (list, tuple)): conditionslist = [] conditionslist.append(conditions) conditions = conditionslist for cond in conditions: # set the bcs on here if not isinstance(cond, uw.conditions.SystemCondition): raise TypeError( "Provided 'conditions' must be 'SystemCondition' objects.") elif type(cond) == uw.conditions.DirichletCondition: if cond.variable == self._velocityField: libUnderworld.StgFEM.FeVariable_SetBC( self._velocityField._cself, cond._cself) elif cond.variable == self._pressureField: libUnderworld.StgFEM.FeVariable_SetBC( self._pressureField._cself, cond._cself) else: raise ValueError( "Provided condition does not appear to correspond to the system unknowns." ) self._conditions = conditions self._eqNums = dict() self._eqNums[velocityField] = sle.EqNumber(self._velocityField, self._removeBCs) self._eqNums[pressureField] = sle.EqNumber(self._pressureField, self._removeBCs) # create solutions vectors and load fevariable values onto them for best first guess self._velocitySol = sle.SolutionVector(velocityField, self._eqNums[velocityField]) self._pressureSol = sle.SolutionVector(pressureField, self._eqNums[pressureField]) libUnderworld.StgFEM.SolutionVector_LoadCurrentFeVariableValuesOntoVector( self._velocitySol._cself) libUnderworld.StgFEM.SolutionVector_LoadCurrentFeVariableValuesOntoVector( self._pressureSol._cself) # create force vectors self._fvector = sle.AssembledVector(velocityField, self._eqNums[velocityField]) self._hvector = sle.AssembledVector(pressureField, self._eqNums[pressureField]) # and matrices self._kmatrix = sle.AssembledMatrix(self._velocitySol, self._velocitySol, rhs=self._fvector) self._gmatrix = sle.AssembledMatrix(self._velocitySol, self._pressureSol, rhs=self._fvector, rhs_T=self._hvector) self._preconditioner = sle.AssembledMatrix(self._pressureSol, self._pressureSol, rhs=self._hvector) # create assembly terms which always use gauss integration gaussSwarm = uw.swarm.GaussIntegrationSwarm(self._velocityField.mesh) self._gradStiffMatTerm = sle.GradientStiffnessMatrixTerm( integrationSwarm=gaussSwarm, assembledObject=self._gmatrix) self._preCondMatTerm = sle.PreconditionerMatrixTerm( integrationSwarm=gaussSwarm, assembledObject=self._preconditioner) # for the following terms, we will use voronoi if that has been requested # by the user, else use gauss again. intswarm = gaussSwarm if self._swarm: intswarm = self._swarm._voronoi_swarm # need to ensure voronoi is populated now, as assembly terms will call # initial test functions which may require a valid voronoi swarm self._swarm._voronoi_swarm.repopulate() self._constitMatTerm = sle.ConstitutiveMatrixTerm( integrationSwarm=intswarm, assembledObject=self._kmatrix, fn_visc1=_fn_viscosity, fn_visc2=_fn_viscosity2, fn_director=_fn_director) self._forceVecTerm = sle.VectorAssemblyTerm_NA__Fn( integrationSwarm=intswarm, assembledObject=self._fvector, fn=_fn_bodyforce) if fn_source: self._cforceVecTerm = sle.VectorAssemblyTerm_NA__Fn( integrationSwarm=intswarm, assembledObject=self._hvector, fn=self.fn_source) for cond in self._conditions: if isinstance(cond, uw.conditions.NeumannCondition): #NOTE many NeumannConditions can be used but the _sufaceFluxTerm only records the last self._surfaceFluxTerm = sle.VectorSurfaceAssemblyTerm_NA__Fn__ni( assembledObject=self._fvector, surfaceGaussPoints= 3, # increase to resolve stress bc fluctuations nbc=cond) if self._fn_minus_one_on_lambda != None: # add matrix and associated assembly term for compressible stokes formulation # a mass matrix goes into the lower right block of the stokes system coeff matrix self._mmatrix = sle.AssembledMatrix(self._pressureSol, self._pressureSol, rhs=self._hvector) # -1. as per Hughes, The Finite Element Method, 1987, Table 4.3.1, [M] self._compressibleTerm = sle.MatrixAssemblyTerm_NA__NB__Fn( integrationSwarm=intswarm, assembledObject=self._mmatrix, mesh=self._velocityField.mesh, fn=self._fn_minus_one_on_lambda) if fn_stresshistory != None: self._NA_j__Fn_ijTerm = sle.VectorAssemblyTerm_NA_j__Fn_ij( integrationSwarm=intswarm, assembledObject=self._fvector, fn=fn_stresshistory) super(Stokes, self).__init__(**kwargs)
def __init__(self, velocityField, pressureField, fn_viscosity=None, fn_bodyforce=None, swarm=None, conditions=[], viscosityFn=None, bodyForceFn=None, rtolerance=None, **kwargs): # DEPRECATE 1/16 if viscosityFn: raise RuntimeError( "Note that the 'viscosityFn' parameter has been renamed to 'fn_viscosity'." ) if bodyForceFn: raise RuntimeError( "Note that the 'bodyForceFn' parameter has been renamed to 'fn_bodyforce'." ) if rtolerance: raise RuntimeError("Note that the 'rtolerance' parameter has been removed.\n" \ "All solver functionality has been moved to underworld.systems.Solver.") if not isinstance(velocityField, uw.mesh.MeshVariable): raise TypeError( "Provided 'velocityField' must be of 'MeshVariable' class.") if velocityField.nodeDofCount != velocityField.mesh.dim: raise ValueError( "Provided 'velocityField' must be a vector field of same dimensionality as its mesh." ) self._velocityField = velocityField if not isinstance(pressureField, uw.mesh.MeshVariable): raise TypeError( "Provided 'pressureField' must be of 'MeshVariable' class.") if pressureField.nodeDofCount != 1: raise ValueError( "Provided 'pressureField' must be a scalar field (ie pressureField.nodeDofCount==1)." ) self._pressureField = pressureField if not fn_viscosity: raise ValueError( "You must specify a viscosity function via the 'fn_viscosity' parameter." ) _fn_viscosity = uw.function.Function._CheckIsFnOrConvertOrThrow( fn_viscosity) if not isinstance(_fn_viscosity, uw.function.Function): raise TypeError( "Provided 'fn_viscosity' must be of or convertible to 'Function' class." ) if not fn_bodyforce: if velocityField.mesh.dim == 2: fn_bodyforce = (0., 0.) else: fn_bodyforce = (0., 0., 0.) _fn_bodyforce = uw.function.Function._CheckIsFnOrConvertOrThrow( fn_bodyforce) if swarm and not isinstance(swarm, uw.swarm.Swarm): raise TypeError("Provided 'swarm' must be of 'Swarm' class.") self._swarm = swarm if not isinstance(conditions, (uw.conditions._SystemCondition, list, tuple)): raise TypeError( "Provided 'conditions' must be a list '_SystemCondition' objects." ) if len(conditions) > 1: raise ValueError( "Multiple conditions are not currently supported.") for cond in conditions: if not isinstance(cond, uw.conditions._SystemCondition): raise TypeError( "Provided 'conditions' must be a list '_SystemCondition' objects." ) # set the bcs on here.. will rearrange this in future. if cond.variable == self._velocityField: libUnderworld.StgFEM.FeVariable_SetBC( self._velocityField._cself, cond._cself) elif cond.variable == self._pressureField: libUnderworld.StgFEM.FeVariable_SetBC( self._pressureField._cself, cond._cself) else: raise ValueError( "Condition object does not appear to apply to the provided velocityField or pressureField." ) # ok, we've set some bcs, lets recreate eqnumbering libUnderworld.StgFEM._FeVariable_CreateNewEqnNumber( self._pressureField._cself) libUnderworld.StgFEM._FeVariable_CreateNewEqnNumber( self._velocityField._cself) self._conditions = conditions # create solutions vectors self._velocitySol = sle.SolutionVector(velocityField) self._pressureSol = sle.SolutionVector(pressureField) # create force vectors self._fvector = sle.AssembledVector(velocityField) self._hvector = sle.AssembledVector(pressureField) # and matrices self._kmatrix = sle.AssembledMatrix(velocityField, velocityField, rhs=self._fvector) self._gmatrix = sle.AssembledMatrix(velocityField, pressureField, rhs=self._fvector, rhs_T=self._hvector) self._preconditioner = sle.AssembledMatrix(pressureField, pressureField, rhs=self._hvector, allowZeroContrib=True) # create swarm self._gaussSwarm = uw.swarm.GaussIntegrationSwarm( self._velocityField.mesh) self._PICSwarm = None if self._swarm: self._PICSwarm = uw.swarm.PICIntegrationSwarm(self._swarm) self._PICSwarm.repopulate() # create assembly terms self._gradStiffMatTerm = sle.GradientStiffnessMatrixTerm( integrationSwarm=self._gaussSwarm, assembledObject=self._gmatrix) self._preCondMatTerm = sle.PreconditionerMatrixTerm( integrationSwarm=self._gaussSwarm, assembledObject=self._preconditioner) swarmguy = self._PICSwarm if not swarmguy: swarmguy = self._gaussSwarm self._constitMatTerm = sle.ConstitutiveMatrixTerm( integrationSwarm=swarmguy, assembledObject=self._kmatrix, fn=_fn_viscosity) self._forceVecTerm = sle.VectorAssemblyTerm_NA__Fn( integrationSwarm=swarmguy, assembledObject=self._fvector, fn=_fn_bodyforce) super(Stokes, self).__init__(**kwargs)
def __init__(self, velocityField, pressureField, fn_viscosity, fn_bodyforce=None, fn_lambda=None, voronoi_swarm=None, conditions=[], _removeBCs=True, _fn_viscosity2=None, _fn_director=None, _fn_stresshistory=None, **kwargs): if not isinstance(velocityField, uw.mesh.MeshVariable): raise TypeError( "Provided 'velocityField' must be of 'MeshVariable' class.") if velocityField.nodeDofCount != velocityField.mesh.dim: raise ValueError( "Provided 'velocityField' must be a vector field of same dimensionality as its mesh." ) self._velocityField = velocityField if not isinstance(pressureField, uw.mesh.MeshVariable): raise TypeError( "Provided 'pressureField' must be of 'MeshVariable' class.") if pressureField.nodeDofCount != 1: raise ValueError( "Provided 'pressureField' must be a scalar field (ie pressureField.nodeDofCount==1)." ) self._pressureField = pressureField _fn_viscosity = uw.function.Function.convert(fn_viscosity) if not isinstance(_fn_viscosity, uw.function.Function): raise TypeError( "Provided 'fn_viscosity' must be of or convertible to 'Function' class." ) if _fn_viscosity2: _fn_viscosity2 = uw.function.Function.convert(_fn_viscosity2) if not isinstance(_fn_viscosity2, uw.function.Function): raise TypeError( "Provided 'fn_viscosity2' must be of or convertible to 'Function' class." ) if not isinstance(_removeBCs, bool): raise TypeError("Provided '_removeBCs' must be of type bool.") self._removeBCs = _removeBCs if _fn_director: _fn_director = uw.function.Function.convert(_fn_director) if not isinstance(_fn_director, uw.function.Function): raise TypeError( "Provided 'fn_director' must be of or convertible to 'Function' class." ) if _fn_stresshistory: _fn_stresshistory = uw.function.Function.convert(_fn_stresshistory) if not isinstance(_fn_stresshistory, uw.function.Function): raise TypeError( "Provided '_fn_stresshistory' must be of or convertible to 'Function' class." ) if fn_lambda != None: fn_lambda = uw.function.Function.convert(fn_lambda) if not isinstance(fn_lambda, uw.function.Function): raise ValueError( "Provided 'fn_lambda' must be of, or convertible to, the 'Function' class." ) if not fn_bodyforce: if velocityField.mesh.dim == 2: fn_bodyforce = (0., 0.) else: fn_bodyforce = (0., 0., 0.) _fn_bodyforce = uw.function.Function.convert(fn_bodyforce) if voronoi_swarm and not isinstance(voronoi_swarm, uw.swarm.Swarm): raise TypeError( "Provided 'voronoi_swarm' must be of 'Swarm' class.") self._swarm = voronoi_swarm if voronoi_swarm and velocityField.mesh.elementType == 'Q2': import warnings warnings.warn( "Voronoi integration may yield unsatisfactory results for Q2 mesh." ) mesh = velocityField.mesh if not isinstance(conditions, (list, tuple)): conditionslist = [] conditionslist.append(conditions) conditions = conditionslist for cond in conditions: # set the bcs on here if not isinstance(cond, uw.conditions.SystemCondition): raise TypeError( "Provided 'conditions' must be 'SystemCondition' objects.") elif type(cond) == uw.conditions.DirichletCondition: if cond.variable == self._velocityField: libUnderworld.StgFEM.FeVariable_SetBC( self._velocityField._cself, cond._cself) if cond.variable == self._pressureField: libUnderworld.StgFEM.FeVariable_SetBC( self._pressureField._cself, cond._cself) self._conditions = conditions self._eqNums = dict() self._eqNums[velocityField] = sle.EqNumber(self._velocityField, self._removeBCs) self._eqNums[pressureField] = sle.EqNumber(self._pressureField, self._removeBCs) # create solutions vectors and load fevariable values onto them for best first guess self._velocitySol = sle.SolutionVector(velocityField, self._eqNums[velocityField]) self._pressureSol = sle.SolutionVector(pressureField, self._eqNums[pressureField]) libUnderworld.StgFEM.SolutionVector_LoadCurrentFeVariableValuesOntoVector( self._velocitySol._cself) libUnderworld.StgFEM.SolutionVector_LoadCurrentFeVariableValuesOntoVector( self._pressureSol._cself) # create force vectors self._fvector = sle.AssembledVector(velocityField, self._eqNums[velocityField]) self._hvector = sle.AssembledVector(pressureField, self._eqNums[pressureField]) # and matrices self._kmatrix = sle.AssembledMatrix(self._velocitySol, self._velocitySol, rhs=self._fvector) self._gmatrix = sle.AssembledMatrix(self._velocitySol, self._pressureSol, rhs=self._fvector, rhs_T=self._hvector) self._preconditioner = sle.AssembledMatrix(self._pressureSol, self._pressureSol, rhs=self._hvector) if fn_lambda != None: self._mmatrix = sle.AssembledMatrix(self._pressureSol, self._pressureSol, rhs=self._hvector) # create assembly terms which always use gauss integration gaussSwarm = uw.swarm.GaussIntegrationSwarm(self._velocityField.mesh) self._gradStiffMatTerm = sle.GradientStiffnessMatrixTerm( integrationSwarm=gaussSwarm, assembledObject=self._gmatrix) self._preCondMatTerm = sle.PreconditionerMatrixTerm( integrationSwarm=gaussSwarm, assembledObject=self._preconditioner) # for the following terms, we will use voronoi if that has been requested # by the user, else use gauss again. intswarm = gaussSwarm if self._swarm: intswarm = self._swarm._voronoi_swarm # need to ensure voronoi is populated now, as assembly terms will call # initial test functions which may require a valid voronoi swarm self._swarm._voronoi_swarm.repopulate() self._constitMatTerm = sle.ConstitutiveMatrixTerm( integrationSwarm=intswarm, assembledObject=self._kmatrix, fn_visc1=_fn_viscosity, fn_visc2=_fn_viscosity2, fn_director=_fn_director) self._forceVecTerm = sle.VectorAssemblyTerm_NA__Fn( integrationSwarm=intswarm, assembledObject=self._fvector, fn=_fn_bodyforce) for cond in self._conditions: if isinstance(cond, uw.conditions.NeumannCondition): #NOTE many NeumannConditions can be used but the _sufaceFluxTerm only records the last self._surfaceFluxTerm = sle.VectorSurfaceAssemblyTerm_NA__Fn__ni( assembledObject=self._fvector, surfaceGaussPoints= 3, # increase to resolve stress bc fluctuations nbc=cond) if fn_lambda != None: # some logic for constructing the lower-right [2,2] matrix in the stokes system # [M] = [Na * 1.0/fn_lambda * Nb], where in our formulation Na and Nb are the pressure shape functions. # see 4.3.21 of Hughes, Linear static and dynamic finite element analysis # If fn_lambda is negligable, ie <1.0e-8, then we set the entry to 0.0, ie, incompressible # otherwise we provide 1.0/lambda to [M] logicFn = uw.function.branching.conditional([(fn_lambda > 1.0e-8, 1.0 / fn_lambda), (True, 0.)]) self._compressibleTerm = sle.MatrixAssemblyTerm_NA__NB__Fn( integrationSwarm=intswarm, assembledObject=self._mmatrix, mesh=self._velocityField.mesh, fn=logicFn) if _fn_stresshistory != None: self._vepTerm = sle.VectorAssemblyTerm_VEP__Fn( integrationSwarm=intswarm, assembledObject=self._fvector, fn=_fn_stresshistory) super(Stokes, self).__init__(**kwargs)