diff --git a/hysop/backend/host/python/operator/penalization.py b/hysop/backend/host/python/operator/penalization.py index dedb44151c37570533c68aead17714fa7f614af5..c11f92a9ce09412076fcc822c7f119255ce32b3c 100644 --- a/hysop/backend/host/python/operator/penalization.py +++ b/hysop/backend/host/python/operator/penalization.py @@ -1,8 +1,10 @@ +from hysop.constants import PenalizationFormulation from hysop.backend.host.host_operator import HostOperator from hysop.tools.types import check_instance, InstanceOf from hysop.tools.decorators import debug from hysop.fields.continuous_field import Field from hysop.parameters.scalar_parameter import ScalarParameter +from hysop.parameters.tensor_parameter import TensorParameter from hysop.topology.cartesian_descriptor import CartesianTopologyDescriptors from hysop.methods import SpaceDiscretization from hysop.core.memory.memory_request import MemoryRequest @@ -28,6 +30,7 @@ class PythonPenalizeVorticity(HostOperator): dm = super(PythonPenalizeVorticity, cls).default_method() dm.update(cls.__default_method) return dm + @classmethod def available_methods(cls): am = super(PythonPenalizeVorticity, cls).available_methods() @@ -37,15 +40,17 @@ class PythonPenalizeVorticity(HostOperator): @debug def __init__(self, obstacles, variables, velocity, vorticity, - dt, coeff=None, **kwds): + dt, coeff=None, ubar=None, formulation=None, **kwds): check_instance(velocity, Field) check_instance(vorticity, Field) check_instance(variables, dict, keys=Field, values=CartesianTopologyDescriptors) check_instance(dt, ScalarParameter) - check_instance(coeff, (ScalarParameter, float, type(lambda x:x))) + check_instance(coeff, (ScalarParameter, float, type(lambda x: x)), allow_none=True) + check_instance(ubar, TensorParameter, allow_none=True) + check_instance(formulation, PenalizationFormulation, allow_none=True) check_instance(obstacles, (tuple, dict), values=Field, - keys=(ScalarParameter, float), check_kwds=False) + keys=(ScalarParameter, float, type(lambda x: x)), check_kwds=False) input_fields = {velocity: variables[velocity], vorticity: variables[vorticity]} @@ -54,14 +59,22 @@ class PythonPenalizeVorticity(HostOperator): if isinstance(coeff, ScalarParameter): self.coeff = lambda o: coeff()*o - if isinstance(coeff, type(lambda x:x)): + elif isinstance(coeff, type(lambda x: x)): self.coeff = coeff - else: + elif not coeff is None: c = ScalarParameter("penal_coeff", initial_value=coeff) self.coeff = lambda o: c()*o if isinstance(obstacles, dict): - obs = obstacles + obs = {} + for c, o in obstacles.iteritems(): + if isinstance(c, ScalarParameter): + obs[lambda x: c()*x] = o + elif isinstance(c, type(lambda x: x)): + obs[c] = o + elif not c is None: + _ = ScalarParameter("penal_coeff", initial_value=c) + obs[lambda x: _()*x] = o else: obs = {} for o in obstacles: @@ -69,6 +82,16 @@ class PythonPenalizeVorticity(HostOperator): for o in obs.values(): assert o.nb_components == 1 input_fields[o] = variables[o] + self._ubar = ubar + if ubar is None: + self._ubar = TensorParameter( + name="ubar", shape=(velocity.dim,), + quiet=True, dtype=velocity.dtype, + initial_value=(0.,)*velocity.dim) + if formulation is None or formulation is PenalizationFormulation.IMPLICIT: + self._compute_penalization = self._compute_penalization_implicit + else: + self._compute_penalization = self._compute_penalization_exact self.velocity = velocity self.vorticity = vorticity @@ -94,7 +117,8 @@ class PythonPenalizeVorticity(HostOperator): @debug def get_field_requirements(self): - requirements = super(PythonPenalizeVorticity, self).get_field_requirements() + requirements = super(PythonPenalizeVorticity, + self).get_field_requirements() stencil = self.stencil[0] G = max(max(a, b) for a, b in zip(stencil.L, stencil.R)) for is_input, (field, td, req) in requirements.iter_requirements(): @@ -122,16 +146,18 @@ class PythonPenalizeVorticity(HostOperator): self.dobstacles = {} for c, o in self.obstacles.iteritems(): o_df = self.input_discrete_fields[o] - self.dobstacles[c] = o_df.data[0][o_df.local_slices(ghosts=(G, G, G))] + self.dobstacles[c] = o_df.data[0][o_df.local_slices( + ghosts=(G, G, G))] for s, dx in zip(self.stencil, dw.space_step): s.replace_symbols({s.dx: dx}) - self.ghost_exchanger = dw.build_ghost_exchanger() + self.w_ghost_exchanger = dw.build_ghost_exchanger() + self.v_ghost_exchanger = dv.build_ghost_exchanger() @debug def get_work_properties(self): - requests = super(PythonPenalizeVorticity, self).get_work_properties() + requests = super(PythonPenalizeVorticity, self).get_work_properties() buffers = MemoryRequest.empty_like( a=self.V[0], nb_components=4, backend=self.dvelocity.backend) requests.push_mem_request('Wtmp', buffers) @@ -151,18 +177,29 @@ class PythonPenalizeVorticity(HostOperator): def supports_mpi(cls): return True + def _compute_penalization_implicit(self): + dt = self.dt() + self.tmp[...] = 0. + for c, o in self.dobstacles.iteritems(): + self.tmp[...] += (-dt) * c(o) / (1.0 + dt * c(o)) + + def _compute_penalization_exact(self): + dt = self.dt() + self.tmp[...] = 1. + for c, o in self.dobstacles.iteritems(): + self.tmp[...] *= np.exp(-dt*c(o)) + self.tmp[...] -= 1. + @op_apply def apply(self, **kwds): super(PythonPenalizeVorticity, self).apply(**kwds) - dt = self.dt() V, W = self.V, self.W + self.v_ghost_exchanger() - # Penalize velocity - self.tmp[...] = 0. - for c, o in self.dobstacles.iteritems(): - self.tmp[...] += - dt * c(o) / (1.0 + dt * c(o)) - for v, tmp in zip(V, self.tmp_v): - tmp[...] = v * self.tmp + # # Penalize velocity + self._compute_penalization() + for ubar, v, tmp in zip(self._ubar(), V, self.tmp_v): + tmp[...] = (v - ubar) * self.tmp # compute penalized vorticity: # (dvz/dy - dvy/dz) @@ -186,4 +223,4 @@ class PythonPenalizeVorticity(HostOperator): self.tmp = self.stencil[2](a=self.tmp_v[0], out=self.tmp, axis=0) W[1][...] += self.tmp - self.ghost_exchanger() + self.w_ghost_exchanger() diff --git a/hysop/constants.py.in b/hysop/constants.py.in index cf9c1aeaf7b6d58b88cf5dfff284575386c3e5fb..12742767f0ac49b3c26b960e184f43b156577998 100644 --- a/hysop/constants.py.in +++ b/hysop/constants.py.in @@ -189,6 +189,11 @@ StretchingFormulation = EnumFactory.create('StretchingFormulation', ['GRAD_UW', 'GRAD_UW_T', 'MIXED_GRAD_UW', 'CONSERVATIVE']) """Stretching formulations""" +PenalizationFormulation = EnumFactory.create( + 'PenalizationFormulation', + ['IMPLICIT', 'EXACT']) +"""Penalization formulations""" + SpaceDiscretization = EnumFactory.create('SpaceDiscretization', ['FDC2', 'FDC4', 'FDC6', 'FDC8']) """Space discretization for stencil generation""" diff --git a/hysop/operator/penalization.py b/hysop/operator/penalization.py index f829168b17439c0a4e30df996524d28eb06405ea..94d750e7392f588948447ad1f053fdb54d3541c4 100644 --- a/hysop/operator/penalization.py +++ b/hysop/operator/penalization.py @@ -7,12 +7,13 @@ See details in :ref:`penalisation` section of HySoP user guide. """ -from hysop.constants import Implementation +from hysop.constants import Implementation, PenalizationFormulation from hysop.tools.types import check_instance, to_list from hysop.tools.decorators import debug from hysop.fields.continuous_field import Field from hysop.topology.cartesian_descriptor import CartesianTopologyDescriptors from hysop.parameters.scalar_parameter import ScalarParameter +from hysop.parameters.tensor_parameter import TensorParameter from hysop.core.graph.computational_node_frontend import ComputationalGraphNodeFrontend from hysop.backend.host.python.operator.penalization import PythonPenalizeVorticity @@ -26,7 +27,7 @@ class PenalizeVorticity(ComputationalGraphNodeFrontend): using penalization. """ __implementations = { - Implementation.PYTHON: PythonPenalizeVorticity + Implementation.PYTHON: PythonPenalizeVorticity } @classmethod @@ -40,7 +41,7 @@ class PenalizeVorticity(ComputationalGraphNodeFrontend): @debug def __init__(self, obstacles, variables, velocity, vorticity, - dt, coeff=None, + dt, coeff=None, ubar=None, formulation=None, implementation=None, **kwds): """ Parameters @@ -53,6 +54,10 @@ class PenalizeVorticity(ComputationalGraphNodeFrontend): output vorticity coeff : ScalarParameter, optional penalization factor (\f\lambda\f) applied to all geometries. + ubar : TensorParameter, optional + Solid velocity (default to 0) + formulation: PenalizationFormulation + Solving penalization either with IMPLICIT scheme or EXACT solution variables: dict dictionary of fields as keys and topologies as values. dt: ScalarParameter @@ -82,24 +87,29 @@ class PenalizeVorticity(ComputationalGraphNodeFrontend): Warning : coeff as a function is not yet implemented!! """ - obstacles = to_list(obstacles) - assert len(set(obstacles)) == len(obstacles) - obstacles = tuple(obstacles) + if not isinstance(obstacles, dict): + obstacles = to_list(obstacles) + assert len(set(obstacles)) == len(obstacles) + obstacles = tuple(obstacles) check_instance(velocity, Field) check_instance(vorticity, Field) check_instance(variables, dict, keys=Field, values=CartesianTopologyDescriptors) check_instance(dt, ScalarParameter) - check_instance(coeff, (ScalarParameter, float, type(lambda x:x)), allow_none=True) + check_instance(coeff, (ScalarParameter, float, type(lambda x: x)), allow_none=True) + check_instance(formulation, PenalizationFormulation, allow_none=True) + check_instance(ubar, TensorParameter, allow_none=True) check_instance(obstacles, (tuple, dict), values=Field, - keys=(ScalarParameter, float), check_kwds=False) + keys=(ScalarParameter, float, type(lambda x: x)), check_kwds=False) super(PenalizeVorticity, self).__init__( velocity=velocity, vorticity=vorticity, coeff=coeff, + ubar=ubar, obstacles=obstacles, dt=dt, + formulation=formulation, variables=variables, implementation=implementation, **kwds)