diff --git a/docs/sphinx/users_guide/finite_differences.rst b/docs/sphinx/users_guide/finite_differences.rst new file mode 100644 index 0000000000000000000000000000000000000000..81d277931d12716dff1f41adee43ac36cf2b6e3f --- /dev/null +++ b/docs/sphinx/users_guide/finite_differences.rst @@ -0,0 +1,199 @@ +.. _finite_differences: + +.. currentmodule:: hysop.numerics.finite_differences + +Finite differences schemes +-------------------------- + +Differentiate some fields in one direction using finite differences. + +So, to compute + +.. math:: + \begin{eqnarray} + result &=& \frac{\partial \rho}{\partial y} + \end{eqnarray} + +if tab is a numpy array representing the discrete values of the scalar field :math:`\rho` +on a grid, then the basic usage of such schemes is : + +.. code:: + + # Build/declare the scheme for a given space discretization + scheme = FDC2(step, indices) + # Apply scheme on the array + dir = 1 # y direction + result = scheme(tab, dir, result) + +This will compute : + +result = diff(tab[indices], dir), diff depending on +the chosen scheme. + + +Available schemes +^^^^^^^^^^^^^^^^^ + +* :class:`~FDC2` : first derivative, 2nd order centered scheme +* :class:`~FD2C2`: second derivative, 2nd order centered scheme +* :class:`~FDC4`: first derivative, 4th order centered scheme + + +A few important remarks +^^^^^^^^^^^^^^^^^^^^^^^ + +* step is the space discretization step size in each direction, i.e. a list or numpy array + with d values, d being the dimension of the domain. A common case is :code:: + + step = topo.mesh.space_step + +* indices represent the set of points on which the scheme must be applied. This is usually + a list of slices, for example, :code:: + + indices = topo.mesh.iCompute + +* result must be a predefined numpy array of the 'right' size, here the same size/shape as tab. + +* To optimize memory usage and computational time, it's possible to reduce the size of + the output and/or to apply the scheme on a subset of the domain. All available possibilities + are summarized through the examples below. + +* the size of the ghost layer depends on the scheme but is not checked! You must ensure + that topo.ghosts() >= scheme.minimal_ghost_layer. + +* for some schemes a work array may be provided during call. It must be a numpy array of + the same size of the result. It's shape is not really important, since during call + work will be reshaped to be of the same shape as result. This allows us to provide 1D array + that may be shared between different operators/methods whatever the internal required shapes are. + +* Notice that most of the time, finite-differences are defined as internal methods of operators and work arrays management, indices list or ghosts layers are set/checked internally. + +Default case : apply scheme on all the domain with a full-size result +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code:: + + from hysop.numerics.finite_differences import FDC2 + box = Box(length=[1., 1.]) + d2d = Discretization([33, 33], [1, 1]) + topo = box.create_topology(d2d) + rho = Field(box, name='rho') + # discretize and initialize rho + rd = rho.randomize(topo) + # Get 'computational' points, i.e. grid points excluding ghosts + ic = topo.mesh.iCompute + # space step + step = topo.mesh.space_step + # field resolution on the grid defined by topo + shape = topo.mesh.resolution + result = npw.zeros(shape) + scheme = FDC2(step, ic) + assert (topo.ghosts() >= scheme.minimal_ghost_layer).all() + result = scheme(rd.data[0], 1, result) + +In that case: + +* result.shape = (34, 34) +* scheme.indices = [slice(1,33), slice(1,33)] +* scheme.output_indices = [slice(0,32), slice(0,32)] + + +Apply scheme on all the domain with a reduced result +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If you do not want to allocate ghosts points for the result, then use: + +.. code:: + + shape = np.asarray(topo.mesh.resolution).copy() + shape -= 2 * topo.ghosts() + shape = tuple(shape) + result = npw.zeros(shape) + scheme = FDC2(step, ic, indices_out=True) + assert (topo.ghosts() >= scheme.minimal_ghost_layer).all() + result = scheme(rd.data[0], 1, result) + +In that case: + +* result.shape = (32,32) +* scheme.indices = [slice(1,33), slice(1,33)] +* scheme.output_indices = [slice(0,32), slice(0,32)] + + +Apply scheme on a subset of the domain with a full-size result +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code:: + + # We define a subset of the domain, + # a box of size half of the domain size. + from hysop.domain.subsets import SubBox + sl = topo.domain.length * 0.5 + orig = topo.domain.origin + 0.1 * topo.domain.length + subbox = SubBox(parent=topo.domain, origin=orig, length=sl) + indices = subbox.discretize(topo)[0] + scheme = FDC2(step, indices) + result = npw.zeros_like(rd.data[0]) + result = scheme(rd.data[0], 1, result) + +In that case: + +* result.shape = (34,34) +* scheme.indices = [slice(4,21), slice(4,21)] +* scheme.output_indices = scheme.indices + + +Apply scheme on a subset of the domain with a reduced-size result +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code:: + + # We define a subset of the domain, + # a box of size half of the domain size. + from hysop.domain.subsets import SubBox + sl = topo.domain.length * 0.5 + orig = topo.domain.origin + 0.1 * topo.domain.length + subbox = SubBox(parent=topo.domain, origin=orig, length=sl) + indices = subbox.discretize(topo)[0] + scheme = FDC2(step, indices, indices_out=True) + shape = subbox.mesh[topo].resolution + result = npw.zeros(shape) + result = scheme(rd.data[0], 1, result) + +In that case: + +* result.shape = (17,17) +* scheme.indices = [slice(4,21), slice(4,21)] +* scheme.output_indices = [slice(0,17), slice(0,17)]scheme.indices + + +Apply scheme on a subset of the domain with a predifined-size result +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Here you can choose explicitely where in result you want to put +the values of the computed derivative. + + +.. code:: + + # We define a subset of the domain, + # a box of size half of the domain size. + from hysop.domain.subsets import SubBox + sl = topo.domain.length * 0.5 + orig = topo.domain.origin + 0.1 * topo.domain.length + subbox = SubBox(parent=topo.domain, origin=orig, length=sl) + indices = subbox.discretize(topo)[0] + shape = subbox.mesh[topo].resolution + result = npw.zeros_like(rd.data[0) + iout = [slice(2, 19), slice(3, 20)] + scheme = FDC2(step, indices, indices_out=iout) + result = scheme(rd.data[0], 1, result) + +In that case: + +* result.shape = (17,17) +* scheme.indices = [slice(4,21), slice(4,21)] +* scheme.output_indices = iout + +This option is usefull when input tab is a work array, with a size different +from the topology resolution, and the result a field defined on the whole grid. + diff --git a/docs/sphinx/users_guide/numerics.rst b/docs/sphinx/users_guide/numerics.rst new file mode 100644 index 0000000000000000000000000000000000000000..3f420a06f998b8dcc8e709db9f5585ed74a5072a --- /dev/null +++ b/docs/sphinx/users_guide/numerics.rst @@ -0,0 +1,15 @@ + .. _numerics: + +Numerical operations +==================== + +This module handles all the 'low-level' operations mostly applied on numpy arrays. + +.. toctree:: + :maxdepth: 2 + + finite_differences + differential_operations + remeshing_and_interpolation + odesolvers + diff --git a/hysop/default_methods.py b/hysop/default_methods.py index 086c396101650428a7ff3b7d7858f97fe7eba9d4..425cafd5f9e8e7f7886dead7cf75c825aa6c5fd8 100644 --- a/hysop/default_methods.py +++ b/hysop/default_methods.py @@ -1,6 +1,4 @@ -""" -@file default_methods.py -Default parameter values for methods in operators. +"""Default parameters values for numerical methods in operators. """ from hysop.methods_keys import TimeIntegrator, Interpolation, GhostUpdate,\ Remesh, Support, Splitting, MultiScale, Formulation, SpaceDiscretisation, \ @@ -8,6 +6,7 @@ from hysop.methods_keys import TimeIntegrator, Interpolation, GhostUpdate,\ from hysop.constants import HYSOP_REAL from hysop.numerics.integrators.runge_kutta2 import RK2 from hysop.numerics.integrators.runge_kutta3 import RK3 +from hysop.numerics.finite_differences import FDC4, FDC2 from hysop.numerics.interpolation import Linear from hysop.numerics.remeshing import L2_1, Linear as Rmsh_Linear #from hysop.operator.discrete.stretching import Conservative @@ -17,18 +16,18 @@ ADVECTION = {TimeIntegrator: RK2, Interpolation: Linear, Remesh: L2_1, Support: '', Splitting: 'o2', MultiScale: L2_1, Precision: HYSOP_REAL} -from hysop.numerics.finite_differences import FD_C_4, FD_C_2 +from hysop.numerics.finite_differences import FDC4, FDC2 -DIFFERENTIAL = {SpaceDiscretisation: FD_C_4, GhostUpdate: True} +DIFFERENTIAL = {SpaceDiscretisation: FDC4, GhostUpdate: True} -ADAPT_TIME_STEP = {TimeIntegrator: RK3, SpaceDiscretisation: FD_C_4, +ADAPT_TIME_STEP = {TimeIntegrator: RK3, SpaceDiscretisation: FDC4, dtCrit: 'vort'} -BAROCLINIC = {SpaceDiscretisation: FD_C_4} +BAROCLINIC = {SpaceDiscretisation: FDC4} -MULTIPHASEBAROCLINIC = {SpaceDiscretisation: FD_C_4} +MULTIPHASEBAROCLINIC = {SpaceDiscretisation: FDC4} -MULTIPHASEGRADP = {SpaceDiscretisation: FD_C_4} +MULTIPHASEGRADP = {SpaceDiscretisation: FDC4} DIFFUSION = {SpaceDiscretisation: 'fftw', GhostUpdate: True} @@ -36,8 +35,8 @@ POISSON = {SpaceDiscretisation: 'fftw', GhostUpdate: True, Formulation: 'velocity'} STRETCHING = {TimeIntegrator: RK3, Formulation: "Conservative", - SpaceDiscretisation: FD_C_4} + SpaceDiscretisation: FDC4} -FORCES = {SpaceDiscretisation: FD_C_2} +FORCES = {SpaceDiscretisation: FDC2} MULTIRESOLUTION_FILER = {Remesh: Rmsh_Linear, } diff --git a/hysop/gpu/gpu_multiphase_baroclinic_rhs.py b/hysop/gpu/gpu_multiphase_baroclinic_rhs.py index 25500f61db308ee81aa5401590a6cebb7905e6db..32ce524cb79d6d3d97db0945f2bc04d5495a1ed4 100644 --- a/hysop/gpu/gpu_multiphase_baroclinic_rhs.py +++ b/hysop/gpu/gpu_multiphase_baroclinic_rhs.py @@ -15,7 +15,7 @@ from hysop.gpu.gpu_discrete import GPUDiscreteField from hysop.tools.profiler import FProfiler from hysop.mpi import Wtime from hysop.methods_keys import SpaceDiscretisation -from hysop.numerics.finite_differences import FD_C_4 +from hysop.numerics.finite_differences import FDC4 class BaroclinicRHS(DiscreteOperator, GPUOperator): @@ -103,7 +103,7 @@ class BaroclinicRHS(DiscreteOperator, GPUOperator): if 0 in self._cutdir_list: raise ValueError("Not yet implemented with comm in X dir") for d in self._cutdir_list: - if self.method[SpaceDiscretisation] == FD_C_4: + if self.method[SpaceDiscretisation] == FDC4: gh = 2 else: gh = 1 diff --git a/hysop/gpu/tests/test_multiphase_baroclinic.py b/hysop/gpu/tests/test_multiphase_baroclinic.py index e4d45594ae55d5e2b2eeda042fb0f972f2986d72..5c3aa47f847fb130ee077a32f1ee62a7efb58941 100755 --- a/hysop/gpu/tests/test_multiphase_baroclinic.py +++ b/hysop/gpu/tests/test_multiphase_baroclinic.py @@ -5,7 +5,7 @@ from hysop.tools.parameters import Discretization, MPIParams from hysop.domain.box import Box from hysop.fields.continuous import Field from hysop.operator.multiphase_baroclinic_rhs import MultiphaseBaroclinicRHS -from hysop.numerics.finite_differences import FD_C_4, FD_C_2 +from hysop.numerics.finite_differences import FDC4, FDC2 import hysop.tools.numpywrappers as npw import numpy as np from hysop.methods_keys import Support, SpaceDiscretisation, ExtraArgs @@ -91,7 +91,7 @@ def call_operator(func, grad_func, vfunc): gradp: d_coarse, rho: d_fine}, method={Support: 'gpu', - SpaceDiscretisation: FD_C_4, + SpaceDiscretisation: FDC4, ExtraArgs: {'density_func': 'x', }}) op.discretize() op.setup() diff --git a/hysop/methods.py b/hysop/methods.py index 88858e611ecf5aa16661735798696685021c7006..3b971ad3f8ebd1487daa6a35c7baf04c49a8b812 100644 --- a/hysop/methods.py +++ b/hysop/methods.py @@ -1,19 +1,24 @@ -""" -@file methods.py -A list of numerical methods available in HySoP that may be used to set methods -in operators. +"""Some shortcuts to numerical methods available in HySoP that may be used +to set methods attribute in operators. + Usage: + method = {key: value, ...} + Keys must be one of the constants given in methods_keys.py. + Value is usually a class name and sometimes a string. See details in each operator. -Example, the stretching case : -method = {TimeIntegrator: RK3, Formulation: Conservative, - SpaceDiscretisation: FD_C_4} +For example, consider the stretching case where time-integration +is done with Runge-Kutta 3, order 4 finite-difference scheme is used +for space discretisation and the default formulation is conservative:: + + method = {TimeIntegrator: RK3, Formulation: Conservative, + SpaceDiscretisation: FDC4} Note FP: to avoid cycling, this file must never be imported -inside a HySoP module. It's only a review of all the methods +inside an HySoP module. It's only a review of all the methods that can be imported by final user. """ @@ -50,9 +55,9 @@ Linear = interpolation.Linear # Finite differences import hysop.numerics.finite_differences as fd -FD_C_4 = fd.FD_C_4 -FD_C_2 = fd.FD_C_2 -FD2_C_2 = fd.FD2_C_2 +FDC4 = fd.FDC4 +FDC2 = fd.FDC2 +FD2C2 = fd.FD2C2 # Stretching formulations import hysop.operator.discrete.stretching as strd diff --git a/hysop/methods_keys.py b/hysop/methods_keys.py index a4505dee4b5301303b6c6941c356bd9583a6cc11..ec4601ed3d02e5d1432c25dd7f519beeee090b69 100644 --- a/hysop/methods_keys.py +++ b/hysop/methods_keys.py @@ -9,7 +9,7 @@ and sometimes a string. See details in each operator. Example, the stretching case : method = {TimeIntegrator: RK3, Formulation: Conservative, - SpaceDiscretisation: FD_C_4} + SpaceDiscretisation: FDC4} """ diff --git a/hysop/numerics/__init__.py b/hysop/numerics/__init__.py index c991ed075ff1f03868bc14e421f731f1f9f6f649..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 --- a/hysop/numerics/__init__.py +++ b/hysop/numerics/__init__.py @@ -1,17 +0,0 @@ -## @package hysop.numerics -# -# \todo write a proper doc for numerical methods -# -# All functions in this package are supposed to work with numpy arrays, -# not with hysop fields. -# -# -# -# -# -# \section perfandmem About performances and optimisations -# -# \subsection Finite Differences -# Two ways : -# - fd.compute -# - fd.compute_and_add diff --git a/hysop/numerics/differential_operations.py b/hysop/numerics/differential_operations.py index 3f78337a60ee3fdc12309aa4c4406d0f26fc759c..67559774c23e9d897297f697a90c0c39c0466159 100755 --- a/hysop/numerics/differential_operations.py +++ b/hysop/numerics/differential_operations.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- """Library of functions used to perform classical vector calculus -(diff operations like grad, curl ...) +(diff operations like grad, curl ...) based on finite differences schemes. * :class:`~hysop.numerics.differential_operations.Curl`, * :class:`~hysop.numerics.differential_operations.DivRhoV`, @@ -28,12 +28,16 @@ For example : """ from hysop.constants import debug, XDIR, YDIR, ZDIR from abc import ABCMeta -from hysop.numerics.finite_differences import FD_C_4, FD_C_2, FD2_C_2 +from hysop.numerics.finite_differences import FDC4, FDC2, FD2C2 import numpy as np import hysop.tools.numpywrappers as npw +from hysop.tools.misc import WorkSpaceTools, Utils class DifferentialOperation(object): + """Abstract base class for all operations + based on finite differences. + """ __metaclass__ = ABCMeta _authorized_methods = [] @@ -140,7 +144,8 @@ class Curl(DifferentialOperation): """ Computes nabla X V, V being a vector field. """ - _authorized_methods = [FD_C_2, FD_C_4] + _authorized_methods = [FDC2, FDC4] + _lwork = 1 def __init__(self, **kwds): """Curl of a vector field @@ -217,18 +222,10 @@ class DivRhoV(DifferentialOperation): V a vector field. Works for any dimension. - Methods : FD_C_4 - 1 - default : based on fd.compute. - 2 - opt : based on fd.compute_and_add. - To use this one, call self._central4_caa. - shape is a tuple (like np.ndarray.shape), e.g. (nx,ny,nz). - - Note FP: - - 1 seems to be faster than 2 for large systems (>200*3) and - less memory consumming. For smaller systems, well, it depends ... + Methods : FDC4 """ - _authorized_methods = [FD_C_4] + _authorized_methods = [FDC4] def __init__(self, **kwds): """Divergence of rho V, rho a scalar field, V a vector field @@ -240,7 +237,7 @@ class DivRhoV(DifferentialOperation): result = div(rhoV), which is the default. **kwds : parameters for base class - Default method : FD_C_4 + Default method : FDC4 """ super(DivRhoV, self).__init__(**kwds) #self.fcall = self._central4_caa @@ -329,7 +326,7 @@ class DivWV(DifferentialOperation): """ - _authorized_methods = [FD_C_4] + _authorized_methods = [FDC4] def __init__(self, **kwds): """Divergence of (W.Vx, W.Vy, W.Vz), W, V two vector fields @@ -341,7 +338,7 @@ class DivWV(DifferentialOperation): result = div(rhoV), which is the default. **kwds : parameters for base class - Default method : FD_C_4 + Default method : FDC4 """ super(DivWV, self).__init__(**kwds) self.fcall = self._central4 @@ -385,7 +382,8 @@ class DivWV(DifferentialOperation): class Laplacian(DifferentialOperation): """Computes the laplacian of a field. """ - _authorized_methods = [FD2_C_2] + _authorized_methods = [FD2C2] + _lwork = 1 @staticmethod def get_work_length(): @@ -415,7 +413,7 @@ class Laplacian(DifferentialOperation): class GradS(DifferentialOperation): """Gradient of a scalar field """ - _authorized_methods = [FD_C_4, FD_C_2] + _authorized_methods = [FDC4, FDC2] def __call__(self, scal, result): """Apply gradient, with central finite difference scheme. @@ -438,7 +436,7 @@ class GradS(DifferentialOperation): class GradV(DifferentialOperation): """Gradient of a vector field """ - _authorized_methods = [FD_C_4, FD_C_2] + _authorized_methods = [FDC4, FDC2] def __init__(self, **kwds): super(GradV, self).__init__(**kwds) @@ -468,7 +466,8 @@ class GradVxW(DifferentialOperation): """Computes [nabla(V)][W] with V and W some vector fields. """ - _authorized_methods = [FD_C_4, FD_C_2] + _authorized_methods = [FDC4, FDC2] + _lwork = 2 @staticmethod def get_work_length(): @@ -517,7 +516,8 @@ class GradVxW(DifferentialOperation): class DivAdvection(DifferentialOperation): """ Computes -nabla .(V . nabla V) with V a vector field. """ - _authorized_methods = [FD_C_4, FD_C_2] + _authorized_methods = [FDC4, FDC2] + _lwork = 3 @staticmethod def get_work_length(): diff --git a/hysop/numerics/finite_differences.py b/hysop/numerics/finite_differences.py index cecf245794feca8d17fd730f4395b4a4bf5cb341..dbf51487dd75011a5000718a51668e13639fe095 100644 --- a/hysop/numerics/finite_differences.py +++ b/hysop/numerics/finite_differences.py @@ -1,4 +1,49 @@ """Finite difference schemes + +.. currentmodule hysop.numerics.finite_differences + +* :class:`~FDC2` : first derivative, 2nd order centered scheme +* :class:`~FD2C2`: second derivative, 2nd order centered scheme +* :class:`~FDC4`: first derivative, 4th order centered scheme +* :class:`~FiniteDifference`, abstract base class. + + +Usage: + +.. code:: + + # indices and space step from a predefined mesh + indices = topo.mesh.compute_index + step = topo.mesh.space_step + # init scheme + scheme = FDC4(step, indices) + # result = some array of the same shape as field. + # compute dfield/d direction in result + result = scheme(field, direction, result) + # or (with more assert and checks on inputs) + scheme.compute(field, direction, result) + # or result += dfield/d direction + scheme.compute_and_add(field, direction, result) + + +Note +---- +* fd are computed only on points described by indices : + result[ind] = diff(field[ind]), + which means that result and field must have the same shape. +* You can also used a 'reduced' output result to minimize memory. + Use 'reduce_output_shape=True' in scheme init. In that case, + result must be of a shape corresponding to indices 'shape'. + + Example: + +.. code:: + + scheme = FDC4(step, indices, reduce_output_shape=True) + # if indices is slice(4,10) in each direction + result = npw.zeros((6,6,6)) + ... + """ from abc import ABCMeta, abstractmethod from hysop.constants import debug @@ -13,7 +58,7 @@ class FiniteDifference(object): Usage : >> step = topo.mesh_space_step - >> scheme = FD_C_4(step, topo.mesh.compute_index) + >> scheme = FDC4(step, topo.mesh.compute_index) For a given numpy array (obviously discretized on the topo used to compute indices), to compute result as the derivative @@ -39,7 +84,7 @@ class FiniteDifference(object): def __new__(cls, *args, **kw): return object.__new__(cls, *args, **kw) - def __init__(self, step, indices, reduce_output_shape=False): + def __init__(self, step, indices, indices_out=None): """ Parameters @@ -48,26 +93,20 @@ class FiniteDifference(object): resolution of the mesh indices : list of slices Represents the local mesh on which finite-differences - will be applied, like compute_index in :class:`~hysop.domain.mesh.Mesh`. - reduce_output_shape : boolean, optional - True to return the result in a reduced array. See notes below. + will be applied, like compute_index + in :class:`~hysop.domain.mesh.Mesh`. + indices_out : list of slices, optional + set which indices of result will be modified. By default, + indices_out = indices Attributes ---------- - minimal_ghost_layer : int + ghosts_layer_size : int, static minimal number of points required inside the ghost layer for this scheme. - Notes - ----- - Two ways to compute result = scheme(input) - * 1 - either input and result are arrays of the same shape, and - result[indices] = scheme(input[indices]) will be computed - * 2 - or result is a smaller array than input, and - result[...] = scheme(input(indices)) - To use case 2, set reduce_output_shape = True. """ - + step = np.asarray(step) # dim of the field on which scheme will be applied # (i.e dim of the domain) @@ -78,18 +117,36 @@ class FiniteDifference(object): self._a2 = None self._coeff = None # List of slices representing the mesh on which fd scheme is applied - self._indices = indices - if not reduce_output_shape: - self.result_shape = None - self.output_indices = self._indices - else: - self.result_shape = tuple([indices[i].stop - indices[i].start - for i in xrange(len(indices))]) - self.output_indices = [slice(0, self.result_shape[i]) + self.indices = indices + if indices_out is None or indices_out is False: + # This is the default case. It means that + # result shape is unknown. It will + # be the same as input tab shape during call + # and input/output indices are the same: + # we compute result[indices] = scheme(tab[indices]) + self.output_indices = self.indices + elif isinstance(indices_out, list): + # In that case, result shape remains unknown but + # the position where result is written is not the + # same as input indices. + # We compute: + # result[indices_out] = scheme(tab[indices]) + # Warning : result shape/indices_out compliance + # is not checked! + self.output_indices = indices_out + + elif indices_out is True: + # Here, output shape is fixed to the minimal required + # shape, computed with indices. + # So, we compute: + # result[...] = scheme(tab[indices]) + result_shape = tuple([indices[i].stop - indices[i].start + for i in xrange(len(indices))]) + self.output_indices = [slice(0, result_shape[i]) for i in xrange(len(indices))] + else: + assert False - # Minimal size of the ghost layer. - self.minimal_ghost_layer = 1 self._step = step self._compute_indices(step) @@ -118,13 +175,30 @@ class FiniteDifference(object): """ assert result is not tab assert result.__class__ is np.ndarray - assert result.shape == self.result_shape or result.shape == tab.shape assert tab.__class__ is np.ndarray - self.__call__(tab, cdir, result) + result = self.__call__(tab, cdir, result) + return result @abstractmethod - def compute_and_add(self, tab, cdir, result): - """Apply FD scheme and add the result inplace. + def compute_and_add(self, tab, cdir, result, work): + """Apply FD scheme and add the abs of the result inplace. + + Parameters + ---------- + tab : numpy array + input field + cdir : int + direction of differentiation + result : numpy array + in/out, abs(derivative of tab) + result + work : numpy array + internal workspace. Must be 1D and of the same + size as result. + """ + + @abstractmethod + def compute_and_add_abs(self, tab, cdir, result, work): + """Apply FD scheme and add np.abs of the derivative inplace. Parameters ---------- @@ -134,10 +208,13 @@ class FiniteDifference(object): direction of differentiation result : numpy array in/out, derivative of tab + result + work : numpy array + internal workspace. Must be 1D and of the same + size as result. """ -class FD_C_2(FiniteDifference): +class FDC2(FiniteDifference): """ 1st derivative, centered scheme, 2nd order. @@ -147,19 +224,18 @@ class FD_C_2(FiniteDifference): def _compute_indices(self, step): - self.minimal_ghost_layer = 1 self._coeff = npw.asarray(1. / (2. * step)) self._m1 = [] self._a1 = [] for dim in xrange(self._dim): - self._m1.append(list(self._indices)) - self._m1[dim][dim] = slice(self._indices[dim].start - 1, - self._indices[dim].stop - 1, - self._indices[dim].step) - self._a1.append(list(self._indices)) - self._a1[dim][dim] = slice(self._indices[dim].start + 1, - self._indices[dim].stop + 1, - self._indices[dim].step) + self._m1.append(list(self.indices)) + self._m1[dim][dim] = slice(self.indices[dim].start - 1, + self.indices[dim].stop - 1, + self.indices[dim].step) + self._a1.append(list(self.indices)) + self._a1[dim][dim] = slice(self.indices[dim].start + 1, + self.indices[dim].stop + 1, + self.indices[dim].step) def __call__(self, tab, cdir, result): result[self.output_indices] = tab[self._a1[cdir]] @@ -167,8 +243,8 @@ class FD_C_2(FiniteDifference): result[self.output_indices] *= self._coeff[cdir] return result - def compute_and_add(self, tab, cdir, result): - """Apply FD scheme and add the result inplace. + def compute_and_add(self, tab, cdir, result, work): + """Apply FD scheme and add np.abs of the derivative inplace. Parameters ---------- @@ -178,14 +254,55 @@ class FD_C_2(FiniteDifference): direction of differentiation result : numpy array in/out, derivative of tab + result + work : numpy array + internal workspace. Must be 1D and of the same + size as result. + """ assert result.__class__ is np.ndarray assert tab.__class__ is np.ndarray - result[self.output_indices] += \ - self._coeff[cdir] * (tab[self._a1[cdir]] - tab[self._m1[cdir]]) + assert work.size == result.size + wk = work.reshape(result.shape) + np.subtract(tab[self._a1[cdir]], tab[self._m1[cdir]], + wk[self.output_indices]) + np.multiply(wk[self.output_indices], self._coeff[cdir], + wk[self.output_indices]) + np.add(wk[self.output_indices], result[self.output_indices], + result[self.output_indices]) + return result + def compute_and_add_abs(self, tab, cdir, result, work): + """Apply FD scheme and add np.abs of the derivative inplace. -class FD2_C_2(FiniteDifference): + Parameters + ---------- + tab : numpy array + input field + cdir : int + direction of differentiation + result : numpy array + in/out, derivative of tab + result + work : numpy array + internal workspace. Must be 1D and of the same + size as result. + + """ + assert result.__class__ is np.ndarray + assert tab.__class__ is np.ndarray + assert work.__class__ is np.ndarray + assert work is not result + wk = work.reshape(result.shape) + np.subtract(tab[self._a1[cdir]], tab[self._m1[cdir]], + wk[self.output_indices]) + np.multiply(wk[self.output_indices], self._coeff[cdir], + wk[self.output_indices]) + np.abs(wk[self.output_indices], wk[self.output_indices]) + np.add(wk[self.output_indices], result[self.output_indices], + result[self.output_indices]) + return result + + +class FD2C2(FiniteDifference): """ Second derivative, centered scheme, 2nd order. """ @@ -194,29 +311,28 @@ class FD2_C_2(FiniteDifference): def _compute_indices(self, step): - self.minimal_ghost_layer = 1 self._m1 = [] self._a1 = [] self._coeff = npw.asarray(1. / (step * step)) for dim in xrange(self._dim): - self._m1.append(list(self._indices)) - self._m1[dim][dim] = slice(self._indices[dim].start - 1, - self._indices[dim].stop - 1, - self._indices[dim].step) - self._a1.append(list(self._indices)) - self._a1[dim][dim] = slice(self._indices[dim].start + 1, - self._indices[dim].stop + 1, - self._indices[dim].step) + self._m1.append(list(self.indices)) + self._m1[dim][dim] = slice(self.indices[dim].start - 1, + self.indices[dim].stop - 1, + self.indices[dim].step) + self._a1.append(list(self.indices)) + self._a1[dim][dim] = slice(self.indices[dim].start + 1, + self.indices[dim].stop + 1, + self.indices[dim].step) def __call__(self, tab, cdir, result): - result[self.output_indices] = tab[self._indices] + result[self.output_indices] = tab[self.indices] result[self.output_indices] *= -2 result[self.output_indices] += tab[self._a1[cdir]] result[self.output_indices] += tab[self._m1[cdir]] result[self.output_indices] *= self._coeff[cdir] return result - def compute_and_add(self, tab, cdir, result): + def compute_and_add(self, tab, cdir, result, work): """Apply FD scheme and add the result inplace. Parameters @@ -227,15 +343,59 @@ class FD2_C_2(FiniteDifference): direction of differentiation result : numpy array in/out, derivative of tab + result + work : numpy array + internal workspace. Must be 1D and of the same + size as result. + + """ + assert result.__class__ is np.ndarray + assert tab.__class__ is np.ndarray + wk = work.reshape(result.shape) + np.multiply(tab[self.indices], -2., wk[self.output_indices]) + np.add(tab[self._a1[cdir]], wk[self.output_indices], + wk[self.output_indices]) + np.add(tab[self._m1[cdir]], wk[self.output_indices], + wk[self.output_indices]) + np.multiply(wk[self.output_indices], self._coeff[cdir], + wk[self.output_indices]) + np.add(wk[self.output_indices], result[self.output_indices], + result[self.output_indices]) + return result + + def compute_and_add_abs(self, tab, cdir, result, work): + """Apply FD scheme and add np.abs of the derivative inplace. + + Parameters + ---------- + tab : numpy array + input field + cdir : int + direction of differentiation + result : numpy array + in/out, derivative of tab + result + work : numpy array + internal workspace. Must be 1D and of the same + size as result. + """ assert result.__class__ is np.ndarray assert tab.__class__ is np.ndarray - result[self.output_indices] += self._coeff[cdir] * ( - -2 * tab[self._indices] + tab[self._m1[cdir]] + tab[self._a1[cdir]] - ) + wk = work.reshape(result.shape) + np.multiply(tab[self.indices], -2., wk[self.output_indices]) + np.add(tab[self._a1[cdir]], wk[self.output_indices], + wk[self.output_indices]) + np.add(tab[self._m1[cdir]], wk[self.output_indices], + wk[self.output_indices]) + np.multiply(wk[self.output_indices], self._coeff[cdir], + wk[self.output_indices]) + np.abs(wk[self.output_indices], wk[self.output_indices]) + np.add(wk[self.output_indices], result[self.output_indices], + result[self.output_indices]) + + return result -class FD_C_4(FiniteDifference): +class FDC4(FiniteDifference): """ 1st derivative, centered scheme, 4th order. """ @@ -244,7 +404,6 @@ class FD_C_4(FiniteDifference): def _compute_indices(self, step): - self.minimal_ghost_layer = 2 self._m1 = [] self._m2 = [] self._a1 = [] @@ -252,22 +411,22 @@ class FD_C_4(FiniteDifference): # FD scheme coefficients self._coeff = npw.asarray(1. / (12. * step)) for dim in xrange(self._dim): - self._m1.append(list(self._indices)) - self._m1[dim][dim] = slice(self._indices[dim].start - 1, - self._indices[dim].stop - 1, - self._indices[dim].step) - self._m2.append(list(self._indices)) - self._m2[dim][dim] = slice(self._indices[dim].start - 2, - self._indices[dim].stop - 2, - self._indices[dim].step) - self._a1.append(list(self._indices)) - self._a1[dim][dim] = slice(self._indices[dim].start + 1, - self._indices[dim].stop + 1, - self._indices[dim].step) - self._a2.append(list(self._indices)) - self._a2[dim][dim] = slice(self._indices[dim].start + 2, - self._indices[dim].stop + 2, - self._indices[dim].step) + self._m1.append(list(self.indices)) + self._m1[dim][dim] = slice(self.indices[dim].start - 1, + self.indices[dim].stop - 1, + self.indices[dim].step) + self._m2.append(list(self.indices)) + self._m2[dim][dim] = slice(self.indices[dim].start - 2, + self.indices[dim].stop - 2, + self.indices[dim].step) + self._a1.append(list(self.indices)) + self._a1[dim][dim] = slice(self.indices[dim].start + 1, + self.indices[dim].stop + 1, + self.indices[dim].step) + self._a2.append(list(self.indices)) + self._a2[dim][dim] = slice(self.indices[dim].start + 2, + self.indices[dim].stop + 2, + self.indices[dim].step) def __call__(self, tab, cdir, result): result[self.output_indices] = tab[self._a1[cdir]] @@ -278,7 +437,7 @@ class FD_C_4(FiniteDifference): result[self.output_indices] *= self._coeff[cdir] return result - def compute_and_add(self, tab, cdir, result): + def compute_and_add(self, tab, cdir, result, work): """Apply FD scheme and add the result inplace. Parameters @@ -289,9 +448,62 @@ class FD_C_4(FiniteDifference): direction of differentiation result : numpy array in/out, derivative of tab + result + work : numpy array + internal workspace. Must be 1D and of the same + size as result. + + """ + assert result.__class__ is np.ndarray + assert tab.__class__ is np.ndarray + assert work is not result + assert work.size == result.size + wk = work.reshape(result.shape) + np.subtract(tab[self._a1[cdir]], tab[self._m1[cdir]], + wk[self.output_indices]) + np.multiply(wk[self.output_indices], 8., + wk[self.output_indices]) + np.add(wk[self.output_indices], tab[self._m2[cdir]], + wk[self.output_indices]) + np.subtract(wk[self.output_indices], tab[self._a2[cdir]], + wk[self.output_indices]) + np.multiply(wk[self.output_indices], self._coeff[cdir], + wk[self.output_indices]) + np.add(wk[self.output_indices], result[self.output_indices], + result[self.output_indices]) + return result + + def compute_and_add_abs(self, tab, cdir, result, work): + """Apply FD scheme and add np.abs of the derivative inplace. + + Parameters + ---------- + tab : numpy array + input field + cdir : int + direction of differentiation + result : numpy array + in/out, derivative of tab + result + work : numpy array + internal workspace. Must be 1D and of the same + size as result. + """ assert result.__class__ is np.ndarray assert tab.__class__ is np.ndarray - result[self.output_indices] += self._coeff[cdir] * ( - 8 * (tab[self._a1[cdir]] - tab[self._m1[cdir]]) + - tab[self._m2[cdir]] - tab[self._a2[cdir]]) + assert work is not result + assert work.size == result.size + wk = work.reshape(result.shape) + np.subtract(tab[self._a1[cdir]], tab[self._m1[cdir]], + wk[self.output_indices]) + np.multiply(wk[self.output_indices], 8., + wk[self.output_indices]) + np.add(wk[self.output_indices], tab[self._m2[cdir]], + wk[self.output_indices]) + np.subtract(wk[self.output_indices], tab[self._a2[cdir]], + wk[self.output_indices]) + np.multiply(wk[self.output_indices], self._coeff[cdir], + wk[self.output_indices]) + np.abs(wk[self.output_indices], wk[self.output_indices]) + np.add(wk[self.output_indices], result[self.output_indices], + result[self.output_indices]) + return result diff --git a/hysop/numerics/tests/test_finite_differences.py b/hysop/numerics/tests/test_finite_differences.py new file mode 100644 index 0000000000000000000000000000000000000000..b098eb7b03b12cb43fd210fe543a9e8795af8a60 --- /dev/null +++ b/hysop/numerics/tests/test_finite_differences.py @@ -0,0 +1,199 @@ +"""FD schemes tests +""" +from hysop.numerics.finite_differences import FDC2, FDC4, FD2C2 +import hysop.tools.numpywrappers as npw +from hysop import Box, Discretization, Field +import numpy as np +from hysop.domain.subsets import SubBox + + +Nx = Ny = Nz = 128 +g = 2 +d2d = Discretization([Nx, Ny], [g, g]) +d3d = Discretization([Nx, Ny, Nz], [g, g, g]) + + +def f2d(res, x, y, t): + res[0][...] = np.cos(x) * y ** 2 + x * y ** 3 + return res + + +def ref_f2d(res, x, y, t): + res[0][...] = -np.sin(x) * y ** 2 + y ** 3 + return res + + +def ref2_f2d(res, x, y, t): + res[0][...] = 2 * np.cos(x) + 6 * x * y + return res + + +def f3d(res, x, y, z, t): + res[0][...] = np.cos(x) * y ** 2 + x * y ** 3 + return res + + +def ref_f3d(res, x, y, z, t): + res[0][...] = -np.sin(x) * y ** 2 + y ** 3 + return res + + +def ref2_f3d(res, x, y, z, t): + res[0][...] = 2 * np.cos(x) + 6 * x * y + return res + + +lengthes = [1., 1., 1.] + + +def init(discr, formulas): + dimension = len(discr.resolution) + box = Box(length=lengthes[:dimension]) + f1 = Field(name='input', domain=box, formula=formulas[0]) + ref = Field(name='ref', domain=box, formula=formulas[1]) + topo = box.create_topology(discr) + f1d = f1.discretize(topo).data[0] + refd = ref.discretize(topo).data[0] + f1.initialize(topo=topo) + ref.initialize(topo=topo) + ref2 = Field(name='ref', domain=box, formula=formulas[2]) + ref2d = ref2.discretize(topo).data[0] + ref2.initialize(topo=topo) + return topo, f1d, refd, ref2d + + +def run_schemes(schemes, f1d, result, ind, hh, iout=None): + + work = npw.zeros(result.size) + if iout is None: + iout = ind + for sc in schemes: + ref = schemes[sc][0] + order = schemes[sc][2] + direction = schemes[sc][1] + result = sc(f1d, direction, result) + assert np.allclose(result[iout], ref[ind], atol=hh[0] ** order) + result[...] = 1. + result = sc.compute_and_add(f1d, direction, result, work) + assert np.allclose(result[iout], 1. + ref[ind], atol=hh[0] ** order) + result[...] = 1. + result = sc.compute_and_add_abs(f1d, direction, result, work) + assert np.allclose(result[iout], 1. + np.abs(ref[ind]), + atol=hh[0] ** order) + + +def check_fd_schemes(discr, formulas): + topo, f1d, refd, ref2d = init(discr, formulas) + ind = topo.mesh.compute_index + hh = topo.mesh.space_step + sc = { + FDC2(hh, ind): [refd, 0, 2], + FDC4(hh, ind): [refd, 0, 4], + FD2C2(hh, ind): [ref2d, 1, 2]} + shape = topo.mesh.resolution + result = npw.zeros(shape) + run_schemes(sc, f1d, result, ind, hh) + + +def check_fd_schemes_reduce_input(discr, formulas): + topo, f1d, refd, ref2d = init(discr, formulas) + sl = topo.domain.length * 0.5 + orig = topo.domain.origin + 0.1 * topo.domain.length + subbox = SubBox(parent=topo.domain, origin=orig, length=sl) + ind = subbox.discretize(topo)[0] + hh = topo.mesh.space_step + sc = { + FDC2(hh, ind): [refd, 0, 2], + FDC4(hh, ind): [refd, 0, 4], + FD2C2(hh, ind): [ref2d, 1, 2]} + shape = topo.mesh.resolution + result = npw.zeros(shape) + run_schemes(sc, f1d, result, ind, hh) + + +def check_fd_schemes_reduce_output(discr, formulas): + topo, f1d, refd, ref2d = init(discr, formulas) + ind = topo.mesh.compute_index + hh = topo.mesh.space_step + sc = { + FDC2(hh, ind, indices_out=True): [refd, 0, 2], + FDC4(hh, ind, indices_out=True): [refd, 0, 4], + FD2C2(hh, ind, indices_out=True): [ref2d, 1, 2] + } + shape = np.asarray(topo.mesh.resolution).copy() + shape -= 2 * g + shape = tuple(shape) + result = npw.zeros(shape) + iout = [slice(0, shape[i]) for i in xrange(len(shape))] + run_schemes(sc, f1d, result, ind, hh, iout) + + +def check_fd_schemes_reduce_all(discr, formulas): + topo, f1d, refd, ref2d = init(discr, formulas) + hh = topo.mesh.space_step + sl = topo.domain.length * 0.5 + orig = topo.domain.origin + 0.1 * topo.domain.length + subbox = SubBox(parent=topo.domain, origin=orig, length=sl) + ind = subbox.discretize(topo)[0] + sc = { + FDC2(hh, ind, indices_out=True): [refd, 0, 2], + FDC4(hh, ind, indices_out=True): [refd, 0, 4], + FD2C2(hh, ind, indices_out=True): [ref2d, 1, 2] + } + shape = subbox.mesh[topo].resolution + result = npw.zeros(shape) + iout = [slice(0, shape[i]) for i in xrange(len(shape))] + run_schemes(sc, f1d, result, ind, hh, iout) + + +def check_fd_schemes_setiout(discr, formulas): + topo, f1d, refd, ref2d = init(discr, formulas) + hh = topo.mesh.space_step + sl = topo.domain.length * 0.5 + orig = topo.domain.origin + 0.1 * topo.domain.length + subbox = SubBox(parent=topo.domain, origin=orig, length=sl) + ind = subbox.discretize(topo)[0] + shape = np.asarray(subbox.mesh[topo].resolution).copy() + shape += 6 + shape = tuple(shape) + result = npw.zeros(shape) + iout = [slice(3, shape[i] - 3) for i in xrange(len(shape))] + sc = { + FDC2(hh, ind, indices_out=iout): [refd, 0, 2], + FDC4(hh, ind, indices_out=iout): [refd, 0, 4], + FD2C2(hh, ind, indices_out=iout): [ref2d, 1, 2] + } + run_schemes(sc, f1d, result, ind, hh, iout) + + +def test_fd_2d(): + check_fd_schemes(d2d, [f2d, ref_f2d, ref2_f2d]) + + +def test_fd_3d(): + check_fd_schemes(d3d, [f3d, ref_f3d, ref2_f3d]) + + +def test_fd_3d_reduce_input(): + check_fd_schemes_reduce_input(d3d, [f3d, ref_f3d, ref2_f3d]) + + +def test_fd_3d_reduce_output(): + check_fd_schemes_reduce_output(d3d, [f3d, ref_f3d, ref2_f3d]) + + +def test_fd_3d_reduce_all(): + check_fd_schemes_reduce_all(d3d, [f3d, ref_f3d, ref2_f3d]) + + +def test_fd_3d_setiout(): + check_fd_schemes_setiout(d3d, [f3d, ref_f3d, ref2_f3d]) + + +if __name__ == '__main__': + test_fd_2d() + test_fd_3d() + test_fd_3d_reduce_input() + test_fd_3d_reduce_output() + test_fd_3d_reduce_all() + test_fd_3d_setiout() diff --git a/hysop/operator/adapt_timestep.py b/hysop/operator/adapt_timestep.py index 93ba310d003dc1be383e7cd5b9e37ec4e527d807..b298ea7200e214064203ce4cd26b060907e17924 100755 --- a/hysop/operator/adapt_timestep.py +++ b/hysop/operator/adapt_timestep.py @@ -8,7 +8,7 @@ Definition of the adaptative time step according to the flow fields. from hysop.constants import debug from hysop.methods_keys import TimeIntegrator, SpaceDiscretisation,\ dtCrit -from hysop.numerics.finite_differences import FD_C_4 +from hysop.numerics.finite_differences import FDC4 from hysop.operator.discrete.adapt_timestep import AdaptTimeStep_D from hysop.operator.continuous import opsetup from hysop.operator.computational import Computational @@ -102,7 +102,7 @@ class AdaptTimeStep(Computational): return res def discretize(self): - if self.method[SpaceDiscretisation] is FD_C_4: + if self.method[SpaceDiscretisation] is FDC4: nbGhosts = 2 else: raise ValueError("Unknown method for space discretization of the\ diff --git a/hysop/operator/baroclinic.py b/hysop/operator/baroclinic.py index 7609042784860623d860ddb7d85d1a0208bd9312..7937b55a558377a6420c858b106630bfb1aed6c5 100644 --- a/hysop/operator/baroclinic.py +++ b/hysop/operator/baroclinic.py @@ -7,7 +7,7 @@ MultiPhase Rot Grad P from hysop.operator.computational import Computational from hysop.operator.discrete.baroclinic import Baroclinic as BD from hysop.methods_keys import SpaceDiscretisation -from hysop.numerics.finite_differences import FD_C_4 +from hysop.numerics.finite_differences import FDC4 from hysop.constants import debug import hysop.default_methods as default from hysop.operator.continuous import opsetup @@ -51,7 +51,7 @@ class Baroclinic(Computational): assert SpaceDiscretisation in self.method.keys() def discretize(self): - if self.method[SpaceDiscretisation] is FD_C_4: + if self.method[SpaceDiscretisation] is FDC4: nbGhosts = 2 else: raise ValueError("Unknown method for space discretization of the\ diff --git a/hysop/operator/baroclinic_from_rhs.py b/hysop/operator/baroclinic_from_rhs.py index 2678d8aca0b9250faa449de187e5b520dbf91420..a352c4e645ec6579d1ce390fa257a46a3544f066 100644 --- a/hysop/operator/baroclinic_from_rhs.py +++ b/hysop/operator/baroclinic_from_rhs.py @@ -7,7 +7,7 @@ MultiPhase baroclinic term from hysop.operator.computational import Computational from hysop.operator.discrete.baroclinic_from_rhs import BaroclinicFromRHS as BD from hysop.methods_keys import SpaceDiscretisation -from hysop.numerics.finite_differences import FD_C_4 +from hysop.numerics.finite_differences import FDC4 from hysop.constants import debug import hysop.default_methods as default from hysop.operator.continuous import opsetup diff --git a/hysop/operator/discrete/drag_and_lift.py b/hysop/operator/discrete/drag_and_lift.py index 875b9ee3b38cab61ead102183ac928eb406fd507..73f3fd550a06b5face864dc76309f271423e7137 100644 --- a/hysop/operator/discrete/drag_and_lift.py +++ b/hysop/operator/discrete/drag_and_lift.py @@ -10,7 +10,7 @@ from hysop.constants import XDIR, YDIR, ZDIR from hysop.domain.control_box import ControlBox from hysop.domain.subsets import Subset from hysop.numerics.differential_operations import Laplacian -from hysop.numerics.finite_differences import FD_C_2 +from hysop.numerics.finite_differences import FDC2 import numpy as np @@ -462,8 +462,8 @@ class NocaForces(Forces): res[i_n] += self._coeff * self.nu * normal * npw.real_sum(buff) # function used to compute first derivative of # a scalar field in a given direction. - # Default = FD_C_2. Todo : set this as an input method value. - fd_scheme = FD_C_2(self._topology.mesh.space_step, ind, + # Default = FDC2. Todo : set this as an input method value. + fd_scheme = FDC2(self._topology.mesh.space_step, ind, reduce_output_shape=True) fd_scheme.compute(vd[i_n], i_n, buff) res[i_n] += 2.0 * normal * self.nu * npw.real_sum(buff) diff --git a/hysop/operator/discrete/reprojection.py b/hysop/operator/discrete/reprojection.py index a883d293c968ff713e784013010e3adb405d247e..86506809712df2b94b312f4d3e7aa85d334a86a7 100644 --- a/hysop/operator/discrete/reprojection.py +++ b/hysop/operator/discrete/reprojection.py @@ -7,7 +7,7 @@ import numpy as np from hysop.constants import debug, HYSOP_MPI_REAL from hysop.methods_keys import SpaceDiscretisation from hysop.operator.discrete.discrete import DiscreteOperator -from hysop.numerics.finite_differences import FD_C_4 +from hysop.numerics.finite_differences import FDC4 from hysop.numerics.differential_operations import GradV import hysop.tools.numpywrappers as npw from hysop.numerics.update_ghosts import UpdateGhosts @@ -29,7 +29,7 @@ class Reprojection(DiscreteOperator): @param frequency : set frequency of execution of the reprojection """ if 'method' in kwds and kwds['method'] is None: - kwds['method'] = {SpaceDiscretisation: FD_C_4} + kwds['method'] = {SpaceDiscretisation: FDC4} ## vorticity field self.vorticity = vorticity diff --git a/hysop/operator/drag_and_lift.py b/hysop/operator/drag_and_lift.py index b20ff77544129586c3a039220ec9271186a00121..f0580dd042885e1873d223325edb6b99d1dcf1f1 100755 --- a/hysop/operator/drag_and_lift.py +++ b/hysop/operator/drag_and_lift.py @@ -201,11 +201,11 @@ class NocaForces(Forces): import hysop.default_methods as default self.method = default.FORCES from hysop.methods_keys import SpaceDiscretisation - from hysop.numerics.finite_differences import FD_C_4, FD_C_2 + from hysop.numerics.finite_differences import FDC4, FDC2 assert SpaceDiscretisation in self.method.keys() - if SpaceDiscretisation is FD_C_2: + if SpaceDiscretisation is FDC2: self._min_ghosts = 1 - elif SpaceDiscretisation is FD_C_4: + elif SpaceDiscretisation is FDC4: self._min_ghosts = 2 if surfdir is None: diff --git a/hysop/operator/forcing.py b/hysop/operator/forcing.py index bfe03b4e5bf98f0ef60b389dc6608df88f858651..d5cf8314209699b25400d22fb62258d8711dafbc 100644 --- a/hysop/operator/forcing.py +++ b/hysop/operator/forcing.py @@ -14,8 +14,8 @@ from hysop.constants import debug from hysop.operator.continuous import opsetup import hysop.default_methods as default from hysop.methods_keys import SpaceDiscretisation -from hysop.numerics.finite_differences import FD_C_4,\ - FD_C_2 +from hysop.numerics.finite_differences import FDC4,\ + FDC2 from hysop.operator.differential import Curl from hysop.fields.continuous import Field @@ -113,11 +113,11 @@ class ForcingConserv(Forcing): def discretize(self): - if self.method[SpaceDiscretisation] is FD_C_4: + if self.method[SpaceDiscretisation] is FDC4: # Finite differences method # Minimal number of ghost points nb_ghosts = 2 - elif self.method[SpaceDiscretisation] is FD_C_2: + elif self.method[SpaceDiscretisation] is FDC2: nb_ghosts = 1 else: raise ValueError("Unknown method for space discretization of the\ diff --git a/hysop/operator/low_pass_filt.py b/hysop/operator/low_pass_filt.py index 91f03f28be47654913a9af35b81b612e455cf9ed..a86381ce800cef3ef4aab3a5ecd0dfe2d85b4ecb 100644 --- a/hysop/operator/low_pass_filt.py +++ b/hysop/operator/low_pass_filt.py @@ -13,8 +13,8 @@ from hysop.constants import debug from hysop.operator.continuous import opsetup import hysop.default_methods as default from hysop.methods_keys import SpaceDiscretisation -from hysop.numerics.finite_differences import FD_C_4,\ - FD_C_2 +from hysop.numerics.finite_differences import FDC4,\ + FDC2 from hysop.operator.differential import Curl from hysop.fields.continuous import Field @@ -110,11 +110,11 @@ class LowPassFiltConserv(LowPassFilt): def discretize(self): - if self.method[SpaceDiscretisation] is FD_C_4: + if self.method[SpaceDiscretisation] is FDC4: # Finite differences method # Minimal number of ghost points nb_ghosts = 2 - elif self.method[SpaceDiscretisation] is FD_C_2: + elif self.method[SpaceDiscretisation] is FDC2: nb_ghosts = 1 else: raise ValueError("Unknown method for space discretization of the\ diff --git a/hysop/operator/multiphase_gradp.py b/hysop/operator/multiphase_gradp.py index f3ad480e5fa1c43fb265cef3e340bf366e6c1091..a9411d3469a67a446ff14ed0c889263d4a5a39d2 100644 --- a/hysop/operator/multiphase_gradp.py +++ b/hysop/operator/multiphase_gradp.py @@ -9,7 +9,7 @@ Computation of the pressure gradient in a multiphasic flow: """ from hysop.operator.computational import Computational from hysop.methods_keys import SpaceDiscretisation -from hysop.numerics.finite_differences import FD_C_4 +from hysop.numerics.finite_differences import FDC4 from hysop.constants import debug, np import hysop.default_methods as default from hysop.operator.continuous import opsetup @@ -51,7 +51,7 @@ class MultiphaseGradP(Computational): assert SpaceDiscretisation in self.method.keys() def discretize(self): - if self.method[SpaceDiscretisation] is FD_C_4: + if self.method[SpaceDiscretisation] is FDC4: nbGhosts = 2 else: raise ValueError("Unknown method for space discretization of the\ diff --git a/hysop/operator/penalization.py b/hysop/operator/penalization.py index 2cabff25dfc17f6885c3aa148dd4b6bce23052f4..bb5e73c66fb772f122e70807f1841cb2aa2eff52 100644 --- a/hysop/operator/penalization.py +++ b/hysop/operator/penalization.py @@ -18,8 +18,8 @@ from hysop.operator.continuous import opsetup from hysop.domain.subsets import Subset import hysop.default_methods as default from hysop.methods_keys import SpaceDiscretisation -from hysop.numerics.finite_differences import FD_C_4,\ - FD_C_2 +from hysop.numerics.finite_differences import FDC4,\ + FDC2 from hysop.operator.differential import Curl from hysop.fields.continuous import Field @@ -139,11 +139,11 @@ class PenalizeVorticity(Penalization): def discretize(self): - if self.method[SpaceDiscretisation] is FD_C_4: + if self.method[SpaceDiscretisation] is FDC4: # Finite differences method # Minimal number of ghost points nb_ghosts = 2 - elif self.method[SpaceDiscretisation] is FD_C_2: + elif self.method[SpaceDiscretisation] is FDC2: nb_ghosts = 1 else: raise ValueError("Unknown method for space discretization of the\ diff --git a/hysop/operator/stretching.py b/hysop/operator/stretching.py index 5320c192e7912fcf210cbf13eb0e44d2bc06692a..ad6371f311f2d86a9ef0fa8f5985a609ac341948 100755 --- a/hysop/operator/stretching.py +++ b/hysop/operator/stretching.py @@ -11,7 +11,7 @@ See also from hysop.constants import debug from hysop.methods_keys import TimeIntegrator, Formulation, \ SpaceDiscretisation -from hysop.numerics.finite_differences import FD_C_4 +from hysop.numerics.finite_differences import FDC4 from hysop.operator.computational import Computational from hysop.operator.continuous import opsetup from hysop.operator.discrete.stretching import Conservative, GradUW @@ -113,7 +113,7 @@ class Stretching(Computational): @debug def discretize(self): - if self.method[SpaceDiscretisation] is FD_C_4: + if self.method[SpaceDiscretisation] is FDC4: nbghosts = 2 else: raise ValueError("Unknown method for space discretization of the\ @@ -175,7 +175,7 @@ class StretchingLinearized(Stretching): @debug def discretize(self): - if self.method[SpaceDiscretisation] is FD_C_4: + if self.method[SpaceDiscretisation] is FDC4: nbghosts = 2 else: raise ValueError("Unknown method for space discretization of the\ diff --git a/hysop/operator/tests/test_Stretching.py b/hysop/operator/tests/test_Stretching.py index 159d506352946f3fabbb1be902459aa9a73ebf7c..ad76dca56e977ee3d6bf9f4a2d226d7213b3e0be 100755 --- a/hysop/operator/tests/test_Stretching.py +++ b/hysop/operator/tests/test_Stretching.py @@ -7,7 +7,7 @@ from hysop.operator.stretching import Stretching, \ from hysop.problem.simulation import Simulation from hysop.methods_keys import TimeIntegrator, Formulation,\ SpaceDiscretisation -from hysop.methods import Euler, RK3, FD_C_4, Conservative +from hysop.methods import Euler, RK3, FDC4, Conservative from hysop.tools.parameters import Discretization import hysop.tools.numpywrappers as npw pi = np.pi @@ -116,7 +116,7 @@ def test_stretching(): # Operators #method = {TimeIntegrator: RK3, Formulation: Conservative, - # SpaceDiscretisation: FD_C_4} + # SpaceDiscretisation: FDC4} stretch = Stretching(velo, vorti, discretization=nbElem) stretch.discretize() topo = stretch.discreteFields[velo].topology @@ -199,7 +199,7 @@ def test_stretching_external_work(): # Operators #method = {TimeIntegrator: RK3, Formulation: Conservative, - # SpaceDiscretisation: FD_C_4} + # SpaceDiscretisation: FDC4} stretch = Stretching(velo, vorti, discretization=nbElem) stretch.discretize() wk_p = stretch.get_work_properties() diff --git a/hysop/operator/tests/test_differential.py b/hysop/operator/tests/test_differential.py index 2ab50a59af60b251ff00bf1df7ff428f866b7aab..9eaa3895b537fd371434e01bcad3d3fd734697d3 100755 --- a/hysop/operator/tests/test_differential.py +++ b/hysop/operator/tests/test_differential.py @@ -6,7 +6,7 @@ from hysop.domain.box import Box from hysop.fields.continuous import Field import hysop.tools.numpywrappers as npw from hysop.methods_keys import SpaceDiscretisation -from hysop.methods import FD_C_4, FD_C_2 +from hysop.methods import FDC4, FDC2 from hysop.operator.differential import Curl, Grad, DivAdvection from hysop.tools.parameters import Discretization @@ -154,28 +154,28 @@ def call_op_fft(class_name, ref_formula, dom, discr, def test_curl_fd_1(): - method = {SpaceDiscretisation: FD_C_4} + method = {SpaceDiscretisation: FDC4} call_op(Curl, vorticity_f, topo1_3d, method=method) def test_curl_fd_2(): - method = {SpaceDiscretisation: FD_C_2} + method = {SpaceDiscretisation: FDC2} call_op(Curl, vorticity_f, topo1_3d, method=method, order=2) def test_curl_fd_1_2d(): - method = {SpaceDiscretisation: FD_C_4} + method = {SpaceDiscretisation: FDC4} call_op(Curl, vorticity_f2d, topo1_2d, method=method, op_dim=1, vform=velocity_f2d) def test_curl_fd_3(): - method = {SpaceDiscretisation: FD_C_4} + method = {SpaceDiscretisation: FDC4} call_op(Curl, vorticity_f, topo3_3d, method=method) def test_curl_fd_3_2d(): - method = {SpaceDiscretisation: FD_C_4} + method = {SpaceDiscretisation: FDC4} call_op(Curl, vorticity_f2d, topo3_2d, op_dim=1, method=method, vform=velocity_f2d) @@ -214,28 +214,28 @@ def test_curl_fft_1(): def test_grad_1(): - method = {SpaceDiscretisation: FD_C_2} + method = {SpaceDiscretisation: FDC2} call_op(Grad, grad_velo, topo1_3d, op_dim=9, method=method, order=2) def test_grad_2(): - method = {SpaceDiscretisation: FD_C_4} + method = {SpaceDiscretisation: FDC4} call_op(Grad, grad_velo, topo1_3d, op_dim=9, method=method) def test_grad_3(): - method = {SpaceDiscretisation: FD_C_2} + method = {SpaceDiscretisation: FDC2} call_op(Grad, grad_velo, topo3_3d, op_dim=9, method=method, order=2) def test_grad_3_2d(): - method = {SpaceDiscretisation: FD_C_4} + method = {SpaceDiscretisation: FDC4} call_op(Grad, grad_velo_2d, topo3_2d, op_dim=4, method=method, vform=velocity_f2d) def test_curl_fd_work(): - method = {SpaceDiscretisation: FD_C_4} + method = {SpaceDiscretisation: FDC4} call_op(Curl, vorticity_f, topo3_3d, use_work=True, method=method) @@ -246,5 +246,5 @@ def divadvection_func(res, x, y, z, t): def test_div_advection(): - method = {SpaceDiscretisation: FD_C_4} + method = {SpaceDiscretisation: FDC4} call_op(DivAdvection, divadvection_func, topo3_3d, op_dim=1, method=method) diff --git a/hysop/operator/tests/test_multiphase_gradp.py b/hysop/operator/tests/test_multiphase_gradp.py index 1f8fc2e1f22d1a6a8d5adafc63f3422c415f7c00..d3e583c3ca297d6dc7680e3664f3c7a21b1a5de9 100755 --- a/hysop/operator/tests/test_multiphase_gradp.py +++ b/hysop/operator/tests/test_multiphase_gradp.py @@ -4,7 +4,7 @@ from hysop.tools.parameters import Discretization from hysop.domain.box import Box from hysop.fields.continuous import Field from hysop.operator.multiphase_gradp import MultiphaseGradP -from hysop.numerics.finite_differences import FD_C_4, FD_C_2 +from hysop.numerics.finite_differences import FDC4, FDC2 import hysop.tools.numpywrappers as npw import numpy as np from hysop.methods_keys import Support, SpaceDiscretisation, ExtraArgs