diff --git a/docs/sphinx/conf.py.in b/docs/sphinx/conf.py.in index 31fe2749ff73432ec2b93c543c466235a800adf2..8399b4a984cfc674a93c06e90e22f278927f4e77 100644 --- a/docs/sphinx/conf.py.in +++ b/docs/sphinx/conf.py.in @@ -185,10 +185,10 @@ html_static_path = ['_static'] # '**': ['menu.html',],# 'searchbox.html'], # 'using/windows': ['windowssidebar.html', 'searchbox.html'], #} -html_sidebars = { - '**': ['menu.html',],# 'searchbox.html'], -# 'using/windows': ['windowssidebar.html', 'searchbox.html'], -} +# html_sidebars = { +# '**': ['menu.html', ],# 'searchbox.html'], +# 'using/windows': ['windowssidebar.html', 'searchbox.html'], +# } # Additional templates that should be rendered to pages, maps page names to # template names. diff --git a/docs/sphinx/hysop.bib b/docs/sphinx/hysop.bib index 5ba5c1351f9b04a32d262f71e1ef471f682db7a9..63a5a0eae611353ecdb131dcf8a714f378faf3d6 100644 --- a/docs/sphinx/hysop.bib +++ b/docs/sphinx/hysop.bib @@ -42,3 +42,10 @@ Title = {A comparison of methods for evaluating time-dependent fluid dynamic forces on bodies, using only velocity fields and their derivatives}, Volume = {13}, Year = {1999}} + +@misc{cottet2000vortex, + title={Vortex methods: theory and practice}, + author={Cottet, Georges-Henri and Koumoutsakos, Petros D}, + year={2000}, + publisher={Cambridge University Press} +} \ No newline at end of file diff --git a/docs/sphinx/install_guide/index.rst b/docs/sphinx/install_guide/index.rst new file mode 100644 index 0000000000000000000000000000000000000000..4e6ed9939f2779d0577feba7632894921c216f82 --- /dev/null +++ b/docs/sphinx/install_guide/index.rst @@ -0,0 +1,80 @@ +.. hysop_install_guide: + +HySoP installation guide +======================== + + +HySoP is written in Python (main user interface and high level functionnalities) and Fortran. + +Quick start and install +----------------------- + +:: + + cd path_to_build + cmake path_to_sources + make -j N + make install + +Note: + +* -jN for make command runs the build process on N processes. Choose a value of N that fits with your machine. +* depending on your system you may need to set PYTHONPATH to where hysop has been installed:: + + export PYTHONPATH=hysop_install_path:${PYTHONPATH} + + Check the end of cmake output, where the proper command will be indicated. + + + + +Then just run python interactively and :: + + + >>> import hysop + >>> dir(hysop) + + +or run python on an hysop example file:: + + + mpirun -np 4 python your_file.py + + +.. _hysop_config: + +Configuration options +--------------------- + +cmake configuration may be customized by user, using:: + + cmake -DOPTION_NAME=option_value path_to_source + +'OPTION_NAME' being one of the options described below. + +* FFTW_DIR : where to find fftw if it's not in a "standard" place. +* WITH_SCALES=ON/OFF : to compile an HySoP version including scales (default = on) +* WITH_TESTS=ON/OFF: enable testing (i.e. prepare target "make test", default = off) + + +.. _hysop_dependencies: + +Dependencies +------------ + +* python > 2.7 +* a proper mpi implementation including a fortran compiler +* fftw +* cmake > 2.8 +* numpy, mpi4py, h5py + + +.. _hysop_install: + +What will be installed +---------------------- + +* python package in PREFIX/lib/pythonX.Y/site-packages/hysop/ +* library in PREFIX/lib/pythonX.Y/site-packages/hysop/lib +* fortran modules in PREFIX/lib/pythonX.Y/site-packages/hysop/include/Modules +* CMake configuration files in PREFIX/lib/pythonX.Y/site-packages/hysop/share/CMake diff --git a/docs/sphinx/users_guide/absorption_bc.rst b/docs/sphinx/users_guide/absorption_bc.rst index c50a907f0e27d5b2e1b7ef64a3b730b945acda2f..1f16a5490d04810b789d19757ff1a67c2d593ebf 100644 --- a/docs/sphinx/users_guide/absorption_bc.rst +++ b/docs/sphinx/users_guide/absorption_bc.rst @@ -17,11 +17,11 @@ where f is the smoothing function defined as follows : .. math:: - f(x) = \begin{cases} + f(x) = \begin{cases} 1, \text{ if } x < x_b\\ - \frac{tanh(\epsilon(x - x_c)) - tanh(\epsilon(x_e - x_c))}, \text{ if } x_b < x < x_e \\ + \frac{tanh(\epsilon(x - x_c)) - tanh(\epsilon(x_e - x_c))}{tanh(\epsilon(x_b - x_c)) - tanh(\epsilon(x_e - x_c))}, \text{ if } x_b < x < x_e \\ 0 \text{ if } x > x_e - \end{cases} + \end{cases} with :math:`x_c = \frac{x_b + x_e}{2}` (we refer to the figure below for a schematic description of the absorption process). @@ -56,3 +56,36 @@ not the case when the vorticity is absorbed as follows : Indeed, defining the absorbed vorticity as the curl of the absorbed velocity to project the vorticity in the space of divergence free vector fields (see :ref:`vorticity_projection`). In practice, vorticity absorption based on equation 6 is responsible for reflexion effects and produces spurious oscillations (see drag plots for instance). From an algorithmic point of view, the vorticity absorption is applied before solving the Poisson equation. + + +The corresponding operator is :class:AbsorptionBC`, build with the standard parameters of all operators, plus: + +* a float, req_flow_rate, to set required value of the flow rate at the outlet. +* a 'x_range' vector, to set the coordinates delimitating the absorption domain, x_range=[xb, xe] +* an optional 'filter_func' parameter, list of two python functions, used to set the filter function and its derivative + + +Example:: + + d3d = Discretization([33, 33, 33]) + dom = Box([1., ] * dim) + v = Field(dom, name='velo', is_vector=True) + w = Field(dom, name='vorti', is_vector=True) + # -- Build and apply absorption operator on w -- + # set flowrate + flowrate = VariableParameter(data=10.) + # set layer size + x_range = [0.9, 1.] + op = AbsorptionBC(v, w, flowrate, x_range, + discretization=d3d) + op.discretize() + op.setup() + + simu = Simulation(nb_iter=100) + simu.initialize() + + op.apply(simu) + + +One may also choose user-defined functions to apply in the absorption area (in place of the tanh-like function shown above). +See the example in test_absorption_bc.py file. diff --git a/docs/sphinx/users_guide/custom.rst b/docs/sphinx/users_guide/custom.rst new file mode 100644 index 0000000000000000000000000000000000000000..74499c519d2aa96d0e3463d3b909efcf0746b926 --- /dev/null +++ b/docs/sphinx/users_guide/custom.rst @@ -0,0 +1,44 @@ +.. _custom: + +User-defined operator +===================== + +A specific operator class, :class:`~hysop.operator.custom.Custom` is available in hysop to allow users to +define their own operator.apply, thanks to a python function. + + +.. code:: + + # v1, v2, v3 some continuous fields + iop = IOParams('somefile.dat', fileformat=IO.ASCII) + my_op = Custom(function=my_function, in_fields=[v1, v2], out_fields=[v3], + diagnostics_shape=(1,2), io_params=iop, ...) + my_op.discretize() + my_op.setup() + + simu = Simulation(nb_iter=10) + my_op.apply(simu) + + +A call to my_op.apply(simu) will run 'my_func(simu, [v1, v2], [v3], buffer)' +and write 'buffer' into a file (defined as usual with iop). + +* my_func arguments list MUST match the following:: + + def my_func(sim, in_fields, out_fields=None, diagnostics=None): + # optionally compute out_fields depending on in_fields + out_fields[0].data[1] = 2 * in_fields[0].data[0] + # optionally compute some diagnostics + diagnostics[0,0] = sim.time + diagnostics[0,1] = out_fields[0].data[0].max() + +* diagnostics_shape arg must corresponds to the shape of the buffer written in the function + and buffer must be a 2D array (i.e. diagnostics_shape a tuple like (nx, ny)). + +* if diagnostics_shape is None, no file output will be done and obviously in that case, + diagnostics must not be filled in my_func + +* as usual real use-case are available in operator/test/test_custom.py + + + diff --git a/docs/sphinx/users_guide/operators.rst b/docs/sphinx/users_guide/operators.rst index a9107f4226a2cffeb9d3e54cddd356477342797d..861af66d70722a7d53c6996b431b894d10872465 100644 --- a/docs/sphinx/users_guide/operators.rst +++ b/docs/sphinx/users_guide/operators.rst @@ -116,3 +116,4 @@ Review advection stretching energy_enstrophy + custom diff --git a/docs/sphinx/users_guide/stretching.rst b/docs/sphinx/users_guide/stretching.rst index 79d00d7f01a686a53192459cfc7bcc1b0a86e7da..c8a37b0e951aa5177e595d804734a51f00e21a25 100644 --- a/docs/sphinx/users_guide/stretching.rst +++ b/docs/sphinx/users_guide/stretching.rst @@ -4,6 +4,19 @@ Stretching ========== .. currentmodule:: hysop.operator.stretching + +The stretching equation, :math:`\frac{\partial\omega}{\partial t} = (\omega.\nabla)u` +which models the lengthening of vortices in a three-dimensional flow, +may be given under several formulations :cite:`Cottet2000vortex`: + + +.. math:: + + \frac{\partial\omega}{\partial t} &=& [\nabla u] . \omega \\ + &=& [\nabla u]^T . \omega \\ + &=& \nabla.(\omega:u) + + Solve @@ -20,7 +33,7 @@ Two formulations are proposed : .. math:: - \frac{\partial \omega}{\partial t} = (\omega .\nabla)u + \frac{\partial \omega}{\partial t} = [\nabla u]^T . \omega The default is 'conservative'. @@ -46,10 +59,35 @@ TO BE REVIEWED Linearized Stretching --------------------- -Specific formulation to solve the linearized stretching equation, +In the context of a global linear stability study of the Navier-Stokes equation, one may have to formulate and solve +a "linearized stretching". See details in :ref:`global_linear_stability`. + +Let us decompose the vorticity and the velocity fields into the sum of the steady state solution, :math:`(.)_b`, and a perturbation, +:math:`(.)'`: .. math:: - \frac{\partial \omega}{\partial t} &=& (\omega \cdot \nabla)u_b + (\om_b \cdot \nabla)u + (\omega,u) = (\omega' + \omega_b, u' + u_b) + +then the stretching part of the governing equations writes: + +.. math:: + + \frac{\partial\omega'}{\partial t} = \underbrace{(\omega'\cdot\nabla)u_b}_{A} + \underbrace{(\omega_b\cdot\nabla)u'}_{B} + + +The corresponding operator is :class:`StretchingLinearized`, built with the same parameters as for the standard stretching +plus two fields corresponding to the steady state part of the velocity and the vorticity ('BF' below stands for 'Base Flow'): + + +.. code:: + + stretch_lin = StretchingLinearized(velocity_BF=v_b, vorticity_BF=w_b, + velocity=v, vorticity=w, ...) + + +Notice that time-integrator for part A of the equation above is user-defined but set to Euler scheme for part B. + + diff --git a/hysop/constants.py.in b/hysop/constants.py.in new file mode 100644 index 0000000000000000000000000000000000000000..2dda2f611000d144d3f26f9a12a1505e2edeb4a6 --- /dev/null +++ b/hysop/constants.py.in @@ -0,0 +1,135 @@ +"""Default values for constant parameters used +in hysop package. + +Mostly deals with float/int numbers precision and +some labels for numerical methods and operators. + +This file is generated from constants.py.in +and it's probably a bad idea to modify it. + +""" +from hysop import __DEBUG__, __PROFILE__ +import numpy as np +import math +__MPI_ENABLED__ = "@USE_MPI@" is "ON" +if __MPI_ENABLED__: + from hysop.mpi import MPI + +PI = math.pi + +HYSOP_REAL = @PYTHON_PREC@ +"""Set default type for real and integer numbers""" + +SIZEOF_HYSOP_REAL = int(HYSOP_REAL(1.).nbytes) +"""Size in memory of hysop real default type""" + +HYSOP_INDEX = np.uint32 +"""type for array indices""" + +HYSOP_INTEGER = np.int32 +"""type for integers""" + +HYSOP_DIM = np.int16 +"""integer used for arrays dimensions""" + +if __MPI_ENABLED__: + HYSOP_MPI_REAL = @MPI_PYTHON_PREC@ + """float type used in MPI""" + + HYSOP_MPI_INTEGER = MPI.INT + """integer type used in MPI""" + + ORDERMPI = @MPI_DATA_LAYOUT@ + """Default array layout for MPI""" + + +ORDER = @DATA_LAYOUT@ +"""default array layout (fortran or C convention)""" + +EPS = np.finfo(HYSOP_REAL).eps +"""machine epsilon for HYSOP_REAL""" + +# to check array ordering with : +# assert tab.flags.f_contiguous is CHECK_F_CONT +if ORDER is 'F': + CHECK_F_CONT = True + """True if array layout is fortran""" +else: + CHECK_F_CONT = False + +XDIR = 0 +"""label for x direction""" + +YDIR = 1 +"""label for y direction""" + +ZDIR = 2 +"""label for z direction""" + +PERIODIC = 99 +"""Tag for periodic boundary conditions""" + +S_DIR = ["_X", "_Y", "_Z"] +"""Directions string""" + +WITH_GUESS = 1 +""" +Optimisation level for time integrators : +no need to recompute the right-hand side, an initial guess +must be given in input arguments. + """ + +NOALIAS = 2 +"""Optimisation level for time integrators : +no need to recompute the right-hand side, an initial guess +must be given in input arguments and we ensure that +y is different from result arg. +""" + +DEFAULT_TASK_ID = 999 +"""Default value for task id (mpi task)""" + + +def _debugdecorator(f): + if __DEBUG__: + # function f is being decorated + def decorator(*args, **kw): + # Print informations on decorated function + if f.__name__ is '__new__': + fullclassname = args[0].__mro__[0].__module__ + '.' + fullclassname += args[0].__mro__[0].__name__ + print ('Instanciate :', fullclassname,) + print (' (Inherits from : ',) + print ([c.__name__ for c in args[0].__mro__[1:]], ')') + else: + print ('Call : ', f.__name__, 'in ', f.__code__.co_filename,) + print (f.__code__.co_firstlineno) + # Calling f + r = f(*args, **kw) + if f.__name__ is '__new__': + print (' |-> : ', repr(r)) + return r + return decorator + else: + #define empty debug decorator: + return f + +debug = _debugdecorator +"""Debug decorator + +Usage: @debug before function definition you want to debug +""" + +# redefine profile decorator +if __PROFILE__: + from memory_profiler import profile + prof = profile + """Profiling decorator + + Usage: @profile before function you want to profile + """ + +else: + def prof(f): + # Nothing ... + return f diff --git a/hysop/default_methods.py b/hysop/default_methods.py index df41a328e367e5f79221d04f65ae1954c4646eb2..ad08c9a7434d4ce5a960de1101afa6b403dc74a8 100644 --- a/hysop/default_methods.py +++ b/hysop/default_methods.py @@ -9,8 +9,7 @@ from hysop.numerics.interpolation import Linear from hysop.numerics.remeshing import L2_1, Linear as Rmsh_Linear from hysop.numerics.finite_differences import FDC4, FDC2 from hysop.problem.simulation import O2 - -#from hysop.operator.discrete.stretching import Conservative +from hysop.operator.discrete.stretching import Conservative ADVECTION = {TimeIntegrator: RK2, Interpolation: Linear, @@ -44,7 +43,7 @@ POISSON = {SpaceDiscretisation: 'fftw', GhostUpdate: True, """Poisson operators default setup """ -STRETCHING = {TimeIntegrator: RK3, Formulation: "Conservative", +STRETCHING = {TimeIntegrator: RK3, Formulation: Conservative, SpaceDiscretisation: FDC4} """Stretching operators default setup """ diff --git a/hysop/f2hysop.pyf.in b/hysop/f2hysop.pyf.in new file mode 100644 index 0000000000000000000000000000000000000000..a11194e7df7e5f7f02bb55b202ff01bf3faa85e9 --- /dev/null +++ b/hysop/f2hysop.pyf.in @@ -0,0 +1,20 @@ +! -*- f90 -*- + +! Generated file - Do not edit. + +! Note: the context of this file is case sensitive. + +python module f2hysop ! in + + interface + ! Example + include '@CMAKE_SOURCE_DIR@/hysop/fortran/template.pyf' + ! precision + include '@CMAKE_SOURCE_DIR@/hysop/f2py/parameters.pyf' + ! fftw + include '@CMAKE_SOURCE_DIR@/hysop/f2py/fftw2py.pyf' + ! scales + include '@CMAKE_SOURCE_DIR@/hysop/f2py/scales2py.pyf' + end interface + +end python module f2hysop \ No newline at end of file diff --git a/hysop/methods.py b/hysop/methods.py index 65e2e9b0d27c63fb24d3b907552c59348027e5c1..3437bc3c028e446e9998f3f2f82c91a593c8145d 100644 --- a/hysop/methods.py +++ b/hysop/methods.py @@ -23,6 +23,11 @@ that can be imported by final user. """ import hysop.numerics.odesolvers as odesolvers +import hysop.numerics.interpolation as interpolation +import hysop.numerics.remeshing as remesh +import hysop.numerics.finite_differences as fd +import hysop.operator.discrete.stretching as strd + RK2 = odesolvers.RK2 """Runge-Kutta 2 integration""" @@ -36,7 +41,6 @@ Euler = odesolvers.Euler """Euler integration""" # Remesh -import hysop.numerics.remeshing as remesh L2_1 = remesh.L2_1 L2_2 = remesh.L2_2 L2_3 = remesh.L2_3 @@ -54,16 +58,13 @@ Rmsh_Linear = remesh.Linear # A completer ... # Interpolation -import hysop.numerics.interpolation as interpolation Linear = interpolation.Linear # Finite differences -import hysop.numerics.finite_differences as fd FDC4 = fd.FDC4 FDC2 = fd.FDC2 FD2C2 = fd.FD2C2 # Stretching formulations -import hysop.operator.discrete.stretching as strd Conservative = strd.Conservative GradUW = strd.GradUW diff --git a/hysop/operator/absorption_bc.py b/hysop/operator/absorption_bc.py index 8e9c46f9f07f7953bb8bbaedf69e3ba46cc2613d..7927106886d195c24400774e63981f62bc062eab 100755 --- a/hysop/operator/absorption_bc.py +++ b/hysop/operator/absorption_bc.py @@ -3,6 +3,8 @@ by vorticity absorption in order to set the far field velocity to u_inf at the inlet) +See :ref:`absorption_bc`. + """ from hysop.constants import debug from hysop.operator.discrete.absorption_bc import AbsorptionBC as Dab @@ -119,3 +121,6 @@ class AbsorptionBC(Computational): self._set_io('absorption_BC', (1, 2 + self.domain.dimension)) self.discrete_op.set_writer(self._writer) self._is_uptodate = True + + def wait(self): + print "TEMP WAIT FOR TEST" diff --git a/hysop/operator/analytic.py b/hysop/operator/analytic.py index 9e3cf0c179ac01ca4c7b59090299efe19597c9ff..46cbe93fbba2e327fe1bc49490d940536cca0956 100644 --- a/hysop/operator/analytic.py +++ b/hysop/operator/analytic.py @@ -1,6 +1,4 @@ -""" -@file operator/analytic.py -Initialize fields on a grid, with a user-defined function +"""Initialize fields on a grid, with a user-defined function """ from hysop.constants import debug from hysop.operator.continuous import opsetup, opapply @@ -15,18 +13,27 @@ class Analytic(Computational): @debug def __init__(self, formula=None, vectorize_formula=False, **kwds): - """ - Operator to apply a user-defined formula onto a list of fields. - @param formula : the formula to be applied - @param vectorize_formula : true if formula must be vectorized (numpy), - default = false. + """ Apply a user-defined formula onto a list of fields. + + Parameters + ---------- + formula : python function + the formula to be applied + vectorize_formula : boolean, optional + true if formula must be vectorized (numpy), default = false. + + Notes + ----- + see :ref:`analytical_operator` for details on + the authorized signature for input formula or check + test_analytic.py """ super(Analytic, self).__init__(**kwds) isGPU = False if 'method' in kwds.keys() and Support in kwds['method'].keys(): isGPU = kwds['method'][Support].find('gpu') >= 0 if formula is not None: - ## A formula applied to all variables of this operator + # A formula applied to all variables of this operator self.formula = formula for v in self.variables: v.set_formula(formula, vectorize_formula) diff --git a/hysop/operator/baroclinic.py b/hysop/operator/baroclinic.py index 7937b55a558377a6420c858b106630bfb1aed6c5..83ff508e7f5e7d960a1b2026b398698135497955 100644 --- a/hysop/operator/baroclinic.py +++ b/hysop/operator/baroclinic.py @@ -75,6 +75,8 @@ class Baroclinic(Computational): self._is_uptodate = True - def initialize_velocity(self): self.discrete_op.initialize_velocity() + + def get_work_properties(self): + return {'rwork': None, 'iwork': None} diff --git a/hysop/operator/continuous.py b/hysop/operator/continuous.py index 65623755a9f7b67f2493164d63cc20dba0f61754..055497d796bde3676e6885ca0317f47efafdd8cb 100755 --- a/hysop/operator/continuous.py +++ b/hysop/operator/continuous.py @@ -266,11 +266,8 @@ class Operator(object): # default values for iop self.io_params = IOParams(filename, fileformat=IO.ASCII) else: - if self.io_params.fileformat is not IO.ASCII: - self.io_params.fileformat = IO.ASCII - msg = 'Warning, wrong file format for operator output.' - msg += 'This will be reset to ASCII.' - print msg + msg = 'Error, wrong file format for operator output.' + assert self.io_params.fileformat is IO.ASCII, msg self._writer = io.Writer(io_params=self.io_params, mpi_params=self._mpis, buffshape=buffshape) @@ -322,8 +319,8 @@ def opapply(f): """decorate 'apply' method""" # get 'continuous' base class and run its apply function # --> call wait function of ops in wait_list - t0 = ftime() name = inspect.getmro(args[0].apply.im_class) + t0 = ftime() name[-2].apply(args[0]) #t0 = ftime() res = f(*args, **kwargs) diff --git a/hysop/operator/custom.py b/hysop/operator/custom.py index 5af161e895e8daab3d2fd387bbd7a37ce7a821d2..8fdc409f89646021533725e6b5474e7a23dad8bf 100644 --- a/hysop/operator/custom.py +++ b/hysop/operator/custom.py @@ -1,45 +1,65 @@ -""" -@file custom.py +"""Interface to set a user-defined operator """ from hysop.operator.computational import Computational -from hysop.operator.discrete.custom import CustomMonitor as CM -from hysop.operator.discrete.custom import CustomOp as CO +from hysop.operator.discrete.custom import Custom as CO from hysop.operator.continuous import opsetup -class CustomOp(Computational): - def __init__(self, in_fields, out_fields, function, **kwds): - super(CustomOp, self).__init__(**kwds) +class Custom(Computational): + """User-defined generic operator + """ + def __init__(self, function, in_fields, out_fields=None, + diagnostics_shape=None, **kwds): + """ + + Parameters + ---------- + in_fields: list of :class:`~hysop.fields.discrete.DiscreteField` + input fields args. for function, see notes below + out_fields: list of :class:`~hysop.fields.discrete.DiscreteField` + output fields args for function, see notes below + function: python function + a user defined function, called by this op.apply method. + diagnostics_shape: tuple, optional + shape of the data expected to be written into file. + + Notes + ----- + A function is used to set the behavior of the current operator, + during apply call. + This function must look like:: + + def some_func(simulation, in_fields, out_fields, diagnostics=None): + # do things ... + + and compute out_fields values and optionnaly some diagnostics. + See :ref:`custom` + """ + super(Custom, self).__init__(**kwds) self.function = function self.input = in_fields - self.output = out_fields + if out_fields is not None: + self.output = out_fields + self._diagnostics_shape = diagnostics_shape + + def discretize(self): + super(Custom, self)._standard_discretize() @opsetup def setup(self, rwork=None, iwork=None): if not self._is_uptodate: - self.discretize() self.discrete_op = CO( - [self.discreteFields[f] for f in self.input], - [self.discreteFields[f] for f in self.output], - self.function, + in_fields=[self.discreteFields[f] for f in self.input], + out_fields=[self.discreteFields[f] for f in self.output], + function=self.function, variables=self.discreteFields.values()) - self._is_uptodate = True + if self._diagnostics_shape is not None: + assert isinstance(self._diagnostics_shape, tuple) + assert len(self._diagnostics_shape) == 2 + self._set_io(self.function.__name__, self._diagnostics_shape) + self.discrete_op.set_writer(self._writer) - -class CustomMonitor(Computational): - def __init__(self, function, res_shape=1, **kwds): - super(CustomMonitor, self).__init__(**kwds) - self.function = function - self.res_shape = res_shape - self.input = self.variables - - @opsetup - def setup(self, rwork=None, iwork=None): - if not self._is_uptodate: - self.discretize() - self.discrete_op = CM(self.function, self.res_shape, - variables=self.discreteFields.values()) - # Output setup - self._set_io(self.function.__name__, (1, 1 + self.res_shape)) - self.discrete_op.set_writer(self._writer) self._is_uptodate = True + + def get_work_properties(self): + return {'rwork': None, 'iwork': None} diff --git a/hysop/operator/discrete/__init__.py b/hysop/operator/discrete/__init__.py index 70f15434bdf7ca63593af802292c2fbb54364f1c..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 --- a/hysop/operator/discrete/__init__.py +++ b/hysop/operator/discrete/__init__.py @@ -1,24 +0,0 @@ -## @package hysop.operator.discrete -# Discrete operators classes. -# -# A DiscreteOperator is an object that represents the discretisation of a -# continuous operator for a specific given method and of its variables for -# some resolutions. -# -# Example: if we want to perform the advection of a scalar at -# velocity v using scales with M4 remesh, we define the following continuous -# operator : -#\code -# nbElem = [65, 65, 65] -# advec = Advection(velo, scal, -# resolutions={velo: nbElem, -# scal: nbElem}, -# method = 'scales, p_M4',) -# ... -# advec.setup() -# ... -# advec.apply() -# \endcode -# -# setup call will result in the creation of a ScalesAdvection operator -# and apply will perform a call to scale's solver. diff --git a/hysop/operator/discrete/custom.py b/hysop/operator/discrete/custom.py index 20b6aa4daf32ae48f394566a99509914fca27823..85929894c8827ed5a30e5fd182085b68abe2c715 100644 --- a/hysop/operator/discrete/custom.py +++ b/hysop/operator/discrete/custom.py @@ -1,28 +1,55 @@ +"""User-defined discrete operator""" + from hysop.operator.discrete.discrete import DiscreteOperator -class CustomOp(DiscreteOperator): - def __init__(self, in_fields, out_fields, function, **kwds): - super(CustomOp, self).__init__(**kwds) - self.function = function - self._in_fields = in_fields - self._out_fields = out_fields +class Custom(DiscreteOperator): + """User-defined operator: action defined by an external function. + """ + def __init__(self, function, in_fields, out_fields=None, **kwds): + """ - def apply(self, simulation): - self.function(simulation, self._in_fields, self._out_fields) + Parameters + ---------- + in_fields: list of :class:`~hysop.fields.discrete.DiscreteField` + input fields args. for function, see notes below + out_fields: list of :class:`~hysop.fields.discrete.DiscreteField` + output fields args for function, see notes below + function: python function + a user defined function, called by this op.apply method. + Notes + ----- + A function is used to set the behavior of the current operator, + during apply call. + This function must look like:: -class CustomMonitor(DiscreteOperator): - def __init__(self, function, res_shape=1, **kwds): - super(CustomMonitor, self).__init__(**kwds) + def some_func(simulation, in_fields, out_fields=None, diag=None): + # do things ... + + and compute out_fields values. + """ + # callback for apply function self.function = function - self.res_shape = res_shape + super(Custom, self).__init__(**kwds) + # in/out fields must obviously belong to variables + self.input = in_fields + if out_fields is not None: + self.input += out_fields + self.output = out_fields + msg = 'Custom: all in/out fields must belong to op variables.' + assert set(self.input).intersection(set(self.variables)) == \ + set(self.input), msg + self._in_fields = in_fields + self._out_fields = out_fields def apply(self, simulation=None): + if self._writer is not None: + diagnostics = self._writer.buffer + else: + diagnostics = None + self.function(simulation, self._in_fields, self._out_fields, + diagnostics) ite = simulation.current_iteration - values = self.function(simulation, - self.variables) if self._writer is not None and self._writer.do_write(ite): - self._writer.buffer[0, 0] = simulation.time - self._writer.buffer[0, 1:] = values self._writer.write() diff --git a/hysop/operator/discrete/profiles.py b/hysop/operator/discrete/profiles.py index 97e1a3682ab610f0e5e47577e42649eb3067b8a2..68373ef77a6365fc46cc7bf3366247cc953dba46 100644 --- a/hysop/operator/discrete/profiles.py +++ b/hysop/operator/discrete/profiles.py @@ -87,17 +87,6 @@ class Profiles(DiscreteOperator): assert self._rwork[0].shape == shape_v assert self._rwork[1].shape == shape_w - def get_work_properties(self): - - v_ind = self.velocity.topology.mesh.compute_index - w_ind = self.vorticity.topology.mesh.compute_index - shape_v = self.velocity.data[0][v_ind].shape - shape_w = self.velocity.data[0][w_ind].shape - if shape_v == shape_w: - return {'rwork': [shape_v], 'iwork': None} - else: - return {'rwork': [shape_v, shape_w], 'iwork': None} - @debug @profile def apply(self, simulation=None): diff --git a/hysop/operator/discrete/stretching.py b/hysop/operator/discrete/stretching.py index f35e2d07ba9d8d62abc9a869f9be13a68c7be3a8..4aebd947b92b94f861d514cbcb56c98116731de8 100755 --- a/hysop/operator/discrete/stretching.py +++ b/hysop/operator/discrete/stretching.py @@ -11,7 +11,7 @@ Formulations: from hysop.constants import debug, WITH_GUESS from hysop.methods_keys import TimeIntegrator, SpaceDiscretisation from hysop.operator.discrete.discrete import DiscreteOperator -import hysop.numerics.differential_operations as diff_op +from hysop.numerics.differential_operations import GradVxW, DivWV import hysop.tools.numpywrappers as npw from hysop.numerics.update_ghosts import UpdateGhosts from hysop.tools.profiler import profile @@ -30,13 +30,19 @@ class Stretching(DiscreteOperator): __metaclass__ = ABCMeta @debug - def __init__(self, velocity, vorticity, formulation, rhs, **kwds): + def __init__(self, velocity, vorticity, formulation, + rhs, extra_ghosts_fields=None, **kwds): """Abstract interface for stretching operator Parameters ---------- velocity, vorticity : :class:`~hysop.fields.discrete.DiscreteField` formulation : one of the discrete stretching classes. + rhs : python function + right-hand side for the time integrator + extra_ghosts_fields : int, optional + number of additional numpy arrays to be synchronized (mpi), + default = None, i.e. synchro of vorticity and velocity components. **kwds : extra parameters for base class """ @@ -69,9 +75,12 @@ class Stretching(DiscreteOperator): self.nb_components = 3 # Stretching only in 3D and for vector fields. # prepare ghost points synchro for velocity and vorticity + nb_ghosts_fields = self.velocity.nb_components + \ + self.vorticity.nb_components + if extra_ghosts_fields is not None: + nb_ghosts_fields += extra_ghosts_fields self._synchronize = UpdateGhosts(self.velocity.topology, - self.velocity.nb_components + - self.vorticity.nb_components) + nb_ghosts_fields) # A function to compute the gradient of the velocity. # Work vector is provided in input. @@ -161,8 +170,8 @@ class Conservative(Stretching): """ return self.strFunc(y, self.velocity.data, result) - super(Conservative, self).__init__(formulation=diff_op.DivWV, - rhs=rhs, **kwds) + super(Conservative, self).__init__( + formulation=DivWV, rhs=rhs, **kwds) @profile def _compute(self, dt, t): @@ -183,8 +192,7 @@ class GradUW(Stretching): self.strFunc(self.velocity.data, y, result, self.diagnostics) return result - super(GradUW, self).__init__(formulation=diff_op.GradVxW, - rhs=rhs, **kwds) + super(GradUW, self).__init__(formulation=GradVxW, rhs=rhs, **kwds) # stability constant # Depends on time integration method @@ -236,52 +244,61 @@ class StretchingLinearized(Stretching): UpdateGhosts(self.vorticity_BF.topology, self.vorticity_BF.nb_components) self.usual_op = usual_op + # boolean used to switch between two rhs forms: + # either rhs(t, y) = div(y:u) (if true) + # or rhs(t,y) = div(y:w_bf) (if false) + self._divwu = True - def rhs(t, y, result, form): + def rhs(t, y, result): """rhs used in time integrator """ - if form == "div(w:u)": + if self._divwu: result = self.strFunc(y, self.velocity.data, result) else: result = self.strFunc(y, self.vorticity_BF.data, result) return result - super(StretchingLinearized, self).__init__(formulation=diff_op.DivWV, - rhs=rhs, **kwds) + super(StretchingLinearized, self).__init__( + formulation=DivWV, rhs=rhs, + extra_ghosts_fields=self.vorticity_BF.nb_components, + **kwds) - def _integrate(self, dt, t): + def _compute(self, dt, t): # - Call time integrator (1st term over 3) - # Init workspace with a first evaluation of the div(wb:u') term in the # rhs of the integrator + self._divwu = True self._ti_work[:self.nb_components] = \ self.timeIntegrator.f(t, self.vorticity_BF.data, - self._ti_work[:self.nb_components], - "div(w:u)") + self._ti_work[:self.nb_components]) # perform integration and save result in-place self.vorticity.data = self.timeIntegrator(t, self.vorticity.data, dt, result=self.vorticity.data) # - Call time integrator (2nd term over 3) - # Init workspace with a first evaluation of the div(u':wb) term in the # rhs of the integrator + self._divwu = False self._ti_work[:self.nb_components] = \ self.timeIntegrator.f(t, self.velocity.data, - self._ti_work[:self.nb_components], - "div(u:w)") + self._ti_work[:self.nb_components]) # perform integration and save result in-place self.vorticity.data = self.timeIntegrator(t, self.vorticity.data, dt, result=self.vorticity.data) - def _compute(self, dt, t): - # No subcycling for this formulation - self._integrate(dt, t) + def apply(self, simulation=None): + assert simulation is not None, \ + "Missing simulation value for computation." + + # time step + dt = simulation.time_step + # current time + t = simulation.time - def _apply(self, t, dt): # Synchronize ghost points - self._synchronize(self.velocity.data + self.vorticity.data) - self._synchronize_vort_BF(self.vorticity_BF.data) + self._synchronize(self.velocity.data + self.vorticity.data + + self.vorticity_BF.data) # Compute the 2 first "stretching" terms (div(wb:u') and div(u':wb)) # and update vorticity for each of them self._compute(dt, t) # Compute the 3rd stretching term (div(w':ub)) and update vorticity - self.usual_op._apply(t, dt) - + self.usual_op.apply(simulation) diff --git a/hysop/operator/profiles.py b/hysop/operator/profiles.py index 3f74bbb2949f5415c8120e1b016876df0470421d..3ce3cd9ce21cbb480712a88d278cd54189a0bc1e 100644 --- a/hysop/operator/profiles.py +++ b/hysop/operator/profiles.py @@ -1,7 +1,4 @@ -# -*- coding: utf-8 -*- -""" -@file profiles.py -Compute and print velo/vorti profiles +"""Compute and print velo/vorti profiles """ from hysop.operator.discrete.profiles import Profiles as ProfD from hysop.operator.computational import Computational @@ -13,7 +10,7 @@ class Profiles(Computational): Compute and print velo/vorti profiles """ - def __init__(self, velocity, vorticity, prof_coords, + def __init__(self, velocity, vorticity, prof_coords, direction, beginMeanComput, **kwds): """ Constructor. @@ -30,24 +27,21 @@ class Profiles(Computational): assert 'variables' not in kwds, 'variables parameter is useless.' super(Profiles, self).__init__(variables=[velocity, vorticity], **kwds) - ## velocity field + # velocity field self.velocity = velocity - ## vorticity field + # vorticity field self.vorticity = vorticity - ## X and Y coordinates of the profile + # X and Y coordinates of the profile self.prof_coords = prof_coords - ## profile direction (0, 1 or 2) + # profile direction (0, 1 or 2) self.direction = direction - ## time at which the computation of mean profile must begin + # time at which the computation of mean profile must begin self.beginMeanComput = beginMeanComput self.input = [velocity, vorticity] self.output = [] def get_work_properties(self): - if not self._is_discretized: - msg = 'The operator must be discretized ' - msg += 'before any call to this function.' - raise RuntimeError(msg) + super(Profiles, self).get_work_properties() vd = self.discreteFields[self.velocity] wd = self.discreteFields[self.vorticity] v_ind = vd.topology.mesh.compute_index @@ -72,4 +66,3 @@ class Profiles(Computational): self._set_io('profile', (1, 9)) self.discrete_op.set_writer(self._writer) self._is_uptodate = True - diff --git a/hysop/operator/stretching.py b/hysop/operator/stretching.py index c0e242cbd3d7fa48b379448e8aaf12359528c65b..80095bb777ec5d782f36fa38fa702c34d2ff6ab1 100755 --- a/hysop/operator/stretching.py +++ b/hysop/operator/stretching.py @@ -16,7 +16,7 @@ from hysop.operator.computational import Computational from hysop.operator.continuous import opsetup from hysop.operator.discrete.stretching import Conservative, GradUW from hysop.operator.discrete.stretching import StretchingLinearized as SLD -import hysop.numerics.differential_operations as diff_op +from hysop.numerics.differential_operations import GradVxW, DivWV from hysop.numerics.odesolvers import Euler @@ -25,6 +25,7 @@ class Stretching(Computational): """ _authorized_methods = [FDC4] + _authorized_formulations = [Conservative, GradUW] @debug def __init__(self, velocity, vorticity, **kwds): @@ -61,11 +62,9 @@ class Stretching(Computational): msg # Formulation used for the stretching equation. # Default = conservative form. - if self.method[Formulation] == "GradUW": - self.formulation = GradUW - else: - self.formulation = Conservative - + self.formulation = self.method[Formulation] + msg = 'Stretching error : unknown formulation.' + assert self.formulation in self._authorized_formulations, msg self.input = [self.velocity, self.vorticity] self.output = [self.vorticity] @@ -81,9 +80,10 @@ class Stretching(Computational): res = ti.get_work_properties(nbc, topo) # ---> differential operator work space if self.formulation is GradUW: - dop = diff_op.GradVxW + dop = GradVxW + elif self.formulation is Conservative: - dop = diff_op.DivWV + dop = DivWV res['rwork'] += dop.get_work_properties(topo)['rwork'] return res @@ -103,12 +103,10 @@ class Stretching(Computational): class StretchingLinearized(Stretching): - """Solve the linearized stretching equation, i.e: + """Solve the linearized stretching equation + + See details in :ref:`stretching`. - \f{eqnarray*} - \frac{\partial \omega}{\partial t} &=& (\om \cdot \nabla)u_b + - (\om_b \cdot \nabla)u - \f} """ @debug def __init__(self, velocity_BF, vorticity_BF, **kwds): diff --git a/hysop/operator/tests/test_absorption_bc.py b/hysop/operator/tests/test_absorption_bc.py index 173e207043e400d21257c10e24b1f20f7d3434d6..8f97dd6c244ee6f982e361783404a2fa5724e12f 100644 --- a/hysop/operator/tests/test_absorption_bc.py +++ b/hysop/operator/tests/test_absorption_bc.py @@ -28,7 +28,7 @@ def init_test(dim, discr, ext_filter, filter_func=None): flowrate = VariableParameter(data=uinf) x_range = [0.9, 1.] op = AbsorptionBC(v, w, flowrate, x_range, - discretization=d3d, filter_func=filter_func) + discretization=discr, filter_func=filter_func) op.discretize() op.setup() wk_prop = op.get_work_properties()['rwork'] diff --git a/hysop/operator/tests/test_custom.py b/hysop/operator/tests/test_custom.py new file mode 100644 index 0000000000000000000000000000000000000000..6f92c54ff6500b5c80c762ad72d6ef948ea10f1b --- /dev/null +++ b/hysop/operator/tests/test_custom.py @@ -0,0 +1,84 @@ +"""Test user-defined (custom) operator +""" + +from hysop.operator.custom import Custom +from hysop import Field, Discretization, Box, Simulation, IOParams, IO +import numpy as np +import os + +d2d = Discretization([33, 65], [2, 0]) +d3d = Discretization([33, 65, 33], [2, 0, 1]) + + +def func3d(sim, f_in, f_out, d=None): + """A test function, for a 3d domain, + no diagnostics + """ + nbc = f_in[0].nb_components + for d in xrange(nbc): + f_out[0][d] = d * f_in[0][d] + + f_in[1][0] + np.cos(sim.time) + + +def func3d_with_diag(sim, f_in, f_out, diagnostics): + """A test function, for a 3d domain, + no diagnostics + """ + nbc = f_in[0].nb_components + for d in xrange(nbc): + f_out[0][d] = d * f_in[0][d] + f_in[1][0] + np.cos(sim.time) + diagnostics[0, 0] = sim.time + diagnostics[0, 1] = f_out[0].data[0].min() + diagnostics[0, 1] = f_out[0].data[0].max() + + +def init_custom(dim, discr, func, do_write=False): + """Test build and apply, without + writer. + """ + dom = Box(length=[1., ] * dim) + v1 = Field(name='v1', is_vector=True, domain=dom) + v2 = Field(name='v2', is_vector=False, domain=dom) + v3 = Field(name='v3', is_vector=True, domain=dom) + topo = dom.create_topology(discr) + v1.randomize(topo) + v2.randomize(topo) + if do_write: + iop = IOParams('/tmp/hysop_custom_test.dat', fileformat=IO.ASCII) + d_shape = (1, 3) + else: + iop = None + d_shape = None + op = Custom(in_fields=[v1, v2], out_fields=[v3], + variables=[v1, v2, v3], discretization=discr, + function=func, io_params=iop, + diagnostics_shape=d_shape) + op.discretize() + op.setup() + sim = Simulation(nb_iter=10) + sim.initialize() + nbc = v1.nb_components + vd1 = v1.discretize(topo) + vd2 = v2.discretize(topo) + vd3 = v3.discretize(topo) + while not sim.is_over: + op.apply(sim) + for d in xrange(nbc): + tmp1 = d * vd1[d] + + vd2[0] + np.cos(sim.time) + assert np.allclose(vd3[d], tmp1) + sim.advance() + if do_write: + assert os.path.isfile(iop.filename) + + +def test_custom_op_1(): + """Test build and apply, without + writer. + """ + init_custom(3, d3d, func3d) + + +def test_custom_op_2(): + """Test build and apply, with + output in a file + """ + init_custom(3, d3d, func3d_with_diag, True) diff --git a/hysop/operator/tests/test_diff_poisson_3D.py b/hysop/operator/tests/test_diff_poisson_3D.py index 9dbea2debb24c60df61232202dd76a34a856b649..0268a81acc2bac6be3205253dcccdc8364a51210 100755 --- a/hysop/operator/tests/test_diff_poisson_3D.py +++ b/hysop/operator/tests/test_diff_poisson_3D.py @@ -4,6 +4,7 @@ from hysop.operator.poisson import Poisson from hysop.operator.diffusion import Diffusion from math import sqrt, pi, exp from hysop.problem.simulation import Simulation +from hysop import testsenv def computeVel(x, y, z): @@ -36,6 +37,7 @@ def computeVort(x, y, z): return wx, wy, wz +@testsenv.fftw_failed def test_Diff_Poisson(): # Parameters nb = 33 @@ -44,16 +46,16 @@ def test_Diff_Poisson(): from hysop.tools.parameters import Discretization d3D = Discretization([nb, nb, nb]) - ## Domain + # Domain box = pp.Box(length=boxLength, origin=boxMin) - ## Fields + # Fields velo = pp.Field(domain=box, formula=computeVel, name='Velocity', is_vector=True) vorti = pp.Field(domain=box, formula=computeVort, name='Vorticity', is_vector=True) - ## FFT Diffusion operators and FFT Poisson solver + # FFT Diffusion operators and FFT Poisson solver diffusion = Diffusion(variables={vorti: d3D}, viscosity=0.002) poisson = Poisson(velo, vorti, discretization=d3D) diff --git a/hysop/operator/tests/test_differential.py b/hysop/operator/tests/test_differential.py index 9eaa3895b537fd371434e01bcad3d3fd734697d3..2a9c983dcea199c5355c746ba0cd6ace9d16d279 100755 --- a/hysop/operator/tests/test_differential.py +++ b/hysop/operator/tests/test_differential.py @@ -9,12 +9,11 @@ from hysop.methods_keys import SpaceDiscretisation from hysop.methods import FDC4, FDC2 from hysop.operator.differential import Curl, Grad, DivAdvection from hysop.tools.parameters import Discretization - +from hysop import testsenv # Domain and topologies definitions - -nb = 65 import math +nb = 65 Lx = Ly = Lz = 2. * math.pi box1_3d = Box(length=[Lx, Ly, Lz], origin=[0., 0., 0.]) box1_2d = Box(length=[Lx, Ly], origin=[0., 0.]) @@ -91,6 +90,8 @@ def grad_velo_2d(res, x, y, t): def check(op, ref_formula, topo, op_dim=3, order=4): + """Apply operator 'op' and compare its results with some references. + """ # Reference field ref = Field(domain=topo.domain, formula=ref_formula, nb_components=op_dim, name='reference') @@ -116,6 +117,10 @@ def check(op, ref_formula, topo, op_dim=3, order=4): def call_op(class_name, ref_formula, topo, use_work=False, op_dim=3, method=None, order=4, vform=velocity_f): + """init and set an operator of type 'class_name' + and call check function on this operator. + """ + # Velocity and result fields velo = Field(domain=topo.domain, formula=vform, is_vector=True, name='velo') @@ -139,6 +144,10 @@ def call_op(class_name, ref_formula, topo, use_work=False, def call_op_fft(class_name, ref_formula, dom, discr, op_dim=3, method=None, order=4, vform=velocity_f): + """init and set an operator of type 'class_name' + and call check function on this operator. FFTW method. + """ + # Velocity and result fields velo = Field(domain=dom, formula=vform, is_vector=True, name='velo') @@ -180,6 +189,12 @@ def test_curl_fd_3_2d(): method=method, vform=velocity_f2d) +def test_curl_fd_work(): + method = {SpaceDiscretisation: FDC4} + call_op(Curl, vorticity_f, topo3_3d, method=method, use_work=True) + + +@testsenv.fftw_failed def test_curl_fft_1(): method = {SpaceDiscretisation: 'fftw'} d1_3d_nog = Discretization([nb, nb, nb]) @@ -228,17 +243,17 @@ def test_grad_3(): call_op(Grad, grad_velo, topo3_3d, op_dim=9, method=method, order=2) +def test_grad_3_work(): + method = {SpaceDiscretisation: FDC2} + call_op(Grad, grad_velo, topo3_3d, op_dim=9, method=method, order=2, + use_work=True) + + def test_grad_3_2d(): 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: FDC4} - call_op(Curl, vorticity_f, topo3_3d, use_work=True, method=method) - - def divadvection_func(res, x, y, z, t): res[0][...] = - cos(z) * cos(z) * (cos(x) * cos(x) - sin(x) * sin(x)) - \ cos(z) * cos(z) * (cos(y) * cos(y) - sin(y) * sin(y)) diff --git a/hysop/operator/tests/test_diffusion.py b/hysop/operator/tests/test_diffusion.py index 6473a8b5d9ba226f8e7ba1717ff72fa2cf2335a6..cc3e80f86a461c55a3e2b4bf2a8f3df1681a005a 100755 --- a/hysop/operator/tests/test_diffusion.py +++ b/hysop/operator/tests/test_diffusion.py @@ -7,10 +7,11 @@ from hysop.tools.parameters import Discretization import numpy as np import hysop.tools.numpywrappers as npw import math +from hysop import testsenv pi = math.pi sin = np.sin cos = np.cos -## Physical Domain description +# Physical Domain description dim = 3 LL = 2 * pi * npw.ones((dim)) cc = 2 * pi / LL @@ -32,6 +33,7 @@ def computeVort2D(res, x, y, t): return res +@testsenv.fftw_failed def test_Diffusion3D(): dom = pp.Box(length=LL) @@ -50,6 +52,7 @@ def test_Diffusion3D(): diff.finalize() +@testsenv.fftw_failed def test_Diffusion3D_2(): dom = pp.Box(length=LL) @@ -68,6 +71,7 @@ def test_Diffusion3D_2(): diff.finalize() +@testsenv.fftw_failed def test_Diffusion2D(): dom = pp.Box(length=LL[:2]) diff --git a/hysop/operator/tests/test_operators.py b/hysop/operator/tests/test_operators.py index 1b184f29bd99d3faa2e2df79e48e613ebdbdb16e..f49e10dc2c667895b52c7546330781d4cb6bda12 100644 --- a/hysop/operator/tests/test_operators.py +++ b/hysop/operator/tests/test_operators.py @@ -1,7 +1,5 @@ # -*- coding: utf-8 -*- -""" -@file test_operators.py -tests for operators general interface +"""tests for operators general interface """ from hysop.mpi.tests.utils import create_multitask_context, CPU, GPU, OTHER diff --git a/hysop/operator/tests/test_Stretching.py b/hysop/operator/tests/test_stretching.py similarity index 65% rename from hysop/operator/tests/test_Stretching.py rename to hysop/operator/tests/test_stretching.py index 3a0f89b2fed9091b517e316a9d4d795279cbb653..97dae7246c14c4e86a8bd398d49e3707760d3fdf 100755 --- a/hysop/operator/tests/test_Stretching.py +++ b/hysop/operator/tests/test_stretching.py @@ -3,7 +3,7 @@ """ from hysop import Field, Box import numpy as np -from hysop.operator.stretching import Stretching, StretchingLinearized +from hysop.operator.stretching import Stretching, StretchingLinearized, GradUW from hysop.problem.simulation import Simulation from hysop.methods_keys import TimeIntegrator, Formulation,\ SpaceDiscretisation @@ -15,46 +15,13 @@ cos = np.cos sin = np.sin -def compute_vel(res, x, y, z, t): - amodul = cos(pi * 1. / 3.) - pix = pi * x - piy = pi * y - piz = pi * z - pi2x = 2. * pix - pi2y = 2. * piy - pi2z = 2. * piz - res[0][...] = 2. * sin(pix) * sin(pix) \ - * sin(pi2y) * sin(pi2z) * amodul - res[1][...] = - sin(pi2x) * sin(piy) \ - * sin(piy) * sin(pi2z) * amodul - res[2][...] = - sin(pi2x) * sin(piz) \ - * sin(piz) * sin(pi2y) * amodul - return res - - -def compute_vort(res, x, y, z, t): - amodul = cos(pi * 1. / 3.) - pix = pi * x - piy = pi * y - piz = pi * z - pi2x = 2. * pix - pi2y = 2. * piy - pi2z = 2. * piz - res[0][...] = 2. * pi * sin(pi2x) * amodul *\ - (- cos(pi2y) * sin(piz) * sin(piz) + - sin(piy) * sin(piy) * cos(pi2z)) - - res[1][...] = 2. * pi * sin(pi2y) * amodul *\ - (2. * cos(pi2z) * sin(pix) * sin(pix) + - sin(piz) * sin(piz) * cos(pi2x)) - - res[2][...] = -2. * pi * sin(pi2z) * amodul *\ - (cos(pi2x) * sin(piy) * sin(piy) + - sin(pix) * sin(pix) * cos(pi2y)) +# 3d discretisation with size 2 ghosts layer +d3d = Discretization([65, ] * 3, [2, ] * 3) - return res -def computeVelBF(res, x, y, z, t): +def compute_vel(res, x, y, z, t): + """3d vector field + """ amodul = cos(pi * 1. / 3.) pix = pi * x piy = pi * y @@ -71,7 +38,9 @@ def computeVelBF(res, x, y, z, t): return res -def computeVortBF(res, x, y, z, t): +def compute_vort(res, x, y, z, t): + """3d vector field + """ amodul = cos(pi * 1. / 3.) pix = pi * x piy = pi * y @@ -97,13 +66,8 @@ def computeVortBF(res, x, y, z, t): def init(method=None, work=False): """Build, init, setup for operator """ - nb = 33 - box_length = [1., 1., 1.] - box_min = [0., 0., 0.] - nb_elem = Discretization([nb, nb, nb], [2, 2, 2]) - # Domain - box = Box(length=box_length, origin=box_min) + box = Box() # Fields velo = Field( @@ -112,17 +76,22 @@ def init(method=None, work=False): vorti = Field( domain=box, formula=compute_vort, name='Vorticity', is_vector=True) - op = Stretching(velo, vorti, discretization=nb_elem, method=method) + # Stretching operator + op = Stretching(velo, vorti, discretization=d3d, method=method) op.discretize() rwork = None if work: + # Find required size for internal work vector, if needed wkp = op.get_work_properties()['rwork'] + # Allocate work space rwork = WorkSpaceTools.check_work_array(len(wkp), wkp[0]) topo = op.discreteFields[velo].topology - velo.initialize(topo=topo) - vorti.initialize(topo=topo) op.setup(rwork=rwork) simulation = Simulation(start=0, end=1., time_step=0.05) + # initialize fields and simu + velo.initialize(topo=topo) + vorti.initialize(topo=topo) + simulation.initialize() return op, simulation @@ -136,7 +105,7 @@ def test_stretching(): def test_stretching_external_work(): - """User-defined work arrays + """Default setup but with user-defined work arrays """ op, simu = init(work=True) op.apply(simu) @@ -145,43 +114,58 @@ def test_stretching_external_work(): def test_stretching_graduw(): """GradUW formulation """ - method = {TimeIntegrator: RK3, Formulation: "GradUW", + method = {TimeIntegrator: RK3, Formulation: GradUW, SpaceDiscretisation: FDC4} op, simu = init(method=method) op.apply(simu) +# def test_compare_stretching(): +# """Run conservative and graduv form, +# check if results are close enough +# """ +# op1, simu = init() +# op1.apply(simu) +# method = {TimeIntegrator: RK3, Formulation: GradUW, +# SpaceDiscretisation: FDC4} +# op2, simu = init(method=method) +# op2.apply(simu) +# w1 = op1.discrete_op.vorticity +# w2 = op2.discrete_op.vorticity +# h = w1.topology.mesh.space_step.max() +# for d in xrange(op1.domain.dimension): +# print np.abs((w1[d] - w2[d])).max() +# assert np.allclose(w1[d], w2[d], atol=h ** 2) + + def init_linearized(method=None, work=False): - """Build, init, setup for operator + """Build, init, setup for linearized stretching """ - nb = 33 - box_length = [1., 1., 1.] - box_min = [0., 0., 0.] - nb_elem = Discretization([nb, nb, nb], [2, 2, 2]) - # Domain - box = Box(length=box_length, origin=box_min) + box = Box() - # Fields + # Base fields: + velo_bf = Field( + domain=box, formula=compute_vel, + name='VelocityBF', is_vector=True) + vorti_bf = Field( + domain=box, formula=compute_vort, + name='VorticityBF', is_vector=True) + # Perturbations velo = Field( domain=box, formula=compute_vel, name='Velocity', is_vector=True) vorti = Field( domain=box, formula=compute_vort, name='Vorticity', is_vector=True) - velo_bf = Field( - domain=box, formula=computeVelBF, - name='VelocityBF', is_vector=True) - vorti_bf = Field( - domain=box, formula=computeVortBF, - name='VorticityBF', is_vector=True) # Usual stretching operator - stretch1 = Stretching(velo, vorti, discretization=nb_elem) + stretch1 = Stretching(velo, vorti, discretization=d3d) + # Linearized stretching stretch2 = StretchingLinearized(velocity=velo, vorticity=vorti, - velocity_BF=velo_bf, - vorticity_BF=vorti_bf, - discretization=nb_elem, method=method) + velocity_BF=velo_bf, + vorticity_BF=vorti_bf, + discretization=d3d, method=method) stretch1.discretize() stretch2.discretize() rwork = None @@ -189,6 +173,7 @@ def init_linearized(method=None, work=False): wkp = stretch2.get_work_properties()['rwork'] rwork = WorkSpaceTools.check_work_array(len(wkp), wkp[0]) topo = stretch1.discreteFields[velo].topology + # initialize all fields velo.initialize(topo=topo) vorti.initialize(topo=topo) velo_bf.initialize(topo=topo) @@ -196,6 +181,7 @@ def init_linearized(method=None, work=False): stretch1.setup() stretch2.setup(rwork=rwork) simulation = Simulation(start=0, end=1., time_step=0.05) + simulation.initialize() return stretch1, stretch2, simulation @@ -210,13 +196,7 @@ def test_stretching_linearized(): def test_stretching_external_work_graduv(): """User-defined work arrays for GradUW formulation """ - method = {TimeIntegrator: RK3, Formulation: "GradUW", + method = {TimeIntegrator: RK3, Formulation: GradUW, SpaceDiscretisation: FDC4} op, simu = init(work=True, method=method) op.apply(simu) - -if __name__ == "__main__": - test_stretching() - test_stretching_external_work() - test_stretching_graduw() - test_stretching_external_work_graduv() diff --git a/trashed_examples/LevelSet3D/levelSet3D.py b/trashed_examples/LevelSet3D/levelSet3D.py index 2ee37c14589160681b89cace46f1a8f2b7c050b7..ef4b982ed43346ca34f9816921c242ebeb1750cb 100644 --- a/trashed_examples/LevelSet3D/levelSet3D.py +++ b/trashed_examples/LevelSet3D/levelSet3D.py @@ -12,7 +12,7 @@ from hysop.numerics.remeshing import L6_4 as remesh_formula from hysop.numerics.remeshing import Linear from hysop.operator.advection import Advection from hysop.operator.analytic import Analytic -from hysop.operator.custom import CustomMonitor +from hysop.operators import Custom from hysop.operator.hdf_io import HDF_Writer from hysop.gpu.gpu_transfer import DataTransfer from hysop.problem.problem import Problem @@ -34,7 +34,7 @@ def vitesse(res, x, y, z, t=0.): return res -def volume(_simu, var): +def volume(_simu, var, **kwds): v_loc = np.sum(var[0].data[0] > 0.5) * np.prod( var[0].topology.mesh.space_step) return main_comm.allreduce(sendobj=v_loc, op=MPI.SUM) @@ -96,9 +96,9 @@ topo_s = advec.advec_dir[0].discreteFields[scal].topology velocity = Analytic(variables={velo: topo_v}, method={Support: 'gpu'}) -volume_m = CustomMonitor(function=volume, res_shape=1, - variables={scal: topo_s}, - io_params=IOParams(filename="volume.dat")) +volume_m = Custom(function=volume, diagnostics_shape=(1, 2), + in_fields=[scal], variables={scal: topo_s}, + io_params=IOParams(filename="volume.dat")) p = HDF_Writer(variables={scal: topo_s}, io_params=IOParams(frequency=outputModulo, filename="levelset", diff --git a/trashed_examples/LevelSet3D/levelSet3D_Scales.py b/trashed_examples/LevelSet3D/levelSet3D_Scales.py index 251b45a43f73837ee812b1ddaaffdb9b5e5f4ff1..4572efca65c05ea6a821d5ec7c7fc02ed89eef70 100644 --- a/trashed_examples/LevelSet3D/levelSet3D_Scales.py +++ b/trashed_examples/LevelSet3D/levelSet3D_Scales.py @@ -6,7 +6,7 @@ from hysop.tools.parameters import Discretization, IOParams from hysop.methods_keys import Scales, MultiScale from hysop.operator.advection import Advection from hysop.operator.analytic import Analytic -from hysop.operator.custom import CustomMonitor +from hysop.operators import Custom from hysop.operator.hdf_io import HDF_Writer from hysop.problem.problem import Problem from hysop.problem.simulation import Simulation @@ -27,7 +27,7 @@ def vitesse(res, x, y, z, t=0.): return res -def volume(_simu, var): +def volume(_simu, var, **kwds): v_loc = np.sum(var[0].data[0] > 0.5) * np.prod( var[0].topology.mesh.space_step) return main_comm.allreduce(sendobj=v_loc, op=MPI.SUM) @@ -68,9 +68,9 @@ topo_s = advec.discreteFields[scal].topology velocity = Analytic(variables={velo: topo_v}) -volume_m = CustomMonitor(function=volume, res_shape=1, - variables={scal: topo_s}, - io_params=IOParams(filename="volume.dat")) +volume_m = Custom(function=volume, res_shape=1, + in_fields=[scal], discretization=topo_s, + io_params=IOParams(filename="volume.dat")) p = HDF_Writer(variables={scal: topo_s}, io_params=IOParams(frequency=outputModulo, filename="levelset", diff --git a/trashed_examples/LevelSet3D/levelSet3D_Scales_MultiScale.py b/trashed_examples/LevelSet3D/levelSet3D_Scales_MultiScale.py index b50c7baed82c2fc85b038266d226360af67f4ae3..8b970f960006b1dade145fbb5d8d4bb85a06f456 100644 --- a/trashed_examples/LevelSet3D/levelSet3D_Scales_MultiScale.py +++ b/trashed_examples/LevelSet3D/levelSet3D_Scales_MultiScale.py @@ -6,7 +6,7 @@ from hysop.tools.parameters import Discretization, IOParams from hysop.methods_keys import Scales, MultiScale from hysop.operator.advection import Advection from hysop.operator.analytic import Analytic -from hysop.operator.custom import CustomMonitor +from hysop.operators import Custom from hysop.operator.hdf_io import HDF_Writer from hysop.problem.problem import Problem from hysop.problem.simulation import Simulation @@ -27,7 +27,7 @@ def vitesse(res, x, y, z, t=0.): return res -def volume(_simu, var): +def volume(_simu, var, **kwds): v_loc = np.sum(var[0].data[0] > 0.5) * np.prod( var[0].topology.mesh.space_step) return main_comm.allreduce(sendobj=v_loc, op=MPI.SUM) @@ -69,9 +69,9 @@ advec.discretize() velocity = Analytic(variables={velo: topo_v}) -volume_m = CustomMonitor(function=volume, res_shape=1, - variables={scal: topo_s}, - io_params=IOParams(filename="volume.dat")) +volume_m = Custom(function=volume, diagnostics_shape=(1, 2), + in_fields=[scal], variables={scal: topo_s}, + io_params=IOParams(filename="volume.dat")) p = HDF_Writer(variables={scal: topo_s}, io_params=IOParams(frequency=outputModulo, filename="levelset", diff --git a/trashed_examples/LevelSet3D/levelSet3D_gpu.py b/trashed_examples/LevelSet3D/levelSet3D_gpu.py index b12d157daac86fcc9af693a5d49003d7552b6fb3..e51895da6366910a6085b1fd090d6a696582473c 100755 --- a/trashed_examples/LevelSet3D/levelSet3D_gpu.py +++ b/trashed_examples/LevelSet3D/levelSet3D_gpu.py @@ -12,7 +12,7 @@ from hysop.numerics.remeshing import L6_4 as remesh_formula from hysop.numerics.remeshing import Linear from hysop.operator.advection import Advection from hysop.operator.analytic import Analytic -from hysop.operator.custom import CustomMonitor +from hysop.operators import Custom from hysop.operator.hdf_io import HDF_Writer from hysop.gpu.gpu_transfer import DataTransfer from hysop.problem.problem import Problem @@ -34,7 +34,7 @@ def vitesse(res, x, y, z, t=0.): return res -def volume(_simu, var): +def volume(_simu, var, **kwds): v_loc = np.sum(var[0].data[0] > 0.5) * np.prod( var[0].topology.mesh.space_step) return main_comm.allreduce(sendobj=v_loc, op=MPI.SUM) @@ -88,9 +88,9 @@ topo_s = advec.advec_dir[0].discreteFields[scal].topology velocity = Analytic(variables={velo: topo_v}) -volume_m = CustomMonitor(function=volume, res_shape=1, - variables={scal: topo_s}, - io_params=IOParams(filename="volume.dat")) +volume_m = Custom(function=volume, diagnostics_shape=1, + in_fields=[scal], variables={scal: topo_s}, + io_params=IOParams(filename="volume.dat")) p = HDF_Writer(variables={scal: topo_s}, io_params=IOParams(frequency=outputModulo, filename="levelset", diff --git a/trashed_examples/LevelSet3D/levelSet3D_gpu_MultiScale.py b/trashed_examples/LevelSet3D/levelSet3D_gpu_MultiScale.py index 2bfef8a41982257b679f9180b8b25a79b9b833bb..3d05e5019213b42d16b5135878ac931f47d1840d 100644 --- a/trashed_examples/LevelSet3D/levelSet3D_gpu_MultiScale.py +++ b/trashed_examples/LevelSet3D/levelSet3D_gpu_MultiScale.py @@ -12,7 +12,7 @@ from hysop.numerics.remeshing import L6_4 as remesh_formula from hysop.numerics.remeshing import Linear from hysop.operator.advection import Advection from hysop.operator.analytic import Analytic -from hysop.operator.custom import CustomMonitor +from hysop.operators import Custom from hysop.operator.hdf_io import HDF_Writer from hysop.gpu.gpu_transfer import DataTransfer from hysop.problem.problem import Problem @@ -34,7 +34,7 @@ def vitesse(res, x, y, z, t=0.): return res -def volume(_simu, var): +def volume(_simu, var, **kwds): v_loc = np.sum(var[0].data[0] > 0.5) * np.prod( var[0].topology.mesh.space_step) return main_comm.allreduce(sendobj=v_loc, op=MPI.SUM) @@ -89,9 +89,9 @@ topo_s = advec.advec_dir[0].discreteFields[scal].topology velocity = Analytic(variables={velo: topo_v}) -volume_m = CustomMonitor(function=volume, res_shape=1, - variables={scal: topo_s}, - io_params=IOParams(filename="volume.dat")) +volume_m = Custom(function=volume, diagnostics_shape=(1, 2), + in_fields=[scal], variables={scal: topo_s}, + io_params=IOParams(filename="volume.dat")) p = HDF_Writer(variables={scal: topo_s}, io_params=IOParams(frequency=outputModulo, filename="levelset", diff --git a/trashed_examples/LevelSet3D/levelSet3D_only_gpu.py b/trashed_examples/LevelSet3D/levelSet3D_only_gpu.py index 5a87c8e07f120f1c90c351b78b58cc290b46d794..a163a5fd25e6216c551015af7378c953c4672cce 100644 --- a/trashed_examples/LevelSet3D/levelSet3D_only_gpu.py +++ b/trashed_examples/LevelSet3D/levelSet3D_only_gpu.py @@ -12,7 +12,7 @@ from hysop.numerics.remeshing import L6_4 as remesh_formula from hysop.numerics.remeshing import Linear from hysop.operator.advection import Advection from hysop.operator.analytic import Analytic -from hysop.operator.custom import CustomMonitor +from hysop.operators import Custom from hysop.operator.hdf_io import HDF_Writer from hysop.gpu.gpu_transfer import DataTransfer from hysop.problem.problem import Problem @@ -20,7 +20,7 @@ from hysop.problem.simulation import Simulation sin, cos, pi, sqrt = np.sin, np.cos, np.pi, np.sqrt -def volume(_simu, var): +def volume(_simu, var, **kwds): v_loc = np.sum(var[0].data[0] > 0.5) * np.prod( var[0].topology.mesh.space_step) return main_comm.allreduce(sendobj=v_loc, op=MPI.SUM) @@ -78,9 +78,9 @@ topo_s = advec.advec_dir[0].discreteFields[scal].topology velocity = Analytic(variables={velo: topo_v}, method={Support: 'gpu'}) -volume_m = CustomMonitor(function=volume, res_shape=1, - variables={scal: topo_s}, - io_params=IOParams(filename="volume.dat")) +volume_m = Custom(function=volume, diagnostics_shape=(1, 2), + in_fields=[scal], variables={scal: topo_s}, + io_params=IOParams(filename="volume.dat")) p = HDF_Writer(variables={scal: topo_s}, io_params=IOParams(frequency=outputModulo, filename="levelset", diff --git a/trashed_examples/LevelSet3D/levelSet3D_only_gpu_MultiScale.py b/trashed_examples/LevelSet3D/levelSet3D_only_gpu_MultiScale.py index 5a689da0c2cf7752957fa921bd2ddb76b9a5fc2a..0726d2328d3ba3fdbb281acce52108d4e5c5b79d 100644 --- a/trashed_examples/LevelSet3D/levelSet3D_only_gpu_MultiScale.py +++ b/trashed_examples/LevelSet3D/levelSet3D_only_gpu_MultiScale.py @@ -12,7 +12,7 @@ from hysop.numerics.remeshing import L6_4 as remesh_formula from hysop.numerics.remeshing import Linear from hysop.operator.advection import Advection from hysop.operator.analytic import Analytic -from hysop.operator.custom import CustomMonitor +from hysop.operators import Custom from hysop.operator.hdf_io import HDF_Writer from hysop.gpu.gpu_transfer import DataTransfer from hysop.problem.problem import Problem @@ -20,7 +20,7 @@ from hysop.problem.simulation import Simulation sin, cos, pi, sqrt = np.sin, np.cos, np.pi, np.sqrt -def volume(_simu, var): +def volume(simu, var, **kwds): v_loc = np.sum(var[0].data[0] > 0.5) * np.prod( var[0].topology.mesh.space_step) return main_comm.allreduce(sendobj=v_loc, op=MPI.SUM) @@ -80,9 +80,9 @@ topo_s = advec.advec_dir[0].discreteFields[scal].topology velocity = Analytic(variables={velo: topo_v}, method={Support: 'gpu'}) -volume_m = CustomMonitor(function=volume, res_shape=1, - variables={scal: topo_s}, - io_params=IOParams(filename="volume.dat")) +volume_m = Custom(function=volume, diagnostics_shape=(1, 2), + in_fields=[scal], variables={scal: topo_s}, + io_params=IOParams(filename="volume.dat")) p = HDF_Writer(variables={scal: topo_s}, io_params=IOParams(frequency=outputModulo, filename="levelset", diff --git a/trashed_examples/LevelSet3D/levelSet3D_python.py b/trashed_examples/LevelSet3D/levelSet3D_python.py index fc845ee45bc9242367b87fec1b67ce2a2322a848..3a3d071d9243ca0eb4ce620e73978329100a8b63 100644 --- a/trashed_examples/LevelSet3D/levelSet3D_python.py +++ b/trashed_examples/LevelSet3D/levelSet3D_python.py @@ -12,7 +12,7 @@ from hysop.numerics.remeshing import L2_1 as remesh_formula from hysop.numerics.interpolation import Linear from hysop.operator.advection import Advection from hysop.operator.analytic import Analytic -from hysop.operator.custom import CustomMonitor +from hysop.operators import Custom from hysop.operator.hdf_io import HDF_Writer from hysop.gpu.gpu_transfer import DataTransfer from hysop.problem.problem import Problem @@ -34,7 +34,7 @@ def vitesse(res, x, y, z, t=0.): return res -def volume(_simu, var): +def volume(_simu, var, **kwds): v_loc = np.sum(var[0].data[0] > 0.5) * np.prod( var[0].topology.mesh.space_step) return main_comm.allreduce(sendobj=v_loc, op=MPI.SUM) @@ -100,9 +100,9 @@ topo_s = advec.advec_dir[0].discreteFields[scal].topology velocity = Analytic(variables={velo: topo_v}) #method={Support: 'gpu'}) -volume_m = CustomMonitor(function=volume, res_shape=1, - variables={scal: topo_s}, - io_params=IOParams(filename="volume.dat")) +volume_m = Custom(function=volume, diagnostics_shape=(1, 2), + in_fields=[scal], variables={scal: topo_s}, + io_params=IOParams(filename="volume.dat")) p = HDF_Writer(variables={scal: topo_s}, io_params=IOParams(frequency=outputModulo, filename="levelset", diff --git a/trashed_examples/Multiphase/NS_planeJet_hybrid_MS_MP.py b/trashed_examples/Multiphase/NS_planeJet_hybrid_MS_MP.py index 0529eebf6eb0a9f50727fd60fe460482381f0a36..bcf74505fc3fb023a20fe7a8f10f2a043b913dad 100644 --- a/trashed_examples/Multiphase/NS_planeJet_hybrid_MS_MP.py +++ b/trashed_examples/Multiphase/NS_planeJet_hybrid_MS_MP.py @@ -39,7 +39,7 @@ from hysop.operator.stretching import Stretching from hysop.operator.poisson import Poisson from hysop.operator.differential import Curl from hysop.operator.adapt_timestep import AdaptTimeStep -from hysop.operator.custom import CustomMonitor +from hysop.operators import Custom from hysop.operator.redistribute_inter import RedistributeInter from hysop.operator.redistribute_intra import RedistributeIntra from hysop.gpu.gpu_transfer import DataTransfer @@ -372,13 +372,14 @@ if IS_OUTPUT: io_params=IOParams(frequency=1, filename='energy.dat', fileformat=ASCII)) - maxvelo = CustomMonitor(variables={velo: topo_F_0g_1d}, - function=calc_maxvelo, - res_shape=3, - mpi_params=mpi_params_UW, - io_params=IOParams(frequency=1, - filename='maxvelo.dat', - fileformat=ASCII)) + maxvelo = Custom(in_fields=[velo], + variables={velo: topo_F_0g_1d}, + function=calc_maxvelo, + diagnostics_shape=(1, 4), + mpi_params=mpi_params_UW, + io_params=IOParams(frequency=1, + filename='maxvelo.dat', + fileformat=ASCII)) if box.is_on_task(TASK_UW): for op in (p_velo, p_velo_xy, p_velo_xz, energy, maxvelo): op.discretize() diff --git a/trashed_examples/Multiphase/RTI.py b/trashed_examples/Multiphase/RTI.py index 4534e86e61e2c3e6a5e131084012d1e86a212df0..2e23829a6b00e086a4fbe07a68629b54074ce483 100644 --- a/trashed_examples/Multiphase/RTI.py +++ b/trashed_examples/Multiphase/RTI.py @@ -42,7 +42,7 @@ from hysop.operator.multiresolution_filter import MultiresolutionFilter from hysop.operator.multiphase_gradp import MultiphaseGradP from hysop.operator.multiphase_baroclinic_rhs import MultiphaseBaroclinicRHS from hysop.operator.adapt_timestep import AdaptTimeStep -from hysop.operator.custom import CustomMonitor +from hysop.operators import Custom from hysop.operator.redistribute_inter import RedistributeInter from hysop.operator.redistribute_intra import RedistributeIntra from hysop.gpu.gpu_transfer import DataTransfer @@ -338,13 +338,14 @@ if IS_OUTPUT: io_params=IOParams(frequency=1, filename='energy.dat', fileformat=ASCII)) - maxvelo = CustomMonitor(variables={velo: topo_C_1d}, - function=calc_maxvelo, - res_shape=3, - mpi_params=mpi_params_UW, - io_params=IOParams(frequency=1, - filename='maxvelo.dat', - fileformat=ASCII)) + maxvelo = Custom(in_fields=[velo], + variables={velo: topo_C_1d}, + function=calc_maxvelo, + diagnostics_shape=(1, 4), + mpi_params=mpi_params_UW, + io_params=IOParams(frequency=1, + filename='maxvelo.dat', + fileformat=ASCII)) if box.is_on_task(TASK_UW): for op in (p_velo, energy, maxvelo): op.discretize() diff --git a/trashed_examples/Plane_jet/NS_planeJet_hybrid_MS.py b/trashed_examples/Plane_jet/NS_planeJet_hybrid_MS.py index bee1729fe1b86ccafb94b021338fe88ea2b9c978..6f65a4f347897448a95269ecbcb04f6a8ae99cc9 100644 --- a/trashed_examples/Plane_jet/NS_planeJet_hybrid_MS.py +++ b/trashed_examples/Plane_jet/NS_planeJet_hybrid_MS.py @@ -33,7 +33,7 @@ from hysop.operator.stretching import Stretching from hysop.operator.poisson import Poisson from hysop.operator.differential import Curl from hysop.operator.adapt_timestep import AdaptTimeStep -from hysop.operator.custom import CustomMonitor +from hysop.operators import Custom from hysop.operator.redistribute_inter import RedistributeInter from hysop.operator.redistribute_intra import RedistributeIntra from hysop.gpu.gpu_transfer import DataTransfer @@ -299,13 +299,14 @@ if IS_OUTPUT: io_params=IOParams(frequency=1, filename='energy.dat', fileformat=ASCII)) - maxvelo = CustomMonitor(variables={velo: topo_CPU_velo_scales}, - function=calc_maxvelo, - res_shape=3, - mpi_params=mpi_params_UW, - io_params=IOParams(frequency=1, - filename='maxvelo.dat', - fileformat=ASCII)) + maxvelo = Custom(in_fields=[velo], + variables={velo: topo_CPU_velo_scales}, + function=calc_maxvelo, + diagnostics_shape=(1, 4), + mpi_params=mpi_params_UW, + io_params=IOParams(frequency=1, + filename='maxvelo.dat', + fileformat=ASCII)) if box.isOnTask(TASK_UW): for op in (p_velo, p_velo_xy, p_velo_xz, energy, maxvelo): op.discretize() diff --git a/trashed_examples/RMI/RMI_hybrid.py b/trashed_examples/RMI/RMI_hybrid.py index 7f2076058b223e14f49e3867aed4564430df7c81..e895a25898d893256719293fff857570657810c0 100644 --- a/trashed_examples/RMI/RMI_hybrid.py +++ b/trashed_examples/RMI/RMI_hybrid.py @@ -40,7 +40,7 @@ from hysop.operator.baroclinic import Baroclinic from hysop.operator.penalization import PenalizeVorticity from hysop.operator.poisson import Poisson from hysop.operator.adapt_timestep import AdaptTimeStep -from hysop.operator.custom import CustomMonitor, CustomOp +from hysop.operators import Custom from hysop.operator.redistribute_inter import RedistributeInter from hysop.operator.redistribute_intra import RedistributeIntra from hysop.gpu.gpu_transfer import DataTransfer @@ -129,17 +129,15 @@ def func_scal_to_rho(simu, f_in, f_out): temp_maxvelo = npw.zeros((3, )) -maxvelo_values = npw.zeros((3, )) -def calc_maxvelo(simu, v): +def calc_maxvelo(simu, v, w=None, maxvelo_values): temp_maxvelo[0] = np.max(np.abs(v[0].data[0])) temp_maxvelo[1] = np.max(np.abs(v[0].data[1])) temp_maxvelo[2] = np.max(np.abs(v[0].data[2])) v[0].topology.comm.Allreduce(sendbuf=[temp_maxvelo, 3, HYSOP_MPI_REAL], recvbuf=[maxvelo_values, 3, HYSOP_MPI_REAL], op=MPI.MAX) - return maxvelo_values ctime = MPI.Wtime() # Domain @@ -222,10 +220,11 @@ advec = Advection(velo, method={Scales: 'p_64', MultiScale: 'L4_4'}) stretch = Stretching(velo, vorti, discretization=d_uw_ghosts, mpi_params=mpi_params_UW) -scal_to_rho = CustomOp([scal, ], [rho, ], func_scal_to_rho, - variables={scal: d_uw_ghosts, - rho: d_uw_ghosts}, - mpi_params=mpi_params_UW) +scal_to_rho = Custom(in_fields=[scal, ], out_fields=[rho, ], + function=func_scal_to_rho, + variables={scal: d_uw_ghosts, + rho: d_uw_ghosts}, + mpi_params=mpi_params_UW) penal = PenalizeVorticity(velocity=velo, vorticity=vorti, discretization=d_uw_ghosts, obstacles=[bc_t, bc_b], coeff=1e8, @@ -291,13 +290,14 @@ if IS_OUTPUT: io_params=IOParams(frequency=1, filename='energy.dat', fileformat=ASCII)) - maxvelo = CustomMonitor(variables={velo: topo_CPU_velo_scales}, - function=calc_maxvelo, - res_shape=3, - mpi_params=mpi_params_UW, - io_params=IOParams(frequency=1, - filename='maxvelo.dat', - fileformat=ASCII)) + maxvelo = Custom(in_fields=[velo], + variables={velo: topo_CPU_velo_scales}, + function=calc_maxvelo, + diagnostics_shape=(1, 4), + mpi_params=mpi_params_UW, + io_params=IOParams(frequency=1, + filename='maxvelo.dat', + fileformat=ASCII)) if box.is_on_task(TASK_UW): for op in (p_velo, p_rho, energy, maxvelo): op.discretize()