diff --git a/hysop/constants.py.in b/hysop/constants.py.in index 12742767f0ac49b3c26b960e184f43b156577998..21923e645f8f021dd1380abb2cc4a048b3726090 100644 --- a/hysop/constants.py.in +++ b/hysop/constants.py.in @@ -146,9 +146,25 @@ BoundaryCondition = EnumFactory.create('BoundaryCondition', 'HOMOGENEOUS_NEUMANN', 'HOMOGENEOUS_DIRICHLET', 'NEUMANN', 'DIRICHLET' ]) """Boundary conditions enum""" + +class BoundaryConditionConfig(object): + def __init__(self, bc, data=None): + assert isinstance(bc, BoundaryCondition), type(bc) + self.bc = bc + self.data = data + def __str__(self): + return bc.__str__()[:-1] + ', {})'.format(self.data) + def __repr__(self): + return bc.__repr__()[:-1] + ', {})'.format(self.data) +for bc in BoundaryCondition.fields(): + bc = getattr(BoundaryCondition, bc) + bc.bc = bc + bc.bind_data = lambda data, bc=bc: BoundaryConditionConfig(bc=bc, data=data) def boundary2str(b): """Helper function to convert a BoundaryCondition to a short string.""" + if isinstance(b, BoundaryConditionConfig): + b = b.bc sstr = { BoundaryCondition.NONE: 'NONE', BoundaryCondition.MIXED: 'MIXED', diff --git a/hysop/fields/ghost_exchangers.py b/hysop/fields/ghost_exchangers.py index 57d2125e78b4cf240a8a0c5acb780b93a87e7914..66ecc18ad97f524792528c17e7fcd9ad46a5cbc2 100644 --- a/hysop/fields/ghost_exchangers.py +++ b/hysop/fields/ghost_exchangers.py @@ -12,9 +12,9 @@ from hysop.core.mpi import MPI from hysop.core.mpi.topo_tools import TopoTools from hysop.backend.device.opencl import cl, clArray from hysop.backend.device.opencl.opencl_kernel_launcher import HostLauncherI -from hysop.constants import BoundaryCondition +from hysop.constants import BoundaryCondition, BoundaryConditionConfig -GHOST_EXCHANGE_DEBUG_LEVEL=2 +GHOST_EXCHANGE_DEBUG_LEVEL=0 def gprint(*args, **kwds): level = kwds.pop('level', 2) if GHOST_EXCHANGE_DEBUG_LEVEL >= level: @@ -97,6 +97,13 @@ class LocalBoundaryExchanger(object): H = (0,)+(-1,)*(S-1) return cls.build_exchanger(shape=shape, direction=direction, H=H, to_left=to_left) + + @classmethod + def build_scalar_exchanger(cls, value, shape, direction, to_left): + def exchange_ghosts(X, value=value): + assert (X is not None) + X[...] = value + return exchange_ghosts class GhostExchangerI(object): @@ -412,13 +419,27 @@ class CartesianDiscreteFieldGhostExchanger(GhostExchanger): def setup(self): local_symmetries = [] for ls in self.local_symmetries: - (buf, slices, shape, d, to_left, bc) = ls + (buf, slices, shape, d, to_left, boundary) = ls + bc = boundary.bc if (bc is BoundaryCondition.HOMOGENEOUS_DIRICHLET): - fn = LocalBoundaryExchanger.build_antisymmetric_exchanger( - shape=shape, direction=d, to_left=to_left) + if isinstance(boundary, BoundaryConditionConfig) and (boundary.data is not None): + msg='Boundary of type HOMOGENEOUS_DIRICHLET does not handle custom boundary data, got {}.' + raise RuntimeError(msg, type(boundary.data).__name__) + else: + fn = LocalBoundaryExchanger.build_antisymmetric_exchanger( + shape=shape, direction=d, to_left=to_left) elif (bc is BoundaryCondition.HOMOGENEOUS_NEUMANN): - fn = LocalBoundaryExchanger.build_symmetric_exchanger( - shape=shape, direction=d, to_left=to_left) + if isinstance(boundary, BoundaryConditionConfig) and (boundary.data is not None): + # allow to force boundary ghosts to a specific scalar value + if isinstance(boundary.data, (int,long,float,np.number)): + fn = LocalBoundaryExchanger.build_scalar_exchanger(value=boundary.data, + shape=shape, direction=d, to_left=to_left) + else: + msg='Boundary of type HOMOGENEOUS_NEUMANN only handle custom scalar boundary data, got {}.' + raise RuntimeError(msg, type(boundary.data).__name__) + else: + fn = LocalBoundaryExchanger.build_symmetric_exchanger( + shape=shape, direction=d, to_left=to_left) else: msg='Unknown boundary condition {}.'.format(bc) local_symmetries.append((fn, buf, slices, shape, d, to_left, bc)) @@ -536,12 +557,10 @@ class CartesianDiscreteFieldGhostExchanger(GhostExchanger): if not should_exchange_to_left: glboundary = global_lboundaries_config[d] if (global_lboundaries_config is not None) else lboundary assert glboundary.bc is lboundary - print(glboundary) lp.local_symmetries.append((buf, left_boundary_layer, bl_shape, d, 1, glboundary)) if not should_exchange_to_right: grboundary = global_rboundaries_config[d] if (global_rboundaries_config is not None) else rboundary assert grboundary.bc is rboundary - print(grboundary) lp.local_symmetries.append((buf, right_boundary_layer, bl_shape, d, 0, grboundary)) if (nprocs == 1): diff --git a/hysop/operator/tests/test_spectral_derivative.py b/hysop/operator/tests/test_spectral_derivative.py index a02ae7c9aa9b56a80578fed5e7f8ca5898afabcc..c4b5ff01531db8199579f685634d7b140cf4652b 100644 --- a/hysop/operator/tests/test_spectral_derivative.py +++ b/hysop/operator/tests/test_spectral_derivative.py @@ -274,7 +274,7 @@ class TestSpectralDerivative(object): except OverflowError: import numpy as np deps = np.inf - if (deps <= 2*10**(nidx+2)): + if (deps <= 5*10**(nidx+2)): if (j == 1): print '{}eps ({})'.format(deps, dinf), else: diff --git a/hysop_examples/examples/particles_above_salt/particles_above_salt_bc.py b/hysop_examples/examples/particles_above_salt/particles_above_salt_bc.py index 2ff3d1500b2dea8d30cae1698f7ae548a1f8c4d4..1229af4ad6744acea13a2da06364c028e4163314 100644 --- a/hysop_examples/examples/particles_above_salt/particles_above_salt_bc.py +++ b/hysop_examples/examples/particles_above_salt/particles_above_salt_bc.py @@ -89,7 +89,7 @@ def compute(args): S_lboundaries = (BoundaryCondition.PERIODIC,)*(dim-1)+(BoundaryCondition.HOMOGENEOUS_NEUMANN,) S_rboundaries = (BoundaryCondition.PERIODIC,)*(dim-1)+(BoundaryCondition.HOMOGENEOUS_DIRICHLET,) C_lboundaries = (BoundaryCondition.PERIODIC,)*(dim-1)+(BoundaryCondition.HOMOGENEOUS_DIRICHLET,) - C_rboundaries = (BoundaryCondition.PERIODIC,)*(dim-1)+(BoundaryCondition.HOMOGENEOUS_NEUMANN.bind_data(2.0),) + C_rboundaries = (BoundaryCondition.PERIODIC,)*(dim-1)+(BoundaryCondition.HOMOGENEOUS_NEUMANN.bind_data(1.0),) box = Box(origin=Xo, length=np.subtract(Xn,Xo), lboundaries=lboundaries, rboundaries=rboundaries)