Source code for underworld.conditions._conditions

##~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~##
##                                                                                   ##
##  This file forms part of the Underworld geophysics modelling application.         ##
##                                                                                   ##
##  For full license and copyright information, please refer to the LICENSE.md file  ##
##  located at the project root, or contact the authors.                             ##
##                                                                                   ##
##~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~#~##
"""
This module contains conditions used for applying constraints on model dynamics.
"""

import underworld as uw
import underworld._stgermain as _stgermain
import underworld.libUnderworld as libUnderworld
import abc

[docs]class SystemCondition(_stgermain.StgCompoundComponent, metaclass = abc.ABCMeta): def _add_to_stg_dict(self,componentDict): pass def __init__(self, variable, indexSetsPerDof): if not isinstance( variable, uw.mesh.MeshVariable ): raise TypeError("Provided variable must be of class 'MeshVariable'.") self._variable = variable if isinstance( indexSetsPerDof, uw.container.IndexSet ): indexSets = ( indexSetsPerDof, ) elif isinstance( indexSetsPerDof, (list,tuple)): indexSets = indexSetsPerDof else: raise TypeError("You must provide the required 'indexSetsPerDof' item\n"+ "as a list or tuple of 'IndexSet' items.") for guy in indexSets: if not isinstance( guy, (uw.container.IndexSet,type(None)) ): raise TypeError("Provided list must only contain objects of 'NoneType' or type 'IndexSet'.") self._indexSets = indexSets if variable.nodeDofCount != len(self._indexSets): raise ValueError("Provided variable has a nodeDofCount of {}, however you have ".format(variable.nodeDofCount)+ "provided {} index set(s). You must provide an index set for each degree ".format(len(self._indexSets))+ "of freedom of your variable, but no more.") # ok, lets setup the c array libUnderworld.StGermain._PythonVC_SetupIndexSetArray(self._cself,len(self._indexSets)) # now, lets add the indexSet objects for position,set in enumerate(self._indexSets): if set: libUnderworld.StGermain._PythonVC_SetIndexSetAtArrayPosition( self._cself, set._cself, position ); @property def indexSetsPerDof(self): """ See class constructor for details. """ return self._indexSets @property def variable(self): """ See class constructor for details. """ return self._variable
[docs]class DirichletCondition(SystemCondition): """ The DirichletCondition class provides the required functionality to imposed Dirichlet conditions on your differential equation system. The user is simply required to flag which nodes/DOFs should be considered by the system to be a Dirichlet condition. The values at the Dirichlet nodes/DOFs is then left untouched by the system. Parameters ---------- variable : underworld.mesh.MeshVariable This is the variable for which the Dirichlet condition applies. indexSetsPerDof : list, tuple, IndexSet The index set(s) which flag nodes/DOFs as Dirichlet conditions. Note that the user must provide an index set for each degree of freedom of the variable. So for a vector variable of rank 2 (say Vx & Vy), two index sets must be provided (say VxDofSet, VyDofSet). Notes ----- Note that it is necessary for the user to set the required value on the variable, possibly via the numpy interface. Constructor must be called collectively all processes. Example ------- Basic setup and usage of Dirichlet conditions: >>> linearMesh = uw.mesh.FeMesh_Cartesian( elementType='Q1/dQ0', elementRes=(4,4), minCoord=(0.,0.), maxCoord=(1.,1.) ) >>> velocityField = uw.mesh.MeshVariable( linearMesh, 2 ) >>> velocityField.data[:] = [0.,0.] # set velocity zero everywhere, which will of course include the boundaries. >>> IWalls = linearMesh.specialSets["MinI_VertexSet"] + linearMesh.specialSets["MaxI_VertexSet"] # get some wall index sets >>> JWalls = linearMesh.specialSets["MinJ_VertexSet"] + linearMesh.specialSets["MaxJ_VertexSet"] >>> freeSlipBC = uw.conditions.DirichletCondition(velocityField, (IWalls,JWalls) ) # this will give free slip sides >>> noSlipBC = uw.conditions.DirichletCondition(velocityField, (IWalls+JWalls,IWalls+JWalls) ) # this will give no slip sides """ _objectsDict = { "_pyvc": "PythonVC" } _selfObjectName = "_pyvc" def __init__(self, variable, indexSetsPerDof): super(DirichletCondition,self).__init__(variable, indexSetsPerDof)
[docs]class NeumannCondition(SystemCondition): """ This class defines Neumann conditions for a differential equation. Neumann conditions specifiy a field's flux along a boundary. As such the user specifices the field's flux as a uw.Function and the nodes where this flux is to be applied - similar to uw.conditions.DirichletCondtion Parameters ---------- fn_flux : underworld.function.Function Function which determines flux values. variable : underworld.mesh.MeshVariable The variable that describes the discretisation (mesh & DOFs) for 'indexSetsPerDof' indexSetsPerDof : list, tuple, IndexSet The index set(s) which flag nodes/DOFs as Neumann conditions. Note that the user must provide an index set for each degree of freedom of the variable above. So for a vector variable of rank 2 (say Vx & Vy), two index sets must be provided (say VxDofSet, VyDofSet). Example ------- Basic setup and usage of Neumann conditions: >>> linearMesh = uw.mesh.FeMesh_Cartesian( elementType='Q1/dQ0', elementRes=(4,4), minCoord=(0.,0.), maxCoord=(1.,1.) ) >>> velocityField = uw.mesh.MeshVariable( linearMesh, 2 ) >>> velocityField.data[:] = [0.,0.] # set velocity zero everywhere, which will of course include the boundaries. >>> myFunc = (uw.function.coord()[1],0.0) >>> bottomWall = linearMesh.specialSets["MinJ_VertexSet"] >>> tractionBC = uw.conditions.NeumannCondition(variable=velocityField, fn_flux=myFunc, indexSetsPerDof=(None,bottomWall) ) """ _objectsDict = { "_pyvc": "PythonVC" } _selfObjectName = "_pyvc" def __init__(self, variable, indexSetsPerDof=None, fn_flux=None ): # call parent super(NeumannCondition,self).__init__(variable, indexSetsPerDof) _fn_flux = uw.function.Function.convert(fn_flux) if not isinstance( _fn_flux, uw.function.Function): raise TypeError( "Provided 'fn_flux' must be of or convertible to 'Function' class." ) self.fn_flux=_fn_flux @property def fn_flux(self): """ Get the underworld.Function that defines the flux """ return self._fn_flux @fn_flux.setter def fn_flux(self, fn): """ Set the underworld.Function that defines the flux """ _fn = uw.function.Function.convert(fn) if not isinstance( _fn, uw.function.Function): raise ValueError( "Provided '_fn' must be of or convertible to 'Function' class." ) self._fn_flux = _fn