From a549bb3f659289677ad28dbf6fda309f004ef2dc Mon Sep 17 00:00:00 2001
From: JM Etancelin <jean-matthieu.etancelin@univ-pau.fr>
Date: Tue, 24 Mar 2020 16:11:30 +0100
Subject: [PATCH] Fix custom operator for vector fields. Improve imports of
 opencl operators on non-opencl machines

---
 hysop/backend/host/python/operator/custom.py | 15 +++--
 hysop/operator/custom.py                     | 12 ++--
 hysop/operator/diffusion.py                  |  5 +-
 hysop/operator/poisson.py                    |  5 +-
 hysop/operator/poisson_curl.py               |  5 +-
 hysop/operators.py                           | 64 +++++++++++---------
 6 files changed, 61 insertions(+), 45 deletions(-)

diff --git a/hysop/backend/host/python/operator/custom.py b/hysop/backend/host/python/operator/custom.py
index 32c874876..80c64db43 100644
--- a/hysop/backend/host/python/operator/custom.py
+++ b/hysop/backend/host/python/operator/custom.py
@@ -1,6 +1,6 @@
 from hysop.tools.decorators import debug
 from hysop.tools.types import check_instance
-from hysop.fields.continuous_field import Field
+from hysop.fields.continuous_field import Field, VectorField
 from hysop.parameters.parameter import Parameter
 from hysop.topology.cartesian_descriptor import CartesianTopologyDescriptors
 from hysop.backend.host.host_operator import HostOperator
@@ -50,20 +50,23 @@ class PythonCustomOperator(HostOperator):
         super(PythonCustomOperator, self).discretize()
         dinvar, dinparam = [], []
         doutvar, doutparam = [], []
+        idf, odf = self.input_discrete_fields, self.output_discrete_fields
         self.ghost_exchanger = []
         if self.invars is not None:
             for v in self.invars:
                 if isinstance(v, Field):
-                    for vd in self.input_discrete_fields[v]:
-                        dinvar.append(vd)
+                    for _v in v if isinstance(v, VectorField) else (v, ):
+                        for vd in idf[_v]:
+                            dinvar.append(vd)
                 elif isinstance(v, Parameter):
                     dinparam.append(v)
         if self.outvars is not None:
             for v in self.outvars:
                 if isinstance(v, Field):
-                    for vd in self.output_discrete_fields[v]:
-                        doutvar.append(vd)
-                    gh =  self.output_discrete_fields[v].build_ghost_exchanger()
+                    for _v in v if isinstance(v, VectorField) else (v, ):
+                        for vd in self.output_discrete_fields[_v]:
+                            doutvar.append(vd)
+                    gh = self.output_discrete_fields[v].build_ghost_exchanger()
                     if gh is not None:
                         self.ghost_exchanger.append(gh)
                 elif isinstance(v, Parameter):
diff --git a/hysop/operator/custom.py b/hysop/operator/custom.py
index e89add0d1..44ba16308 100755
--- a/hysop/operator/custom.py
+++ b/hysop/operator/custom.py
@@ -9,7 +9,7 @@ from hysop.topology.cartesian_descriptor import CartesianTopologyDescriptors
 
 class CustomOperator(ComputationalGraphNodeFrontend):
     """
-    Function should take parameters in the following order: 
+    Function should take parameters in the following order:
       1. all input fields
       2. all input parameters
       3. all output fields
@@ -22,7 +22,7 @@ class CustomOperator(ComputationalGraphNodeFrontend):
         from hysop.backend.host.python.operator.custom import PythonCustomOperator
 
         __implementations = {
-                Implementation.PYTHON: PythonCustomOperator,
+            Implementation.PYTHON: PythonCustomOperator,
         }
         return __implementations
 
@@ -36,25 +36,25 @@ class CustomOperator(ComputationalGraphNodeFrontend):
                        allow_none=True)
         check_instance(outvars, (tuple, list), values=(Field, Parameter),
                        allow_none=True)
-        from inspect import getargspec as signature # should be inspect.signature in python 3
+        from inspect import getargspec as signature  # should be inspect.signature in python 3
         nb_args = len(signature(func).args)
         nb_in_f, nb_in_p, nb_out_f, nb_out_p = 0, 0, 0, 0
         if invars is not None:
             for v in invars:
                 if isinstance(v, Field):
-                    nb_in_f += 1
+                    nb_in_f += v.nb_components
                 elif isinstance(v, Parameter):
                     nb_in_p += 1
         if outvars is not None:
             for v in outvars:
                 if isinstance(v, Field):
-                    nb_out_f += 1
+                    nb_out_f += v.nb_components
                 elif isinstance(v, Parameter):
                     nb_out_p += 1
         msg = "function arguments ({}) did not match given in/out ".format(signature(func))
         msg += "fields and parameters ({} input fields, {} input params,".format(nb_in_f, nb_in_p)
         msg += " {} output fields, {} output params).".format(nb_out_f, nb_out_p)
         assert nb_args == nb_in_f + nb_in_p + nb_out_f + nb_out_p, msg
-            
+
         super(CustomOperator, self).__init__(
             func=func, invars=invars, outvars=outvars, **kwds)
diff --git a/hysop/operator/diffusion.py b/hysop/operator/diffusion.py
index cc31bd226..d6e0e3d21 100644
--- a/hysop/operator/diffusion.py
+++ b/hysop/operator/diffusion.py
@@ -12,7 +12,10 @@ from hysop.parameters.scalar_parameter import ScalarParameter
 
 from hysop.operator.base.spectral_operator import SpectralComputationalGraphNodeFrontend
 from hysop.backend.host.python.operator.diffusion   import PythonDiffusion
-from hysop.backend.device.opencl.operator.diffusion import OpenClDiffusion
+try:
+    from hysop.backend.device.opencl.operator.diffusion import OpenClDiffusion
+except ImportError:
+    OpenClDiffusion = None
 try:
     from hysop.backend.host.fortran.operator.diffusion  import DiffusionFFTW
 except ImportError:
diff --git a/hysop/operator/poisson.py b/hysop/operator/poisson.py
index 7f60fc3ea..a5a87dd5d 100644
--- a/hysop/operator/poisson.py
+++ b/hysop/operator/poisson.py
@@ -11,7 +11,10 @@ from hysop.topology.cartesian_descriptor import CartesianTopologyDescriptors
 
 from hysop.operator.base.spectral_operator import SpectralComputationalGraphNodeFrontend
 from hysop.backend.host.python.operator.poisson import PythonPoisson
-from hysop.backend.device.opencl.operator.poisson import OpenClPoisson
+try:
+    from hysop.backend.device.opencl.operator.poisson import OpenClPoisson
+except ImportError:
+    OpenClPoisson = None
 try:
     from hysop.backend.host.fortran.operator.poisson  import PoissonFFTW
 except ImportError:
diff --git a/hysop/operator/poisson_curl.py b/hysop/operator/poisson_curl.py
index 837b52817..593783628 100644
--- a/hysop/operator/poisson_curl.py
+++ b/hysop/operator/poisson_curl.py
@@ -11,7 +11,10 @@ from hysop.topology.cartesian_descriptor import CartesianTopologyDescriptors
 
 from hysop.operator.base.spectral_operator import SpectralComputationalGraphNodeFrontend
 from hysop.backend.host.python.operator.poisson_curl   import PythonPoissonCurl
-from hysop.backend.device.opencl.operator.poisson_curl import OpenClPoissonCurl
+try:
+    from hysop.backend.device.opencl.operator.poisson_curl import OpenClPoissonCurl
+except ImportError:
+    OpenClPoissonCurl = None
 try:
     from hysop.backend.host.fortran.operator.poisson_curl  import FortranPoissonCurl
 except ImportError:
diff --git a/hysop/operators.py b/hysop/operators.py
index cd86e2ef0..f1f732a86 100644
--- a/hysop/operators.py
+++ b/hysop/operators.py
@@ -5,52 +5,56 @@ Allows things like:
 from hysop.operators import DirectionalAdvection
 """
 
-from hysop.operator.poisson      import Poisson
+from hysop.operator.poisson import Poisson
 from hysop.operator.poisson_curl import PoissonCurl
-from hysop.operator.diffusion    import Diffusion  # FFTW diffusion
-from hysop.operator.advection    import Advection  # Scales fortran advection
+from hysop.operator.diffusion import Diffusion  # FFTW diffusion
+from hysop.operator.advection import Advection  # Scales fortran advection
 from hysop.operator.penalization import PenalizeVorticity
 from hysop.operator.flowrate_correction import FlowRateCorrection
 from hysop.operator.vorticity_absorption import VorticityAbsorption
 from hysop.operator.transpose import Transpose
 from hysop.operator.misc import Noop, ForceTopologyState
 
-from hysop.operator.redistribute           import Redistribute
-from hysop.operator.analytic               import AnalyticField
-from hysop.operator.mean_field             import ComputeMeanField
-from hysop.operator.enstrophy              import Enstrophy
-from hysop.operator.kinetic_energy         import KineticEnergy
-from hysop.operator.adapt_timestep         import AdaptiveTimeStep
-from hysop.operator.hdf_io                 import HDF_Writer, HDF_Reader
-from hysop.operator.custom_symbolic        import CustomSymbolicOperator
-from hysop.operator.parameter_plotter      import ParameterPlotter
-from hysop.operator.integrate              import Integrate
-from hysop.operator.penalization           import PenalizeVorticity
-from hysop.operator.flowrate_correction    import FlowRateCorrection
-from hysop.operator.vorticity_absorption   import VorticityAbsorption
-from hysop.operator.dummy                  import Dummy
-from hysop.operator.custom                 import CustomOperator
-from hysop.operator.convergence            import Convergence
-from hysop.operator.spatial_filtering      import SpatialFilter
+from hysop.operator.redistribute import Redistribute
+from hysop.operator.analytic import AnalyticField
+from hysop.operator.mean_field import ComputeMeanField
+from hysop.operator.enstrophy import Enstrophy
+from hysop.operator.kinetic_energy import KineticEnergy
+from hysop.operator.adapt_timestep import AdaptiveTimeStep
+from hysop.operator.hdf_io import HDF_Writer, HDF_Reader
+from hysop.operator.custom_symbolic import CustomSymbolicOperator
+from hysop.operator.parameter_plotter import ParameterPlotter
+from hysop.operator.integrate import Integrate
+from hysop.operator.penalization import PenalizeVorticity
+from hysop.operator.flowrate_correction import FlowRateCorrection
+from hysop.operator.vorticity_absorption import VorticityAbsorption
+from hysop.operator.dummy import Dummy
+from hysop.operator.custom import CustomOperator
+from hysop.operator.convergence import Convergence
+from hysop.operator.spatial_filtering import SpatialFilter
 
 from hysop.operator.derivative import SpaceDerivative,                  \
-                                      SpectralSpaceDerivative,          \
-                                      FiniteDifferencesSpaceDerivative, \
-                                      MultiSpaceDerivatives
+    SpectralSpaceDerivative,          \
+    FiniteDifferencesSpaceDerivative, \
+    MultiSpaceDerivatives
 
 from hysop.operator.min_max import MinMaxFieldStatistics,                       \
-                                   MinMaxFiniteDifferencesDerivativeStatistics, \
-                                   MinMaxSpectralDerivativeStatistics
+    MinMaxFiniteDifferencesDerivativeStatistics, \
+    MinMaxSpectralDerivativeStatistics
 
 from hysop.operator.gradient import Gradient, MinMaxGradientStatistics
-from hysop.operator.curl     import Curl, SpectralCurl
+from hysop.operator.curl import Curl, SpectralCurl
 from hysop.operator.external_force import SpectralExternalForce
-from hysop.backend.device.opencl.operator.external_force import SymbolicExternalForce
+try:
+    from hysop.backend.device.opencl.operator.external_force import SymbolicExternalForce
+except ImportError:
+    SymbolicExternalForce = None
+from hysop.operator.permeability import PermeabilityEstimate
 
 from hysop.numerics.splitting.strang import StrangSplitting
-from hysop.operator.directional.symbolic_dir   import DirectionalSymbolic
-from hysop.operator.directional.advection_dir  import DirectionalAdvection
-from hysop.operator.directional.diffusion_dir  import DirectionalDiffusion
+from hysop.operator.directional.symbolic_dir import DirectionalSymbolic
+from hysop.operator.directional.advection_dir import DirectionalAdvection
+from hysop.operator.directional.diffusion_dir import DirectionalDiffusion
 from hysop.operator.directional.stretching_dir import DirectionalStretching
 from hysop.operator.directional.stretching_dir import StaticDirectionalStretching
 from hysop.operator.directional.stretching_diffusion_dir import DirectionalStretchingDiffusion
-- 
GitLab