Source code for sfepy.discrete.conditions

"""
The Dirichlet, periodic and linear combination boundary condition
classes, as well as the initial condition class.
"""
from __future__ import absolute_import
import numpy as nm

from sfepy.base.base import basestr, Container, Struct, is_sequence
from sfepy.discrete.functions import Function
import six

[docs] def get_condition_value(val, functions, kind, name): """ Check a boundary/initial condition value type and return the value or corresponding function. """ if type(val) == str: if functions is not None: try: fun = functions[val] except IndexError: raise ValueError('unknown function %s given for %s %s!' % (val, kind, name)) else: raise ValueError('no functions given for %s %s!' % (kind, name)) elif (isinstance(val, Function) or nm.isscalar(val) or isinstance(val, nm.ndarray)): fun = val elif is_sequence(val): fun = nm.array(val) else: raise ValueError('unknown value type for %s %s!' % (kind, name)) return fun
def _get_region(name, regions, bc_name): try: region = regions[name] except IndexError: msg = "no region '%s' used in condition %s!" % (name, bc_name) raise IndexError(msg) return region
[docs] class Conditions(Container): """ Container for various conditions. """
[docs] @staticmethod def from_conf(conf, regions): conds = [] for key, cc in six.iteritems(conf): times = cc.get('times', None) if key.startswith("ebc"): region = _get_region(cc.region, regions, cc.name) cond = EssentialBC(cc.name, region, cc.dofs, key=key, times=times) elif key.startswith("epbc"): rs = [_get_region(ii, regions, cc.name) for ii in cc.region] cond = PeriodicBC(cc.name, rs, cc.dofs, cc.match, key=key, times=times) elif key.startswith('lcbc'): if isinstance(cc.region, basestr): rs = [_get_region(cc.region, regions, cc.name), None] else: rs = [_get_region(ii, regions, cc.name) for ii in cc.region] cond = LinearCombinationBC(cc.name, rs, cc.dofs, cc.dof_map_fun, cc.kind, key=key, times=times, arguments=cc.get('arguments', None)) elif key.startswith('dgebc'): region = _get_region(cc.region, regions, cc.name) cond = DGEssentialBC(cc.name, region, cc.dofs, key=key, times=times) elif key.startswith('dgepbc'): rs = [_get_region(ii, regions, cc.name) for ii in cc.region] cond = DGPeriodicBC(cc.name, rs, cc.dofs, cc.match, key=key, times=times) elif 'ic' in key: region = _get_region(cc.region, regions, cc.name) cond = InitialCondition(cc.name, region, cc.dofs, key=key) else: raise ValueError('unknown condition type! (%s)' % key) conds.append(cond) obj = Conditions(conds) return obj
[docs] def group_by_variables(self, groups=None): """ Group boundary conditions of each variable. Each condition is a group is a single condition. Parameters ---------- groups : dict, optional If present, update the `groups` dictionary. Returns ------- out : dict The dictionary with variable names as keys and lists of single condition instances as values. """ if groups is None: out = {} else: out = groups for cond in self: for single_cond in cond.iter_single(): vname = single_cond.dofs[0].split('.')[0] out.setdefault(vname, Conditions()).append(single_cond) return out
[docs] def canonize_dof_names(self, dofs): """ Canonize the DOF names using the full list of DOFs of a variable. """ for cond in self: cond.canonize_dof_names(dofs)
[docs] def sort(self): """ Sort boundary conditions by their key. """ self._objs.sort(key=lambda a: a.key) self.update()
[docs] def zero_dofs(self): """ Set all boundary condition values to zero, if applicable. """ for cond in self: if isinstance(cond, EssentialBC): cond.zero_dofs()
def _canonize(dofs, all_dofs): """ Helper function. """ vname, dd = dofs.split('.') if dd == 'all': cdofs = all_dofs elif dd[0] == '[': cdofs = [vname + '.' + ii.strip() for ii in dd[1:-1].split(',')] else: cdofs = [dofs] return cdofs
[docs] class Condition(Struct): """ Common boundary condition methods. """ def __init__(self, name, **kwargs): Struct.__init__(self, name=name, **kwargs) self.is_single = False
[docs] def iter_single(self): """ Create a single condition instance for each item in self.dofs and yield it. """ for dofs, val in six.iteritems(self.dofs): single_cond = self.copy(name=self.name) single_cond.is_single = True if 'grad' in dofs: # extract variable name from grad.<var-name>.all dofs dofs = ".".join((dofs.split(".")[1:])) # mark condition as diff single_cond.diff = 1 single_cond.dofs = [dofs, val] yield single_cond
[docs] def canonize_dof_names(self, dofs): """ Canonize the DOF names using the full list of DOFs of a variable. Assumes single condition instance. """ self.dofs[0] = _canonize(self.dofs[0], dofs)
[docs] class EssentialBC(Condition): """ Essential boundary condidion. Parameters ---------- name : str The boundary condition name. region : Region instance The region where the boundary condition is applied. dofs : dict The boundary condition specification defining the constrained DOFs and their values. key : str, optional The sorting key. times : list or str, optional The list of time intervals or a function returning True at time steps, when the condition applies. """ def __init__(self, name, region, dofs, key='', times=None): Condition.__init__(self, name=name, region=region, dofs=dofs, key=key, times=times)
[docs] def zero_dofs(self): """ Set all essential boundary condition values to zero. """ if self.is_single: self.dofs[1] = 0.0 else: new_dofs = {} for key in six.iterkeys(self.dofs): new_dofs[key] = 0.0 self.dofs = new_dofs
[docs] class PeriodicBC(Condition): """ Periodic boundary condidion. Parameters ---------- name : str The boundary condition name. regions : list of two Region instances The master region and the slave region where the DOFs should match. dofs : dict The boundary condition specification defining the DOFs in the master region and the corresponding DOFs in the slave region. match : str The name of function for matching corresponding nodes in the two regions. key : str, optional The sorting key. times : list or str, optional The list of time intervals or a function returning True at time steps, when the condition applies. """ def __init__(self, name, regions, dofs, match, key='', times=None): Condition.__init__(self, name=name, regions=regions, dofs=dofs, match=match, key=key, times=times)
[docs] def canonize_dof_names(self, dofs): """ Canonize the DOF names using the full list of DOFs of a variable. Assumes single condition instance. """ self.dofs[0] = _canonize(self.dofs[0], dofs) self.dofs[1] = _canonize(self.dofs[1], dofs)
[docs] class DGPeriodicBC(PeriodicBC): """ This class is empty, it serves the same purpose as PeriodicBC, and is created only for branching in dof_info.py """ pass
[docs] class DGEssentialBC(EssentialBC): """ This class is empty, it serves the same purpose as EssentialBC, and is created only for branching in dof_info.py """ def __init__(self, *args, diff=0, **kwargs): EssentialBC.__init__(self, *args, **kwargs) self.diff = diff
[docs] class LinearCombinationBC(Condition): """ Linear combination boundary condidion. Parameters ---------- name : str The boundary condition name. regions : list of two Region instances The constrained (master) DOFs region and the new (slave) DOFs region. The latter can be None if new DOFs are not field variable DOFs. dofs : dict The boundary condition specification defining the constrained DOFs and the new DOFs (can be None). dof_map_fun : str The name of function for mapping the constrained DOFs to new DOFs (can be None). kind : str The linear combination condition kind. key : str, optional The sorting key. times : list or str, optional The list of time intervals or a function returning True at time steps, when the condition applies. arguments: tuple, optional Additional arguments, depending on the condition kind. """ def __init__(self, name, regions, dofs, dof_map_fun, kind, key='', times=None, arguments=None): Condition.__init__(self, name=name, regions=regions, dofs=dofs, dof_map_fun=dof_map_fun, kind=kind, key=key, times=times, arguments=arguments)
[docs] def get_var_names(self): """ Get names of variables corresponding to the constrained and new DOFs. """ names = [self.dofs[0].split('.')[0]] if self.dofs[1] is not None: names.append(self.dofs[1].split('.')[0]) return names
[docs] def canonize_dof_names(self, dofs0, dofs1=None): """ Canonize the DOF names using the full list of DOFs of a variable. Assumes single condition instance. """ self.dofs[0] = _canonize(self.dofs[0], dofs0) if self.dofs[1] is not None: self.dofs[1] = _canonize(self.dofs[1], dofs1)
[docs] class InitialCondition(Condition): """ Initial condidion. Parameters ---------- name : str The initial condition name. region : Region instance The region where the initial condition is applied. dofs : dict The initial condition specification defining the constrained DOFs and their values. key : str, optional The sorting key. """ def __init__(self, name, region, dofs, key=''): Condition.__init__(self, name=name, region=region, dofs=dofs, key=key)