From 8d2f2db065104c5d997b709c7bae8e2c4c1a734c Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Keck <Jean-Baptiste.Keck@imag.fr> Date: Wed, 12 Apr 2017 17:05:15 +0200 Subject: [PATCH] get_work_properties enhancement --- CMakeLists.txt | 2 +- hysop/__init__.py | 4 +- hysop/backend/arrays/opencl_backend.py | 2 +- hysop/backend/codegen/structs/mesh_info.py | 1 - hysop/backend/opencl/__init__.py | 2 +- hysop/backend/opencl/device_config.py | 21 - .../opencl/directional/advection_dir.py | 21 +- ...nal_codegen.py => directional_operator.py} | 6 +- .../opencl/directional/stretching_dir.py | 20 +- hysop/backend/opencl/discrete.py | 90 ----- .../opencl/{backend.py => opencl_backend.py} | 0 hysop/backend/opencl/opencl_codegen.py | 10 - hysop/backend/opencl/opencl_device_config.py | 23 ++ hysop/backend/opencl/opencl_discrete.py | 368 ++---------------- hysop/backend/opencl/opencl_env.py | 6 +- hysop/backend/opencl/opencl_operator.py | 38 +- .../{_platform.py => opencl_platform.py} | 0 .../opencl/{tools.py => opencl_tools.py} | 11 + hysop/core/graph/computational_graph.py | 21 +- hysop/methods.py | 2 +- hysop/old/gpu.old/QtRendering.py | 2 +- .../old/gpu.old/directional/advection_dir.py | 2 +- hysop/old/gpu.old/gpu_codegen.py | 2 +- hysop/old/gpu.old/gpu_operator.py | 4 +- hysop/old/gpu.old/gpu_stretching.py | 2 +- hysop/old/gpu.old/tests/test_copy.py | 2 +- .../gpu.old/tests/test_opencl_environment.py | 2 +- hysop/old/gpu.old/tests/test_transposition.py | 2 +- hysop/old/gpu.old/visu/marchingcube.py | 2 +- hysop/operator/directional/advection_dir.py | 4 +- hysop/operator/directional/stretching_dir.py | 4 +- hysop/operator/poisson_old.py | 146 ------- hysop/operators.py | 7 +- hysop/problem.py | 3 +- hysop/simulation.py | 10 +- hysop/tools/decorators.py | 1 - 36 files changed, 171 insertions(+), 672 deletions(-) delete mode 100644 hysop/backend/opencl/device_config.py rename hysop/backend/opencl/directional/{directional_codegen.py => directional_operator.py} (65%) delete mode 100644 hysop/backend/opencl/discrete.py rename hysop/backend/opencl/{backend.py => opencl_backend.py} (100%) delete mode 100644 hysop/backend/opencl/opencl_codegen.py create mode 100644 hysop/backend/opencl/opencl_device_config.py rename hysop/backend/opencl/{_platform.py => opencl_platform.py} (100%) rename hysop/backend/opencl/{tools.py => opencl_tools.py} (97%) delete mode 100644 hysop/operator/poisson_old.py diff --git a/CMakeLists.txt b/CMakeLists.txt index 2ea4785b3..58acb9003 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,7 +39,7 @@ option(WITH_FFTW "Link with fftw library (required for some HySoP solvers), defa option(WITH_EXTRAS "Link with some extra fortran libraries (like arnoldi solver), default = OFF" OFF) option(WITH_GPU "Use of GPU (required for some HySoP solvers), default = ON" ON) option(WITH_MAIN_FORTRAN "Create an executable (test purpose) from fortran sources in src/main, linked with libhysop, default = ON" OFF) -option(WITH_MAIN_CXX "Create an executable (test purpose) from cxx sources in src/hysop++/main, linked with libhysop, default = ON" OFF) +option(WITH_MAIN_CXX "Create an executable (test purpose) from cxx sources in src/hysop++/main, linked with libhysop, default = ON" ON) option(DEBUG "Enable debug mode for HySoP (0:disabled, 1:verbose, 2:trace, 3:verbose+trace). Default = 0" 1) option(FULL_TEST "Enable all test options (pep8, mpi ...) - Default = OFF" OFF) option(PROFILE "Enable profiling mode for HySoP. 0:disabled, 1: enabled. Default = 0" 0) diff --git a/hysop/__init__.py b/hysop/__init__.py index 8b720e5cb..eb594ee09 100644 --- a/hysop/__init__.py +++ b/hysop/__init__.py @@ -17,7 +17,7 @@ __SCALES_ENABLED__ = "ON" is "ON" __OPTIMIZE__ = "OFF" is "ON" __VERBOSE__ = True -__DEBUG__ = True +__DEBUG__ = False __KERNEL_DEBUG__ = "ON" in ["4", "3"] __PROFILE__ = "OFF" in ["0", "1"] @@ -25,7 +25,7 @@ __ENABLE_LONG_TESTS__ = "OFF" is "ON" # OpenCL __DEFAULT_PLATFORM_ID__ = 1 -__DEFAULT_DEVICE_ID__ = 1 +__DEFAULT_DEVICE_ID__ = 0 from hysop.domain.domain import Domain diff --git a/hysop/backend/arrays/opencl_backend.py b/hysop/backend/arrays/opencl_backend.py index cfa5c29d2..e9469606b 100644 --- a/hysop/backend/arrays/opencl_backend.py +++ b/hysop/backend/arrays/opencl_backend.py @@ -16,7 +16,7 @@ from hysop.tools.numerics import is_fp, is_integer, is_signed, is_unsigned,\ get_dtype, match_dtype from hysop.tools.types import first_not_None -from hysop.backend.opencl.tools import get_or_create_opencl_env +from hysop.backend.opencl.opencl_tools import get_or_create_opencl_env default_cl_env = get_or_create_opencl_env() default_cl_platform = default_cl_env.platform() diff --git a/hysop/backend/codegen/structs/mesh_info.py b/hysop/backend/codegen/structs/mesh_info.py index a3b2f922a..569528837 100644 --- a/hysop/backend/codegen/structs/mesh_info.py +++ b/hysop/backend/codegen/structs/mesh_info.py @@ -225,7 +225,6 @@ class MeshInfoStruct(StructCodeGenerator): start,stop,ghosts, dx, lmesh,gmesh, - mesh_dir,mesh_state, **kargs) return (var, cg_var) diff --git a/hysop/backend/opencl/__init__.py b/hysop/backend/opencl/__init__.py index 9e42f376c..fa2857976 100644 --- a/hysop/backend/opencl/__init__.py +++ b/hysop/backend/opencl/__init__.py @@ -2,7 +2,7 @@ Everything concerning OpenCL in hysop. Some sources are parsed at build to handle several OpenCL features. Other sources are generated and optimized at runtime. -see hysop.backend.opencl.tools.parse_file +see hysop.backend.opencl.opencl_tools.parse_file see hysop.backend.codegen """ diff --git a/hysop/backend/opencl/device_config.py b/hysop/backend/opencl/device_config.py deleted file mode 100644 index fdfd713cb..000000000 --- a/hysop/backend/opencl/device_config.py +++ /dev/null @@ -1,21 +0,0 @@ - -from hysop.backend.opencl.kernel_autotuner import AutotunerConfig - -class OpenClDeviceConfig(object): - - def __init__(self, device_type=None, - platform_id=None, - device_id=None, - build_options='', - autotuner_config=None): - - self.device_type = device_type - self.platform_id = platform_id - self.device_id = device_id - self.build_options = build_options - - if (autotuner_config is None): - autotuner_config = AutotunerConfig() - - self.autotuner_config = autotuner_config - diff --git a/hysop/backend/opencl/directional/advection_dir.py b/hysop/backend/opencl/directional/advection_dir.py index 6b74f08f2..f0df4381a 100644 --- a/hysop/backend/opencl/directional/advection_dir.py +++ b/hysop/backend/opencl/directional/advection_dir.py @@ -3,8 +3,8 @@ from hysop.constants import np from hysop.tools.decorators import debug from hysop.core.graph.graph import not_initialized, initialized, discretized, ready -from hysop.backend.opencl.device_config import OpenClDeviceConfig -from hysop.backend.opencl.directional.directional_codegen import OpenClCodegenDirectionalOperator +from hysop.backend.opencl.opencl_device_config import OpenClDeviceConfig +from hysop.backend.opencl.directional.directional_operator import OpenClDirectionalOperator from hysop.tools.types import InstanceOf from hysop.methods import Interpolation, Precision, TimeIntegrator, Remesh @@ -17,7 +17,7 @@ from hysop.backend.codegen.kernels.directional_advection import DirectionalAdve # from hysop.numerics.remeshing import L6_3, L6_4, L6_5, L6_6 # from hysop.numerics.remeshing import L8_4 -class OpenClCodegenDirectionalAdvection(OpenClCodegenDirectionalOperator): +class OpenClDirectionalAdvection(OpenClDirectionalOperator): __default_method = { TimeIntegrator: Euler, @@ -57,7 +57,7 @@ class OpenClCodegenDirectionalAdvection(OpenClCodegenDirectionalOperator): """ - super(OpenClCodegenDirectionalAdvection,self).__init__(**kargs) + super(OpenClDirectionalAdvection,self).__init__(**kargs) self.velocity = velocity self.advected_fields_in = advected_fields_in @@ -82,15 +82,15 @@ class OpenClCodegenDirectionalAdvection(OpenClCodegenDirectionalOperator): self.remesh = method.pop(Remesh) self.interp = method.pop(Interpolation) self.time_integrator = method.pop(TimeIntegrator) - super(OpenClCodegenDirectionalAdvection,self).handle_method(method) + super(OpenClDirectionalAdvection,self).handle_method(method) @debug def discretize(self): - super(OpenClCodegenDirectionalAdvection,self).discretize() + super(OpenClDirectionalAdvection,self).discretize() @debug def get_work_properties(self): - properties = super(OpenClCodegenDirectionalAdvection,self).get_work_properties() + properties = super(OpenClDirectionalAdvection,self).get_work_properties() res = self.f_resol iw,rw = 0,0 @@ -103,12 +103,12 @@ class OpenClCodegenDirectionalAdvection(OpenClCodegenDirectionalOperator): @debug def setup(self, work): - super(OpenClCodegenDirectionalAdvection,self).setup(work) + super(OpenClDirectionalAdvection,self).setup(work) self._device_buffer_allocations(work) @debug def apply(self,**kargs): - super(OpenClCodegenDirectionalAdvection,self).apply(**kargs) + super(OpenClDirectionalAdvection,self).apply(**kargs) ## Backend methods # ComputationalNode @@ -152,7 +152,8 @@ class OpenClCodegenDirectionalAdvection(OpenClCodegenDirectionalOperator): """Allocate OpenCL buffers for velocity and advected field. """ if (work is None): - raise ValueError('work is None.') + return + # raise ValueError('work is None.') # Velocity GPUDiscreteField.fromField(self.cl_env, self.velocity) diff --git a/hysop/backend/opencl/directional/directional_codegen.py b/hysop/backend/opencl/directional/directional_operator.py similarity index 65% rename from hysop/backend/opencl/directional/directional_codegen.py rename to hysop/backend/opencl/directional/directional_operator.py index 4423f5f70..164db5f3e 100644 --- a/hysop/backend/opencl/directional/directional_codegen.py +++ b/hysop/backend/opencl/directional/directional_operator.py @@ -1,12 +1,12 @@ from hysop.tools.decorators import debug -from hysop.backend.opencl.opencl_codegen import OpenClCodegenOperator +from hysop.backend.opencl.opencl_operator import OpenClOperator -class OpenClCodegenDirectionalOperator(OpenClCodegenOperator): +class OpenClDirectionalOperator(OpenClOperator): @debug def __init__(self,direction,splitting_dim,**kargs): - super(OpenClCodegenDirectionalOperator,self).__init__(**kargs) + super(OpenClDirectionalOperator,self).__init__(**kargs) dim = splitting_dim self.direction = direction self.splitting_dim = splitting_dim diff --git a/hysop/backend/opencl/directional/stretching_dir.py b/hysop/backend/opencl/directional/stretching_dir.py index f88010499..92f5fdfb9 100644 --- a/hysop/backend/opencl/directional/stretching_dir.py +++ b/hysop/backend/opencl/directional/stretching_dir.py @@ -4,8 +4,8 @@ from hysop.tools.decorators import debug from hysop.core.graph.graph import not_initialized, initialized, discretized, ready from hysop.constants import StretchingFormulation -from hysop.backend.opencl.device_config import OpenClDeviceConfig -from hysop.backend.opencl.directional.directional_codegen import OpenClCodegenDirectionalOperator +from hysop.backend.opencl.opencl_device_config import OpenClDeviceConfig +from hysop.backend.opencl.directional.directional_operator import OpenClDirectionalOperator from hysop.tools.types import InstanceOf from hysop.methods import Interpolation, Precision, TimeIntegrator, Remesh @@ -13,7 +13,7 @@ from hysop.methods import Interpolation, Precision, TimeIntegrator, Remesh from hysop.constants import StretchingFormulation from hysop.numerics.odesolvers.runge_kutta import ExplicitRungeKutta, Euler, RK2, RK3, RK4 -class OpenClCodegenDirectionalStretching(OpenClCodegenDirectionalOperator): +class OpenClDirectionalStretching(OpenClDirectionalOperator): __default_method = { TimeIntegrator: Euler, @@ -42,7 +42,7 @@ class OpenClCodegenDirectionalStretching(OpenClCodegenDirectionalOperator): """ - super(OpenClCodegenDirectionalStretching,self).__init__(**kargs) + super(OpenClDirectionalStretching,self).__init__(**kargs) self.velocity = velocity self.vorticity = vorticity @@ -62,27 +62,27 @@ class OpenClCodegenDirectionalStretching(OpenClCodegenDirectionalOperator): @debug def handle_method(self,method): - super(OpenClCodegenDirectionalStretching,self).handle_method(method) + super(OpenClDirectionalStretching,self).handle_method(method) @debug def initialize(self, top_method): - super(OpenClCodegenDirectionalStretching,self).initialize(top_method) + super(OpenClDirectionalStretching,self).initialize(top_method) @debug def discretize(self): - super(OpenClCodegenDirectionalStretching,self).discretize() + super(OpenClDirectionalStretching,self).discretize() @debug def get_work_properties(self): - super(OpenClCodegenDirectionalStretching,self).get_work_properties() + super(OpenClDirectionalStretching,self).get_work_properties() @debug def setup(self, work): - super(OpenClCodegenDirectionalStretching,self).setup(work) + super(OpenClDirectionalStretching,self).setup(work) @debug def apply(self,**kargs): - super(OpenClCodegenDirectionalStretching,self).apply(**kargs) + super(OpenClDirectionalStretching,self).apply(**kargs) def _generate_kernels(self): self._generate_advection_kernel() diff --git a/hysop/backend/opencl/discrete.py b/hysop/backend/opencl/discrete.py deleted file mode 100644 index a60a54135..000000000 --- a/hysop/backend/opencl/discrete.py +++ /dev/null @@ -1,90 +0,0 @@ -"""Discrete field defined on device (GPU) -""" -from hysop import __VERBOSE__ -from hysop.constants import HYSOP_ORDER, HYSOP_REAL, DirectionLabels -from hysop.fields.discrete import DiscreteField -from hysop.backend.opencl import cl -from hysop.backend.opencl.opencl_kernel import OpenClKernelLauncher, KernelListLauncher - -from hysop.backend.arrays.numpy_backend import NumpyBackend as npw -from hysop.backend.arrays.numpy_backend import OpenClBackend as npcl - - -class OpenClDiscreteField(DiscreteField): - """GPU Discrete vector field implementation. - Allocates OpenCL device memory for the field. - """ - def __init__(self, cl_env, name, is_vector=False, topology=None): - """GPU Discrete vector field implementation. - Allocates OpenCL device memory for the field. - - Parameters - ---------- - - queue : OpenCL queue - topology : :class:`~hysop.core.mpi.topology.Cartesian`, optional - mpi topology and local meshes info - is_vector: boolean, optional - true if parent field is a vector field, default=False - name : string, optional - Field name - """ - # init base class - super(OpenClDiscreteField, self).__init__(topology, is_vector, name) - - # OpenCL environment - self.cl_env = cl_env - - # OpenCL arrays - self.gpu_data = [None] * self.nb_components - - # True if device allocations have been done, - self.gpu_allocated = False - - # OpenCL Events list modifying this field - self.events = [] - - # Get the ids of processes involved in the field discretisation. - # Default = all, otherwise, get info from input topology if given. - if topology is None: - from hysop.core.mpi import main_rank - self._rank = main_rank - else: - self._rank = topology.rank - - @classmethod - def from_field(cls, cl_env, vfield): - if not isinstance(vfield, OpenClDiscreteField): - vfield.__class__ = cls - OpenClDiscreteField.__init__( - vfield, cl_env, - vfield.topology, vfield.nb_components > 1, vfield.name) - - def allocate(self): - """Device blocking memory allocations.""" - queue = self.cl_env.default_queue() - if not self.gpu_allocated: - self.gpu_data = [ npcl.asarray(array) for array in self.data ] - - def wait(self): - """ - Waiting for all events completion in the field list. - Resets the events list. - """ - if __VERBOSE__: - print "{" + str(self._rank) + "}", "Wait events :", self.name - for e in self.events: - e.wait() - self.events = [] - - - def to_device(self): - - def to_host(self): - - def initialize(self): - pass - def finalize(self): - pass - def get_profiling_info(self): - pass diff --git a/hysop/backend/opencl/backend.py b/hysop/backend/opencl/opencl_backend.py similarity index 100% rename from hysop/backend/opencl/backend.py rename to hysop/backend/opencl/opencl_backend.py diff --git a/hysop/backend/opencl/opencl_codegen.py b/hysop/backend/opencl/opencl_codegen.py deleted file mode 100644 index 1329af59a..000000000 --- a/hysop/backend/opencl/opencl_codegen.py +++ /dev/null @@ -1,10 +0,0 @@ - -from hysop.tools.decorators import debug -from hysop.core.graph.computational_operator import ComputationalGraphOperator -from hysop.backend.opencl.device_config import OpenClDeviceConfig - -class OpenClCodegenOperator(ComputationalGraphOperator): - - @debug - def __init__(self, **kargs): - super(OpenClCodegenOperator,self).__init__(**kargs) diff --git a/hysop/backend/opencl/opencl_device_config.py b/hysop/backend/opencl/opencl_device_config.py new file mode 100644 index 000000000..1aa04f51d --- /dev/null +++ b/hysop/backend/opencl/opencl_device_config.py @@ -0,0 +1,23 @@ + +from hysop.constants import DeviceType +from hysop.backend.opencl.kernel_autotuner import AutotunerConfig +from hysop.backend.opencl import __DEFAULT_PLATFORM_ID__, __DEFAULT_DEVICE_ID__ + +class OpenClDeviceConfig(object): + + def __init__(self, device_type=DeviceType.ALL, + platform_id=__DEFAULT_PLATFORM_ID__, + device_id=__DEFAULT_DEVICE_ID__, + user_build_options='', + autotuner_config=None): + + self.device_type = device_type + self.platform_id = platform_id + self.device_id = device_id + self.user_build_options = user_build_options + + if (autotuner_config is None): + autotuner_config = AutotunerConfig() + + self.autotuner_config = autotuner_config + diff --git a/hysop/backend/opencl/opencl_discrete.py b/hysop/backend/opencl/opencl_discrete.py index 639366bb4..d0d31428c 100644 --- a/hysop/backend/opencl/opencl_discrete.py +++ b/hysop/backend/opencl/opencl_discrete.py @@ -1,23 +1,20 @@ """Discrete field defined on device (GPU) """ from hysop import __VERBOSE__ -from hysop.constants import HYSOP_REAL -from hysop.backend.opencl import cl +from hysop.constants import HYSOP_ORDER, HYSOP_REAL, DirectionLabels from hysop.fields.discrete import DiscreteField +from hysop.backend.opencl import cl from hysop.backend.opencl.opencl_kernel import OpenClKernelLauncher, OpenClKernelListLauncher -from hysop.tools.profiler import FProfiler -from hysop.tools.decorators import debug + +from hysop.backend.arrays.numpy_backend import NumpyBackend as npw +from hysop.backend.arrays.opencl_backend import OpenClBackend as npcl class OpenClDiscreteField(DiscreteField): """GPU Discrete vector field implementation. Allocates OpenCL device memory for the field. """ - def __init__(self, name, cl_env, - topology=None, - is_vector=False, - precision=HYSOP_REAL, - layout=True, simple_layout=False): + def __init__(self, cl_env, name, is_vector=False, topology=None): """GPU Discrete vector field implementation. Allocates OpenCL device memory for the field. @@ -27,36 +24,24 @@ class OpenClDiscreteField(DiscreteField): queue : OpenCL queue topology : :class:`~hysop.core.mpi.topology.Cartesian`, optional mpi topology and local meshes info - precision : np type, optional - Floating point precision, - default=:data:`~hysop.constants.HYSOP_REAL` is_vector: boolean, optional true if parent field is a vector field, default=False name : string, optional Field name - layour : boolean, optional - indicates if components are arranged in memory, default=True - i.e. all components are considered in the same way. - simple_layout : boolean, optional - indicates if in the Z direction, layout is ZYX (simple) or ZXY. """ # init base class super(OpenClDiscreteField, self).__init__(topology, is_vector, name) + # OpenCL environment self.cl_env = cl_env - # Precision for the field - self.precision = precision - # Memory used - self.mem_size = 0 - ## Initialization OpenCL kernel as OpenClKernelLauncher - self.init_kernel = None - self._isReleased = False - ## OpenCL Buffer pointer + + # OpenCL arrays self.gpu_data = [None] * self.nb_components + # True if device allocations have been done, - # (self.allocate call) self.gpu_allocated = False - ## OpenCL Events list modifying this field + + # OpenCL Events list modifying this field self.events = [] # Get the ids of processes involved in the field discretisation. @@ -66,306 +51,21 @@ class OpenClDiscreteField(DiscreteField): self._rank = main_rank else: self._rank = topology.rank - - # Data layout is direction dependant - self.layout = layout - # Layout for the Z direction - self.simple_layout = simple_layout - - ## Layout and shape managers - dim = self.domain.dimension - if dim == 3: - if self.simple_layout: - self._shapeFunc = shapeFunc_3D - self._fromLayoutMgrFunc = fromLayoutMgrFunc_3D - self._toLayoutMgrFunc = toLayoutMgrFunc_3D - else: - self._shapeFunc = shapeFunc_3D_seq - self._fromLayoutMgrFunc = fromLayoutMgrFunc_3D_seq - self._toLayoutMgrFunc = toLayoutMgrFunc_3D_seq - elif dim == 2: - self._shapeFunc = shapeFunc_2D - self._fromLayoutMgrFunc = fromLayoutMgrFunc_2D - self._toLayoutMgrFunc = toLayoutMgrFunc_2D - elif dim == 1: - self._shapeFunc = shapeFunc_1D - self._fromLayoutMgrFunc = fromLayoutMgrFunc_1D - self._toLayoutMgrFunc = toLayoutMgrFunc_1D - else: - msg = 'Shape functions not implemented yet for dimension {}!'.format(dim) - raise NotImplementedError(msg) - - self.profiler += FProfiler("Transfer_to_host") - self.profiler += FProfiler("Transfer_to_device") - - # Transfer size counter (to device) - self.to_dev_size = 0. - # Transfer size counter (to host) - self.to_host_size = 0. - - # Temporary cpu buffer to change data layout between cpu ang gpu - self.host_data_pinned = [None, ] * self.nb_components - - def allocate(self): - """Device memory allocations no batch.""" - if not self.gpu_allocated: - evt = [None, ] * self.nb_components - for d in xrange(self.nb_components): - # convert data to required precision - self.data[d] = np.asarray(self.data[d], - dtype=self.precision, order=ORDER) - # create on-device buffer - self.gpu_data[d] = self.cl_env.global_allocation(self.data[d]) - # update memory counter - self.mem_size += self.gpu_data[d].size - self.host_data_pinned[d], evt[d] = cl.enqueue_map_buffer( - self.cl_env.queue, - self.gpu_data[d], - offset=0, shape=(int(np.prod(self.data[0].shape)), ), - flags=cl.map_flags.READ | cl.map_flags.WRITE, - dtype=HYSOP_REAL, is_blocking=False, order=ORDER) - for d in xrange(self.nb_components): - evt[d].wait() - self.gpu_allocated = True - if __VERBOSE__: - print self.name, self.mem_size, "Bytes (", - print self.mem_size / (1024 ** 2), "MB)" - return True - else: - return False - + @classmethod - def fromField(cls, cl_env, vfield, precision=HYSOP_REAL, - layout=True, simple_layout=False): - """ - Contructor from a discrete vector field. - Mutates the given VectorField to a GPUVectorField. - @param cls : Class of the class method (GPUVectorField) - @param queue : OpenCL queue - @param vfield : VectorField - @param precision : Floating point precision - @param layout : Boolean indicating if components are arranged in memory - @param simple_layout : Boolean indicating if in the Z direction, - """ + def from_field(cls, cl_env, vfield): if not isinstance(vfield, OpenClDiscreteField): vfield.__class__ = cls OpenClDiscreteField.__init__( vfield, cl_env, - vfield.topology, vfield.nb_components > 1, vfield.name, - precision, layout, simple_layout) - - def setInitializationKernel(self, kernel): - """ - Set the initialization kernel - @param kernel : OpenClKernelLauncher to use for initialize field. - """ - self.init_kernel = kernel - - @debug - def dump(self, filename): - """ - @remark Synchronized OpenCL calls (waiting for event(s) completion) - """ - self.to_host() - self.wait() - DiscreteField.dump(self, filename) - - @debug - def load(self, filename, fieldname=None): - """ - @remark Synchronized OpenCL calls (waiting for event(s) completion) - """ - DiscreteField.load(self, filename, fieldname) - self.to_device() - - @debug - def initialize(self, formula=None, vectorize_formula=False, time=0., - *args): - """ - GPU data initialization. - Performs the initialization from different ways if device not already - contains up-to-date data: - - with an OpenCL kernel, - - with a python formula (as VectorField) and the copy data to device. - @param formula : Formula to use. - @param args : formula extra parameters - @remark Synchronized OpenCL calls (waiting for event(s) completion) - """ - t = self.precision(time) - if __VERBOSE__: - print "{" + str(self._rank) + "}", "Initialize", self.name - isGPUKernel = isinstance(formula, OpenClKernelLauncher) \ - or isinstance(formula, KernelListLauncher) - if not isGPUKernel and self.init_kernel is None: - DiscreteField.initialize(self, formula, False, time, *args) - for d in xrange(self.nb_components): - self.data[d] = np.asarray( - self.data[d], - dtype=self.precision, order=ORDER) - self.to_device() - else: - if isGPUKernel: - self.init_kernel = formula - coord_min = np.ones(4, dtype=self.precision) - mesh_size = np.ones(4, dtype=self.precision) - coord_min[:self.dimension] = np.asarray( - self.topology.mesh.origin, - dtype=self.precision) - mesh_size[:self.dimension] = np.asarray( - self.topology.mesh.space_step, - dtype=self.precision) - if self.nb_components == 2: - evt = self.init_kernel(self.gpu_data[0], - self.gpu_data[1], - coord_min, mesh_size, t, - *args, - wait_for=self.events) - elif self.nb_components == 3: - evt = self.init_kernel(self.gpu_data[0], - self.gpu_data[1], - self.gpu_data[2], - coord_min, mesh_size, t, - *args, - wait_for=self.events) - else: - evt = self.init_kernel(self.gpu_data[0], - coord_min, mesh_size, t, - *args, - wait_for=self.events) - self.events.append(evt) - - def finalize(self): - if not self._isReleased: - if __VERBOSE__: - print "deallocate :", self.name, - print " (" + str(self.mem_size / (1024. ** 2)) + " MBytes)" - self.wait() - for d in xrange(self.nb_components): - self.host_data_pinned[d].base.release(self.cl_env.queue) - self.cl_env.global_deallocation(self.gpu_data[d]) - self._isReleased = True - - def get_profiling_info(self): - if self.init_kernel is not None: - for p in self.init_kernel.profile: - self.profiler += p - - def to_device(self, component=None, layoutDir=None): - """ - Host to device method. - @param component : Component to consider (Default : all components) - @param layoutDir : layout to use - If the field have a layout per component, layoutDir is unused. Other - fields can be transfered with a given layout. - - Performs a direct OpenCL copy from numpy arrays - to OpenCL Buffers.\n - Arrange memory on device so that vector components are - contiguous in the direction of the component, if layout flag is True.\n - Example : A 3D vector field F(x,y,z) is made up of 3 - OpenCL Buffers Fx, Fy, Fz. The memory layout is : - - Fx : x-major ordering. On device, - Fx[i + j*WIDTH + k*WIDTH*HEIGHT] access to Fx(i,j,k) - - Fy : y-major ordering. On device, - Fy[i + j*WIDTH + k*WIDTH*HEIGHT] access to Fy(j,i,k) - - Fz : z-major ordering. On device, - Fz[i + j*WIDTH + k*WIDTH*HEIGHT] access to Fz(k,i,j) - """ - if component is None: - range_components = xrange(self.nb_components) - evt = [None] * self.nb_components - else: - range_components = [component] - evt = [None] - self.wait() - mem_transfered = 0 - for d_id, d in enumerate(range_components): - if self.layout: - layoutDir = d - if layoutDir is None: - layoutDir = 0 - if __VERBOSE__: - print "{" + str(self._rank) + "}", "host->device :", \ - self.name, DirectionLabels[d], layoutDir - self.host_data_pinned[d][...] = \ - self._toLayoutMgrFunc[layoutDir](self.data[d]) - evt[d_id] = cl.enqueue_copy( - self.cl_env.queue, self.gpu_data[d], self.host_data_pinned[d], - is_blocking=False) - mem_transfered += self.gpu_data[d].size - for e in evt: - self.events.append(e) - time = 0. - self.to_dev_size += mem_transfered / (1024. ** 3) - if CL_PROFILE: - for e in evt: - if e is not None: - e.wait() - time += (e.profile.end - e.profile.start) * 1e-9 - self.profiler['Transfer_to_device'] += time - - if __VERBOSE__ and time!=0: - print self.mem_size/(1024**2), "MBytes transfered at ", - print "{0:.3f} GBytes/sec".format( - mem_transfered / (time * 1024 ** 3)) - - def to_host(self, component=None, layoutDir=None): - """ - Device to host method. - @param component : Component to consider (Default : all components) - @param layoutDir : layout to use - If the field have a layout per component, layoutDir is unused. Other - fields can be transfered with a given layout. - - Performs a direct OpenCL copy from OpenCL Buffers - to numpy arrays.\n - As memory layout, if set, is arranged on device, not only a - copy is performed but also transpositions to have numpy - arrays consistent to each other. - """ - self.wait() - if component is None: - range_components = xrange(self.nb_components) - evt = [None] * self.nb_components - else: - range_components = [component] - evt = [None] - - mem_transfered = 0 - for d_id, d in enumerate(range_components): - if self.layout: - layoutDir = d - if layoutDir is None: - layoutDir = 0 - if __VERBOSE__: - print "{" + str(self._rank) + "}", "device->host :", \ - self.name, DirectionLabels[d], layoutDir - evt[d_id] = cl.enqueue_copy(self.cl_env.queue, - self.host_data_pinned[d], - self.gpu_data[d], - wait_for=self.events, - is_blocking=False) - mem_transfered += self.gpu_data[d].size - for d_id, d in enumerate(range_components): - shape = self._shapeFunc[layoutDir](self.data[d].shape) - evt[d_id].wait() - self.data[d][...] = self._fromLayoutMgrFunc[layoutDir]( - self.host_data_pinned[d], shape) - for e in evt: - self.events.append(e) - time = 0. - self.to_host_size += mem_transfered / (1024. ** 3) - if CL_PROFILE: - for e in evt: - if e is not None: - e.wait() - time += (e.profile.end - e.profile.start) * 1e-9 - self.profiler['Transfer_to_host'] += time - if __VERBOSE__ and time!=0: - print self.mem_size/(1024**2), "MBytes transfered at ", - print "{0:.3f} GBytes/sec".format( - mem_transfered / (time * 1024 ** 3)) + vfield.topology, vfield.nb_components > 1, vfield.name) + def allocate(self): + """Device blocking memory allocations.""" + queue = self.cl_env.default_queue() + if not self.gpu_allocated: + self.gpu_data = [ npcl.asarray(array) for array in self.data ] + def wait(self): """ Waiting for all events completion in the field list. @@ -377,16 +77,16 @@ class OpenClDiscreteField(DiscreteField): e.wait() self.events = [] - def clean_events(self): - """ - Waiting for all events completion in the field list. - Resets the events list. - """ - if __VERBOSE__: - print "{" + str(self._rank) + "}", "Clean events :", \ - self.name, len(self.events) - c = cl.command_execution_status.COMPLETE - for e in self.events: - e.wait() - self.events = [e for e in self.events - if e.command_execution_status != c] + + def to_device(self): + pass + + def to_host(self): + pass + + def initialize(self): + pass + def finalize(self): + pass + def get_profiling_info(self): + pass diff --git a/hysop/backend/opencl/opencl_env.py b/hysop/backend/opencl/opencl_env.py index 3f317e5ac..6a5210439 100644 --- a/hysop/backend/opencl/opencl_env.py +++ b/hysop/backend/opencl/opencl_env.py @@ -6,8 +6,8 @@ from hysop.constants import Precision, DeviceType, np from hysop.tools.units import bytes2str from hysop.backend.opencl import cl, clTools, __OPENCL_PROFILE__ -from hysop.backend.opencl.tools import convert_device_type, convert_precision -from hysop.backend.opencl.tools import get_platform, get_context, get_device, \ +from hysop.backend.opencl.opencl_tools import convert_device_type, convert_precision +from hysop.backend.opencl.opencl_tools import get_platform, get_context, get_device, \ create_queue, parse_opencl_file from hysop.backend.opencl.opencl_types import OpenClTypeGen @@ -42,7 +42,7 @@ class OpenClEnvironment(object): Notes ----- - See hysop.backend.opencl.tools.get_or_create_opencl_env(). + See hysop.backend.opencl.opencl_tools.get_or_create_opencl_env(). """ msg=\ diff --git a/hysop/backend/opencl/opencl_operator.py b/hysop/backend/opencl/opencl_operator.py index 2e95981fd..127345de5 100644 --- a/hysop/backend/opencl/opencl_operator.py +++ b/hysop/backend/opencl/opencl_operator.py @@ -10,9 +10,11 @@ discrete operators working on the OpenCl backend. """ from abc import ABCMeta +from hysop.tools.decorators import debug +from hysop.core.graph.computational_operator import ComputationalGraphOperator from hysop.backend.codegen.structs.mesh_info import MeshInfoStruct -from hysop.backend.opencl.tools import get_or_create_opencl_env -from hysop.backend.opencl.device_config import OpenClDeviceConfig +from hysop.backend.opencl.opencl_tools import get_or_create_opencl_env +from hysop.backend.opencl.opencl_device_config import OpenClDeviceConfig from hysop.methods import Precision class OpenClOperator(ComputationalGraphOperator): @@ -31,17 +33,17 @@ class OpenClOperator(ComputationalGraphOperator): super(OpenClOperator,self).handle_method(method) assert OpenClDeviceConfig in method - assert Precision in method + # assert Precision in method device_config = method.pop(OpenClDeviceConfig) - precision = method.pop(Precision) + precision = Precision.DEFAULT#method.pop(Precision) - platform_id = config.platform_id - device_id = config.device_id - device_type = config.device_type + platform_id = device_config.platform_id + device_id = device_config.device_id + device_type = device_config.device_type self.precision = precision - self.device_config = config + self.device_config = device_config self.cl_env = get_or_create_opencl_env(platform_id=platform_id, device_id=device_id, device_type=device_type, precision=precision) @@ -53,9 +55,13 @@ class OpenClOperator(ComputationalGraphOperator): super(OpenClOperator,self).initialize(topgraph_method) # after this call handle_method has been called and cl_env has been set up + @debug + def setup(self, work): + super(OpenClOperator,self).setup(work) self._initialize_cl_build_options() self._initialize_cl_size_constants() self._initialize_cl_mesh_info() + self._collect_opencl_kernels() def build_options(self): defines = [] @@ -88,18 +94,26 @@ class OpenClOperator(ComputationalGraphOperator): """ input_mesh_info = {} - for field, topo in self.input_variables: - mesh = field.mesh + for field, topo in self.input_vars.iteritems(): + mesh = topo.mesh input_mesh_info[field] = \ MeshInfoStruct.create_from_mesh('field_mesh_info', self.cl_env, mesh) output_mesh_info = {} - for field, topo in self.output_variables: - mesh = field.mesh + for field, topo in self.output_vars.iteritems(): + dfield = field.discrete_fields[topo] + mesh = topo.mesh output_mesh_info[field] = \ MeshInfoStruct.create_from_mesh('field_mesh_info', self.cl_env, mesh) self._input_mesh_info = input_mesh_info self._output_mesh_info = output_mesh_info + + @debug + def _collect_opencl_kernels(self): + """ + Collect or generate opencl kernels. + """ + pass diff --git a/hysop/backend/opencl/_platform.py b/hysop/backend/opencl/opencl_platform.py similarity index 100% rename from hysop/backend/opencl/_platform.py rename to hysop/backend/opencl/opencl_platform.py diff --git a/hysop/backend/opencl/tools.py b/hysop/backend/opencl/opencl_tools.py similarity index 97% rename from hysop/backend/opencl/tools.py rename to hysop/backend/opencl/opencl_tools.py index 3b6f90539..3a4065a31 100644 --- a/hysop/backend/opencl/tools.py +++ b/hysop/backend/opencl/opencl_tools.py @@ -84,6 +84,8 @@ def convert_device_type(device_type): """ Converts a hysop device type to corresponding opencl device type. """ + if (device_type is None): + return None check_instance(device_type, DeviceType) conversion = { @@ -105,6 +107,8 @@ def convert_precision(precision): """ Converts a hysop precision to corresponding numpy dtype. """ + if (precision is None): + return None check_instance(precision, Precision) if precision == Precision.SAME: @@ -144,6 +148,12 @@ def get_or_create_opencl_env( function (ie. all opencl operators can share the same OpenClEnvironment). """ + check_instance(platform_id, int) + check_instance(device_id, int) + check_instance(device_type, DeviceType, allow_none=True) + check_instance(precision, Precision) + check_instance(gl_sharing, bool) + key = (platform_id,device_id, device_type, gl_sharing, comm) if key in get_or_create_opencl_env.opencl_environments: return get_or_create_opencl_env.opencl_environments[key] @@ -234,6 +244,7 @@ def get_platform(platform_id): :param platform_id : OpenCL platform id """ + assert (platform_id is not None) try: # OpenCL platform platform = cl.get_platforms()[platform_id] diff --git a/hysop/core/graph/computational_graph.py b/hysop/core/graph/computational_graph.py index 0408972c5..c2da1e53b 100644 --- a/hysop/core/graph/computational_graph.py +++ b/hysop/core/graph/computational_graph.py @@ -49,6 +49,19 @@ class ComputationalGraph(ComputationalGraphNode): self.graph = None self.graph_built = False + # def get_topologies(self): + # topologies = {} + # for node in self.nodes: + # node_topologies = node.get_topologies() + # for (backend, topo) in node_topologies.iteritems(): + # if backend not in topologies: + # topologies + # for (fin,topo) in node.input_vars: + # backend = topo.backend() + # if backend not in topologies + + + @debug @not_initialized def push_nodes(self, *args): @@ -94,7 +107,7 @@ class ComputationalGraph(ComputationalGraphNode): self._build_graph(outputs_are_inputs=outputs_are_inputs) self.initialized = True - + @staticmethod def _op_info(op, jmp=False): ifields = op.input_vars @@ -148,9 +161,9 @@ class ComputationalGraph(ComputationalGraphNode): field_write_nodes = {} field_read_nodes = {} - for cfield in continuous_variables: - field_write_nodes[cfield] = {} # dictionnary topology -> node that writes cfield:topo - field_read_nodes[cfield] = {} # dictionnary topology -> list of nodes that reads cfield:topo + for field in continuous_variables: + field_write_nodes[field] = {} # dictionnary topology -> node that writes field:topo + field_read_nodes[field] = {} # dictionnary topology -> list of nodes that reads field:topo for node_id,node in enumerate(self.nodes): node_ops = [] diff --git a/hysop/methods.py b/hysop/methods.py index a04864108..f27aa537a 100644 --- a/hysop/methods.py +++ b/hysop/methods.py @@ -25,7 +25,7 @@ from hysop.constants import Backend, Precision, BoundaryCondition, \ from hysop.numerics.interpolation.interpolation import Interpolation from hysop.numerics.odesolvers.runge_kutta import TimeIntegrator from hysop.numerics.remesh.remesh import Remesh -from hysop.backend.opencl.device_config import OpenClDeviceConfig +from hysop.backend.opencl.opencl_device_config import OpenClDeviceConfig from hysop.constants import StretchingFormulation from hysop.splitting.strang import StrangOrder diff --git a/hysop/old/gpu.old/QtRendering.py b/hysop/old/gpu.old/QtRendering.py index 3092f4b52..33d5755f3 100644 --- a/hysop/old/gpu.old/QtRendering.py +++ b/hysop/old/gpu.old/QtRendering.py @@ -8,7 +8,7 @@ import sys from PyQt4 import QtGui, QtCore from PyQt4.QtOpenGL import QGLWidget import OpenGL.GL as gl -from hysop.backend.opencl.tools import get_opengl_shared_environment +from hysop.backend.opencl.opencl_tools import get_opengl_shared_environment from hysop.backend.opencl import cl from hysop.backend.opencl.opencl_discrete import OpenClDiscreteField from hysop.backend.opencl.opencl_kernel import OpenClKernelLauncher diff --git a/hysop/old/gpu.old/directional/advection_dir.py b/hysop/old/gpu.old/directional/advection_dir.py index 0eb59bebf..17e93af32 100644 --- a/hysop/old/gpu.old/directional/advection_dir.py +++ b/hysop/old/gpu.old/directional/advection_dir.py @@ -1,7 +1,7 @@ from hysop.constants import np -from hysop.backend.opencl.device_config import OpenClDeviceConfig +from hysop.backend.opencl.opencl_device_config import OpenClDeviceConfig from hysop.backend.opencl.directional.directional_codegen import OpenClCodegenDirectionalOperator from hysop.tools.types import InstanceOf diff --git a/hysop/old/gpu.old/gpu_codegen.py b/hysop/old/gpu.old/gpu_codegen.py index e37b59af7..5530fed8b 100644 --- a/hysop/old/gpu.old/gpu_codegen.py +++ b/hysop/old/gpu.old/gpu_codegen.py @@ -1,7 +1,7 @@ from hysop.backend.opencl.gpu_operator import GPUOperator from hysop.core.graph.computational_operator import ComputationalGraphOperator -from hysop.backend.opencl.device_config import OpenClDeviceConfig +from hysop.backend.opencl.opencl_device_config import OpenClDeviceConfig class OpenClCodegenOperator(ComputationalGraphOperator): diff --git a/hysop/old/gpu.old/gpu_operator.py b/hysop/old/gpu.old/gpu_operator.py index 968cbbda7..09ddb4224 100644 --- a/hysop/old/gpu.old/gpu_operator.py +++ b/hysop/old/gpu.old/gpu_operator.py @@ -10,10 +10,10 @@ discrete operators working on GPU. """ from abc import ABCMeta from hysop.constants import HYSOP_REAL, DirectionLabels -from hysop.backend.opencl.tools import get_opencl_environment +from hysop.backend.opencl.opencl_tools import get_opencl_environment from hysop.methods import ExtraArgs from hysop.operator.discrete.discrete import get_extra_args_from_method -from hysop.backend.opencl.device_config import OpenClDeviceConfig +from hysop.backend.opencl.opencl_device_config import OpenClDeviceConfig from hysop.methods import Precision class GPUOperator(object): diff --git a/hysop/old/gpu.old/gpu_stretching.py b/hysop/old/gpu.old/gpu_stretching.py index 8b7d191be..161f18ae4 100644 --- a/hysop/old/gpu.old/gpu_stretching.py +++ b/hysop/old/gpu.old/gpu_stretching.py @@ -23,7 +23,7 @@ from hysop.numerics.finite_differences import FDC2, FDC4 from hysop.operator.discrete.stretching import Conservative, GradUW from hysop.backend.codegen.kernels.stretching import CachedStretchingKernel -from hysop.backend.opencl.tools import KernelAutotuner +from hysop.backend.opencl.opencl_tools import KernelAutotuner class GPUStretching(DiscreteOperator, GPUOperator): diff --git a/hysop/old/gpu.old/tests/test_copy.py b/hysop/old/gpu.old/tests/test_copy.py index a71bdd8e7..4569b4ba2 100644 --- a/hysop/old/gpu.old/tests/test_copy.py +++ b/hysop/old/gpu.old/tests/test_copy.py @@ -4,7 +4,7 @@ Testing copy kernels. """ from hysop.backend.opencl import cl from hysop.constants import np -from hysop.backend.opencl.tools import get_opencl_environment +from hysop.backend.opencl.opencl_tools import get_opencl_environment from hysop.backend.opencl.opencl_kernel import OpenClKernelLauncher from hysop.tools.numpywrappers import npw diff --git a/hysop/old/gpu.old/tests/test_opencl_environment.py b/hysop/old/gpu.old/tests/test_opencl_environment.py index 70b893758..706f2c053 100644 --- a/hysop/old/gpu.old/tests/test_opencl_environment.py +++ b/hysop/old/gpu.old/tests/test_opencl_environment.py @@ -1,6 +1,6 @@ """Test hysop implementation of OpenCL basic functionnalities""" import numpy as np -from hysop.backend.opencl.tools import get_opencl_environment, explore, OpenClEnvironment +from hysop.backend.opencl.opencl_tools import get_opencl_environment, explore, OpenClEnvironment from hysop.constants import HYSOP_REAL FLOAT_GPU = np.float32 from hysop.core.mpi import main_comm diff --git a/hysop/old/gpu.old/tests/test_transposition.py b/hysop/old/gpu.old/tests/test_transposition.py index 11c14821c..22874e649 100644 --- a/hysop/old/gpu.old/tests/test_transposition.py +++ b/hysop/old/gpu.old/tests/test_transposition.py @@ -4,7 +4,7 @@ Testing copy kernels. """ from hysop.backend.opencl import cl from hysop.constants import np -from hysop.backend.opencl.tools import get_opencl_environment +from hysop.backend.opencl.opencl_tools import get_opencl_environment from hysop.backend.opencl.opencl_kernel import OpenClKernelLauncher from hysop.tools.numpywrappers import npw diff --git a/hysop/old/gpu.old/visu/marchingcube.py b/hysop/old/gpu.old/visu/marchingcube.py index 691292979..639c998ab 100644 --- a/hysop/old/gpu.old/visu/marchingcube.py +++ b/hysop/old/gpu.old/visu/marchingcube.py @@ -11,7 +11,7 @@ import ctypes from hysop.constant import HYSOP_REAL from hysop.backend.opencl import cl -from hysop.backend.opencl.tools import get_opencl_environment +from hysop.backend.opencl.opencl_tools import get_opencl_environment class Marching_Cube(object): diff --git a/hysop/operator/directional/advection_dir.py b/hysop/operator/directional/advection_dir.py index 477b883b7..6e6ef602d 100644 --- a/hysop/operator/directional/advection_dir.py +++ b/hysop/operator/directional/advection_dir.py @@ -11,7 +11,7 @@ from hysop.fields.continuous import Field from hysop.core.mpi.topology import Topology from hysop.operator.directional.directional import DirectionalOperator -from hysop.backend.opencl.directional.advection_dir import OpenClCodegenDirectionalAdvection +from hysop.backend.opencl.directional.advection_dir import OpenClDirectionalAdvection class DirectionalAdvection(DirectionalOperator): """ @@ -20,7 +20,7 @@ class DirectionalAdvection(DirectionalOperator): """ __implementations = { - Backend.OPENCL: OpenClCodegenDirectionalAdvection + Backend.OPENCL: OpenClDirectionalAdvection } @classmethod diff --git a/hysop/operator/directional/stretching_dir.py b/hysop/operator/directional/stretching_dir.py index f46703154..38def9da2 100644 --- a/hysop/operator/directional/stretching_dir.py +++ b/hysop/operator/directional/stretching_dir.py @@ -11,7 +11,7 @@ from hysop.fields.continuous import Field from hysop.core.mpi.topology import Topology from hysop.operator.directional.directional import DirectionalOperator -from hysop.backend.opencl.directional.stretching_dir import OpenClCodegenDirectionalStretching +from hysop.backend.opencl.directional.stretching_dir import OpenClDirectionalStretching class DirectionalStretching(DirectionalOperator): """ @@ -20,7 +20,7 @@ class DirectionalStretching(DirectionalOperator): """ __implementations = { - Backend.OPENCL: OpenClCodegenDirectionalStretching + Backend.OPENCL: OpenClDirectionalStretching } @classmethod diff --git a/hysop/operator/poisson_old.py b/hysop/operator/poisson_old.py deleted file mode 100644 index fa015b771..000000000 --- a/hysop/operator/poisson_old.py +++ /dev/null @@ -1,146 +0,0 @@ -# -*- coding: utf-8 -*- -"""Operator to solve Poisson problem. - -See :ref:`poisson` in HySoP user guide. -""" -from hysop.operator.computational import Computational -from hysop.operator.discrete.poisson_fft import PoissonFFT -from hysop.constants import debug -from hysop.operator.velocity_correction import VelocityCorrection -from hysop.operator.reprojection import Reprojection -from hysop.methods import SpaceDiscretisation, Formulation -from hysop.operator.continuous import opsetup -from hysop import __FFTW_ENABLED__ - - -class Poisson(Computational): - """Solve Poisson problem (in: vorticity, out velocity) - for incompressible flow. - """ - - _authorized_methods = ['fftw'] - - @debug - def __init__(self, output_field, input_field, flowrate=None, - projection=None, **kwds): - """Poisson operator, incompressible flow. - - Parameters - ---------- - output_field : :class:`~hysop.fields.continuous.Field - solution field - input_field : :class:`~hysop.fields.continuous.Field` - right-hand side - flowrate: :class:`~hysop.fields.variable_parameter.VariableParameter` - or double, optional - flow rate value through input surface (normal to xdir), - used to calibrate solution, default=0. - projection : double or tuple, optional - projection criterion, see notes below. - kwds : base class parameters. - - - Notes: - * projection might be: - * None: no projection - * the value of the frequency of reprojection (constant) - * a tuple (frequency, threshold). In that case, a criterion - depending on the input_field will be computed at each time step, - and if criterion > threshold., then frequency projection is active. - * About method parameter: - - SpaceDiscretisation == fftw - - Formulation = 'velocity' or 'pressure' - velocity : laplacian(phi) = -w and v = nabla X psi, in = vorticity, out = velo - pressure : laplacian(p) = -nabla.(u.nabla u, in = velo, out = pressure - """ - # Warning : for fftw all variables must have - # the same resolution. - assert 'variables' not in kwds, 'variables parameter is useless.' - super(Poisson, self).__init__(variables=[output_field, input_field], - **kwds) - # solution of the problem - self.output_field = output_field - # -(right-hand side) - self.input_field = input_field - if self.method is None: - import hysop.default_methods as default - self.method = default.POISSON - if self.method[SpaceDiscretisation] is 'fftw': - assert __FFTW_ENABLED__ - msg = 'Poisson : unknown method for space discretization' - assert self.method[SpaceDiscretisation] in self._authorized_methods,\ - msg - - # Set Poisson equation formulation : - # Velo Poisson eq or Pressure Poisson eq - self.formulation = None - if self.method[Formulation] is not 'velocity': - self.formulation = self.method[Formulation] - - self.input = [self.input_field] - self.output = [self.output_field] - # Enable correction if required - if flowrate is not None: - self.withCorrection = True - self._flowrate = flowrate - else: - self.withCorrection = False - self.correction = None - self.projection = projection - self._config = kwds - - if projection is not None: - self.output.append(self.input_field) - - def discretize(self): - # Poisson solver based on fftw - if self.method[SpaceDiscretisation] is 'fftw': - super(Poisson, self)._fftw_discretize() - # prepare correction and projection, if needed - if self.withCorrection: - toporef = self.discrete_fields[self.output_field].topology - if 'discretization' in self._config: - self._config['discretization'] = toporef - self.correction = VelocityCorrection( - self.output_field, self.input_field, - req_flowrate=self._flowrate, **self._config) - self.correction.discretize() - - if isinstance(self.projection, tuple): - freq = self.projection[0] - threshold = self.projection[1] - self.projection = Reprojection(self.input_field, - threshold, freq, - **self._config) - self.projection.discretize() - - @debug - @opsetup - def setup(self, rwork=None, iwork=None): - # Activate correction, if required - if self.withCorrection: - self.correction.setup() - cd = self.correction.discrete_op - else: - cd = None - - # Activate projection, if required - if isinstance(self.projection, Reprojection): - # Projection frequency is updated at each - # time step, and depends on the input_field - self.projection.setup(rwork=rwork) - projection_discr = self.projection.discrete_op - else: - projection_discr = self.projection - - self.discrete_op = PoissonFFT(self.discrete_fields[self.output_field], - self.discrete_fields[self.input_field], - correction=cd, - rwork=rwork, iwork=iwork, - projection=projection_discr, - formulation=self.formulation) - - self._is_uptodate = True - - def get_work_properties(self): - return {'rwork': None, 'iwork': None} diff --git a/hysop/operators.py b/hysop/operators.py index a72f05a76..d81e53f29 100644 --- a/hysop/operators.py +++ b/hysop/operators.py @@ -5,7 +5,10 @@ Allows things like: from hysop.operators import DirectionalAdvection """ -from hysop.operator.poisson import Poisson -from hysop.operator.diffusion import Diffusion +from hysop.operator.poisson import Poisson +from hysop.operator.diffusion import Diffusion +from hysop.operator.redistribute import Redistribute +from hysop.operator.analytic import Analytic +from hysop.operator.hdf_io import HDF_Writer, HDF_Reader from hysop.operator.directional.advection_dir import DirectionalAdvection from hysop.operator.directional.stretching_dir import DirectionalStretching diff --git a/hysop/problem.py b/hysop/problem.py index 8bc67c640..26c29f078 100644 --- a/hysop/problem.py +++ b/hysop/problem.py @@ -19,9 +19,10 @@ class Problem(ComputationalGraph): @debug def solve(self, simu, **kargs): + from hysop import vprint simu.initialize() while not simu.is_over: - print + vprint() simu.print_state() self.apply(simulation=simu, **kargs) simu.advance() diff --git a/hysop/simulation.py b/hysop/simulation.py index fabd6aaf5..451e7f289 100644 --- a/hysop/simulation.py +++ b/hysop/simulation.py @@ -28,8 +28,8 @@ Usage io.apply(s) """ -import sys from abc import ABCMeta, abstractmethod +from hysop.deps import sys eps = sys.float_info.epsilon """Machine epsilon, used to compare times.""" @@ -92,8 +92,9 @@ class Simulation(object): msg += ' are given, time step input will be ignored.\n' msg += '------------------------------------------------\n' - if nb_iter is not None and time_step is not None: - print (msg) + if (nb_iter is not None) and (time_step is not None): + from hysop import vprint + vprint(msg) self.time_step = (self.end - self.start) / self.nb_iter elif time_step is not None: # Simulation time step @@ -198,7 +199,8 @@ class Simulation(object): """Print current simulation parameters """ msg = "== Iteration : {0:3d}, from t = {1:6.5} to t = {2:6.5f} ==" - print (msg.format(self.current_iteration, self.tk, self.time)) + from hysop import vprint + vprint(msg.format(self.current_iteration, self.tk, self.time)) def __str__(self): s = "Simulation parameters : " diff --git a/hysop/tools/decorators.py b/hysop/tools/decorators.py index 28952c92b..51fdad4c8 100644 --- a/hysop/tools/decorators.py +++ b/hysop/tools/decorators.py @@ -72,7 +72,6 @@ def debug(f): fullclassname = args[0].__mro__[0].__module__ + '.' fullclassname += args[0].__mro__[0].__name__ print '=> instanciate :', fullclassname, - print # Calling f -- GitLab