From 21f4a780335a13fe25efddcd340953e44aaff873 Mon Sep 17 00:00:00 2001 From: JM Etancelin <jean-matthieu.etancelin@univ-pau.fr> Date: Mon, 30 Nov 2020 15:21:59 +0100 Subject: [PATCH] Fix convergence operator with custom field for previous values --- .../host/python/operator/convergence.py | 11 ++++---- hysop/operator/base/convergence.py | 27 +++++++++++++++---- hysop/operator/convergence.py | 19 ++++++------- 3 files changed, 37 insertions(+), 20 deletions(-) diff --git a/hysop/backend/host/python/operator/convergence.py b/hysop/backend/host/python/operator/convergence.py index 7a2c3651f..309ea9595 100644 --- a/hysop/backend/host/python/operator/convergence.py +++ b/hysop/backend/host/python/operator/convergence.py @@ -29,12 +29,11 @@ class PythonConvergence(ConvergenceBase, HostOperator): dtype=self.convergence.dtype) self._tmp_reduce = npw.zeros((1+self.field.nb_components), dtype=self.convergence.dtype) - old = [npw.zeros(_.shape) for _ in self.field_buffers] - self.dField_old = tuple(old) - self.__compute_error_absolute = lambda ui, ui_old: npw.max(npw.abs(ui - ui_old)) - self.__compute_error_relative = lambda ui, ui_old, max_ui: npw.max( - npw.abs(ui - ui_old))/max_ui + self.__compute_error_absolute = \ + lambda ui, ui_old: npw.max(npw.abs(ui - ui_old)) + self.__compute_error_relative = \ + lambda ui, ui_old, max_ui: npw.max(npw.abs(ui - ui_old))/max_ui if self._residual_computation == ResidualError.ABSOLUTE: self.__compute_error = self.__compute_error_absolute elif self._residual_computation == ResidualError.RELATIVE: @@ -47,7 +46,7 @@ class PythonConvergence(ConvergenceBase, HostOperator): @op_apply def apply(self, **kwds): - u = self.field_buffers + u = self.dField.compute_buffers u_old = self.dField_old self._tmp_convergence[...] = 0. diff --git a/hysop/operator/base/convergence.py b/hysop/operator/base/convergence.py index eeca70420..9ca58e0d5 100644 --- a/hysop/operator/base/convergence.py +++ b/hysop/operator/base/convergence.py @@ -1,13 +1,15 @@ from abc import ABCMeta import numpy as np -from hysop.tools.types import check_instance, first_not_None, InstanceOf -from hysop.tools.decorators import debug +from hysop.tools.types import check_instance, first_not_None, InstanceOf +from hysop.tools.decorators import debug from hysop.fields.continuous_field import Field from hysop.parameters.tensor_parameter import TensorParameter from hysop.topology.cartesian_descriptor import CartesianTopologyDescriptors from hysop.core.memory.memory_request import MemoryRequest from hysop.constants import ResidualError +from hysop.tools.numpywrappers import npw + class ConvergenceBase(object): """Common implementation interface for Convergence operator""" @@ -25,6 +27,7 @@ class ConvergenceBase(object): dm = super(ConvergenceBase, cls).default_method() dm.update(cls.__default_method) return dm + @classmethod def available_methods(cls): am = super(ConvergenceBase, cls).available_methods() @@ -32,11 +35,12 @@ class ConvergenceBase(object): return am @debug - def __init__(self, variables, convergence=None, + def __init__(self, variables, convergence=None, u_old=None, implementation=None, **kwds): """ variables: dict dictionary of fields as keys and topologies as values. + convergence: TensorParameter (optional) Parameter to store the components of ||u-u_old||_\infty or ||u-u_old||_\infty/||u||_\infty implementation: Implementation, optional, defaults to None @@ -48,19 +52,24 @@ class ConvergenceBase(object): """ check_instance(convergence, TensorParameter, allow_none=True) check_instance(variables, dict, keys=Field, values=CartesianTopologyDescriptors) + check_instance(u_old, Field, allow_none=True) field = variables.keys()[0] if convergence is None: convergence = TensorParameter(name="|residual|", dtype=field.dtype, shape=(field.nb_components, ), is_read_only=False, quiet=False, - initial_value=np.asarray([np.finfo(field.dtype).max,]*field.nb_components)) + initial_value=np.asarray([np.finfo(field.dtype).max, ]*field.nb_components)) - input_fields = {field: variables[field]} + input_fields = {field: variables[field]} output_params = {convergence.name: convergence} self.field = field self.convergence = convergence + self.u_old = u_old + + if not u_old is None: + input_fields.update({u_old: variables[u_old]}) super(ConvergenceBase, self).__init__(input_fields=input_fields, output_params=output_params, **kwds) @@ -76,3 +85,11 @@ class ConvergenceBase(object): return super(ConvergenceBase, self).discretize() self.dField = self.get_input_discrete_field(self.field) + if not self.u_old is None: + self.dField_old = self.get_input_discrete_field(self.u_old).compute_buffers + + @debug + def setup(self, work): + super(ConvergenceBase, self).setup(work) + if self.u_old is None: + self.dField_old = tuple([npw.zeros(_.shape) for _ in self.dField.compute_buffers]) diff --git a/hysop/operator/convergence.py b/hysop/operator/convergence.py index 3abcd47e3..1f31631b8 100644 --- a/hysop/operator/convergence.py +++ b/hysop/operator/convergence.py @@ -3,14 +3,15 @@ Convergence operator. """ -from hysop.tools.decorators import debug -from hysop.constants import Implementation -from hysop.tools.types import check_instance +from hysop.tools.decorators import debug +from hysop.constants import Implementation +from hysop.tools.types import check_instance from hysop.fields.continuous_field import Field from hysop.parameters.tensor_parameter import TensorParameter from hysop.topology.cartesian_descriptor import CartesianTopologyDescriptors from hysop.core.graph.computational_node_frontend import ComputationalGraphNodeFrontend + class Convergence(ComputationalGraphNodeFrontend): """ Computes the convergence citeria for a given field. @@ -24,7 +25,7 @@ class Convergence(ComputationalGraphNodeFrontend): def implementations(cls): from hysop.backend.host.python.operator.convergence import PythonConvergence implementations = { - Implementation.PYTHON: PythonConvergence + Implementation.PYTHON: PythonConvergence } return implementations @@ -33,7 +34,7 @@ class Convergence(ComputationalGraphNodeFrontend): return Implementation.PYTHON @debug - def __init__(self, variables, error=None, convergence=None, + def __init__(self, variables, u_old=None, convergence=None, implementation=None, **kwds): """Initialize a convergence operator. @@ -43,8 +44,8 @@ class Convergence(ComputationalGraphNodeFrontend): variables: dict dictionary of fields as keys and topologies as values. - error: Field (optional) - Field to compute u-u_old. This field is created if not given. + u_old: Field (optional) + Field to store u_old. This field is created if not given. convergence: TensorParameter (optional) Parameter to store the components of ||u-u_old||_\infty or ||u-u_old||_\infty/||u||_\infty implementation: Implementation, optional, defaults to None @@ -54,11 +55,11 @@ class Convergence(ComputationalGraphNodeFrontend): Extra keywords arguments that will be passed towards implementation enstrophy operator __init__. """ - check_instance(error, Field, allow_none=True) + check_instance(u_old, Field, allow_none=True) check_instance(convergence, TensorParameter, allow_none=True) check_instance(variables, dict, keys=Field, values=CartesianTopologyDescriptors) super(Convergence, self).__init__( - error=error, convergence=convergence, + u_old=u_old, convergence=convergence, variables=variables, implementation=implementation, **kwds) -- GitLab