diff --git a/HySoP/CMakeLists.txt b/HySoP/CMakeLists.txt index aea105a84dbde57c8897d2bc4264d1129a4fa001..1e8a086e5a9f39b1cb6fa97eb757c3c179d71d64 100644 --- a/HySoP/CMakeLists.txt +++ b/HySoP/CMakeLists.txt @@ -5,7 +5,7 @@ # - high level python interface to parmes routines # - parmes fortran library (libparmes...) # - parmesscales (fortran library) particular solver from scales, (libparmesscales...) -# +# # parmes depends (optionally) on : # - parmesscales (WITH_SCALES=ON, default) # - ppm-core (USE_PPM=ON, default=OFF) @@ -15,7 +15,7 @@ # #=============================================================================== -# ============= Global cmake Settings ============= +# ============= Global cmake Settings ============= # Set minimum version for cmake cmake_minimum_required(VERSION 2.8.7) # Set cmake modules directory (i.e. the one which contains all user-defined FindXXX.cmake files among other things) @@ -47,20 +47,15 @@ set(${PYPACKAGE_NAME}_version 1.0.0) set(PROJECT_LIBRARY_NAME ${PROJECT_NAME}) # ============= The project ============= -# Set project name and project languages +# Set project name and project languages # => this automatically defines: # - ${PROJECT_NAME}_BINARY_DIR : where you have run cmake, i.e. the place for compilation # - ${PROJECT_NAME}_SOURCE_DIR : where sources (.f and .h and this CMakeLists.txt) are located -# Note that because of OutOfSourceBuild, binary_dir and source_dir must be different. +# Note that because of OutOfSourceBuild, binary_dir and source_dir must be different. project(${PROJECT_NAME} Fortran) -# ============= Tests ============= -if(WITH_TESTS) - enable_testing() -endif(WITH_TESTS) - # ============= Search for libraries ============= -# We search for libraries Parmes depends on and +# We search for libraries Parmes depends on and # set the compile/link conf (-I and -L opt) @@ -81,7 +76,7 @@ endif() find_python_module(numpy REQUIRED) #Install dir for python (default = --user) execute_process( - COMMAND ${PYTHON_EXECUTABLE} -c "import site ; print site.USER_SITE" + COMMAND ${PYTHON_EXECUTABLE} -c "import site ; print site.USER_SITE" OUTPUT_VARIABLE ${PROJECT_NAME}_INSTALL_DIR) string(STRIP ${${PROJECT_NAME}_INSTALL_DIR} ${PROJECT_NAME}_INSTALL_DIR) set(CMAKE_INSTALL_PREFIX ${${PROJECT_NAME}_INSTALL_DIR}/${PROJECT_NAME}) @@ -144,19 +139,26 @@ add_dependencies(python-install ${PARMES_LIBRARY_NAME}) set(CMAKE_SKIP_BUILD_RPATH FALSE) # when building, don't use the install RPATH already # (but later on when installing) -set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) +set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) # the RPATH to be used when installing set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib") # add the automatically determined parts of the RPATH # which point to directories outside the build tree to the install RPATH set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) +# ============= Tests ============= +if(WITH_TESTS) + enable_testing() + configure_file(CTestCustom.ctest.in CTestCustom.ctest) + add_test(NAME parmepy_test COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/BUILD_MAIN_PYTEST) +endif(WITH_TESTS) + # ============= Summary ============= if(VERBOSE_MODE) message(STATUS "====================== Summary ======================") message(STATUS " Python version :${PYTHON_VERSION_STRING}") - message(STATUS " Python executable : ${PYTHON_EXECUTABLE}"}) + message(STATUS " Python executable : ${PYTHON_EXECUTABLE}") message(STATUS " Python libraries : ${PYTHON_LIBRARIES}") message(STATUS " Compiler : ${CMAKE_Fortran_COMPILER}") message(STATUS " Sources are in : ${CMAKE_SOURCE_DIR}") diff --git a/HySoP/CTestCustom.ctest.in b/HySoP/CTestCustom.ctest.in new file mode 100644 index 0000000000000000000000000000000000000000..712b40f12d23715f953d382903b84f4670e3f8c1 --- /dev/null +++ b/HySoP/CTestCustom.ctest.in @@ -0,0 +1,3 @@ +if(EXISTS Testing/Temporary/PythonFailures.log) + SET(CTEST_CUSTOM_POST_TEST "cat Testing/Temporary/PythonFailures.log") +endif(EXISTS Testing/Temporary/PythonFailures.log) \ No newline at end of file diff --git a/HySoP/hysop/__init__.py.in b/HySoP/hysop/__init__.py.in index dcbbb2347440c28c2997e98c352128730c9a4e86..6076ae813c3fd9f5e2972304774035d734a3676c 100755 --- a/HySoP/hysop/__init__.py.in +++ b/HySoP/hysop/__init__.py.in @@ -16,6 +16,8 @@ rank_world = MPI.COMM_WORLD.Get_rank() if(rank_world == 0): print "Starting @PACKAGE_NAME@ version " + str(__version__) + ".\n" +version = "1.0.0" + import constants import domain.box @@ -33,6 +35,7 @@ import fields.discrete import fields.continuous import fields.analytical ScalarField = fields.discrete.ScalarField +VectorField = fields.discrete.VectorField ContinuousField = fields.continuous.ContinuousField AnalyticalField = fields.analytical.AnalyticalField @@ -55,3 +58,5 @@ GPUParticleSolver = particular_solvers.gpu.GPUParticleSolver ## Tools import tools.printer Printer = tools.printer.Printer + +from tools.explore_hardware import explore diff --git a/HySoP/hysop/domain/box.py b/HySoP/hysop/domain/box.py index eec974a3b1e48a613062f56ee4b42fc5b10c8ab1..bfaccddc647b5ef030a2c24d88c6612b7bbe4b9b 100644 --- a/HySoP/hysop/domain/box.py +++ b/HySoP/hysop/domain/box.py @@ -2,6 +2,7 @@ Classes for box domains description. """ + from ..constants import * from .domain import Domain from .grid import CartesianGrid @@ -19,12 +20,18 @@ class Box(Domain): Create a Periodic Box from a dimension, length and origin. Parameters dimensions must coincide. Raise ValueError in case of inconsistent parameters dimensions. - @par By defaults, it creates a \f$[0;1]^3\f$ Box. @param dimension : Box dimension. Default: 3 @param length : Box length. Default [1.0, 1.0, 1.0] @param origin : Box minimum position. Default [0., 0., 0.] + + >>> import parmepy as pp + >>> import numpy as np + >>> b = pp.Box() + >>> (b.max == np.asarray([1.0, 1.0, 1.0])).all() + True + """ if not (dimension == len(length) and dimension == len(origin)): raise ValueError("Box parameters inconsistents dimensions") @@ -49,6 +56,21 @@ class Box(Domain): Use an array for discreteDomain??? i.e to associate several discretisations for the same domain. Or maybe this should be a member of the fields?? + + >>> import parmepy as pp + >>> import numpy as np + >>> b = pp.Box() + >>> n = 11 + >>> g = b.discretize(np.asarray([n, n, n])) + >>> (g.origin == b.origin).all() + True + >>> (g.length == b.length).all() + True + >>> (g.step == b.length/(n)).all() + True + >>> b.discreteDomain == g + True + """ self.discreteDomain = CartesianGrid(resolution, self) return self.discreteDomain diff --git a/HySoP/hysop/domain/grid.py b/HySoP/hysop/domain/grid.py index e1bdcb5fa32320036a920439c0863f26b2f26bf2..03ab1e4dc06e118694499af4a8b8559b47f936b7 100644 --- a/HySoP/hysop/domain/grid.py +++ b/HySoP/hysop/domain/grid.py @@ -25,7 +25,7 @@ class CartesianGrid(DiscreteDomain): ## number of points in each direction self.resolution = resolution ## space step size - self.step = self.length / (self.resolution - 1) + self.step = self.length / (self.resolution) def update(start): self.start = start diff --git a/HySoP/hysop/test/__init__.py b/HySoP/hysop/test/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/HySoP/hysop/test/main_unit_tests.py b/HySoP/hysop/test/main_unit_tests.py new file mode 100644 index 0000000000000000000000000000000000000000..b2b2a5c2ce8dd311b7efcd4a7dbecc472d062193 --- /dev/null +++ b/HySoP/hysop/test/main_unit_tests.py @@ -0,0 +1,33 @@ +""" +@package parmepy.test +Launch tests for parmepy +""" +import unittest +import doctest +import sys +import os +# Insert parmepy sources path to sys.path from sys.path[0] (i.e. absolute path to __file__) +# This file is desined to be launched after calling: setup.py build +# Then this file is located in ./build/lib._platform_dependent_directory/parmepy/test +# Tests are run on parmepy sources located in ./build/lib._platform_dependent_directory +if sys.path[0].find("build/lib.") >= 0: + sys.path.insert(1, os.path.split(os.path.split(sys.path[0])[0])[0]) +import parmepy + +# Automatic recursive finding unittest.TestCase implemetations in package 'test' +suite = unittest.TestLoader().discover(sys.path[0], pattern='test*.py') + +# Add doctests from python files +suite.addTest(doctest.DocFileSuite('domain/box.py', package=parmepy)) + +runner = unittest.TextTestRunner(verbosity=2).run(suite) + +if sys.path[0].find("build/lib.") >= 0: + if not runner.wasSuccessful(): + fails = "\nFAILURES in " + __file__ + " : (" + str(len(runner.failures)) + ")\n" + for fail in runner.failures: + fails += fail[1] + log_failures = open('Testing/Temporary/PythonFailures.log', 'w') + log_failures.write(fails) + log_failures.close() + raise Exception("FAILED") diff --git a/HySoP/hysop/test/test_domain/__init__.py b/HySoP/hysop/test/test_domain/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/HySoP/hysop/test/test_domain/test_topology.py b/HySoP/hysop/test/test_domain/test_topology.py new file mode 100644 index 0000000000000000000000000000000000000000..9daf3ea5614236404eefac1db8fac06a00e6b129 --- /dev/null +++ b/HySoP/hysop/test/test_domain/test_topology.py @@ -0,0 +1,61 @@ +""" +Module for testing parmepy.domain.topology +""" + +import unittest +import parmepy as pp +import numpy as np + + +class CartesianTopologyTestCase(unittest.TestCase): + def setUp(self): + self.b = pp.Box() + self.nbElem = [10, 10, 10] + self.topo = pp.CartesianTopology(domain=self.b, + resolution=self.nbElem, + dim=len(self.nbElem)) + + def tearDown(self): + pass + + def test_constructor(self): + self.assertEqual(self.topo.dim, len(self.nbElem)) + self.assertItemsEqual(self.topo.dims, np.asarray([1, 1, 1])) + self.assertEqual(self.topo.size, 1) + self.assertEqual(self.topo.rank, 0) + + +class LocalMeshTestCase(unittest.TestCase): + def setUp(self): + self.b = pp.Box() + self.nbElem = [10, 10, 10] + self.topo = pp.CartesianTopology(domain=self.b, + resolution=self.nbElem, + dim=len(self.nbElem)) + + def tearDown(self): + pass + + def test_constructor(self): + self.assertItemsEqual(self.topo.mesh.origin, np.asarray([0., 0., 0.])) + point = [self.topo.mesh.coords[0][0, 0, 0], + self.topo.mesh.coords[1][0, 0, 0], + self.topo.mesh.coords[2][0, 0, 0]] + self.assertItemsEqual(np.asarray(point), np.asarray([0., 0., 0.])) + point = [self.topo.mesh.coords[0][9, 0, 0], + self.topo.mesh.coords[1][0, 9, 0], + self.topo.mesh.coords[2][0, 0, 9]] + self.assertItemsEqual(np.asarray(point), np.asarray([.9, .9, .9])) + self.assertItemsEqual(self.topo.mesh.start, [0, 0, 0]) + self.assertItemsEqual(self.topo.mesh.end, [9, 9, 9]) + self.assertEqual(self.topo.mesh.coords[0].shape, (10, 1, 1)) + self.assertEqual(self.topo.mesh.coords[1].shape, (1, 10, 1)) + self.assertEqual(self.topo.mesh.coords[2].shape, (1, 1, 10)) + +if __name__ == "__main__": + unittest.TextTestRunner(verbosity=2).run( + unittest.TestLoader().loadTestsFromTestCase(LocalMeshTestCase) + ) + unittest.TextTestRunner(verbosity=2).run( + unittest.TestLoader().loadTestsFromTestCase(CartesianTopologyTestCase) + ) diff --git a/HySoP/hysop/test/test_field/__init__.py b/HySoP/hysop/test/test_field/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/HySoP/hysop/test/test_field/test_analytical.py b/HySoP/hysop/test/test_field/test_analytical.py new file mode 100644 index 0000000000000000000000000000000000000000..37364f7a2acd1755ca0c1d91efb1ba11d7460990 --- /dev/null +++ b/HySoP/hysop/test/test_field/test_analytical.py @@ -0,0 +1,57 @@ +""" +Module for testing parmepy.field.analytical +""" + +import unittest +import parmepy as pp +import numpy as np +from test_continuous import ContinuousFieldTestCase + + +class AnalyticalFieldTestCase(ContinuousFieldTestCase): + def setUp(self): + self.b = pp.Box() + self.nbElem = [10, 10, 10] + self.topo = pp.CartesianTopology(domain=self.b, + resolution=self.nbElem, + dim=len(self.nbElem)) + self.nbElem_bis = [10, 5, 5] + self.topo_bis = pp.CartesianTopology(domain=self.b, + resolution=self.nbElem_bis, + dim=len(self.nbElem)) + self.field_scalar = pp.fields.analytical.AnalyticalField(self.b, + formula=lambda x: x ** 3, + name="test_field_scalar") + self.field_vector = pp.fields.analytical.AnalyticalField(self.b, + formula=lambda x, y, z: (x*y*z, 1.0, -x*y*z), + name="test_field_vector", vector=True) + + def tearDown(self): + pass + + def test_discretization_scalar(self): + """Test discretization of a continuous scalar field + - discretization with different topology + - multiple discretizations""" + ContinuousFieldTestCase.test_discretization_scalar(self) + + def test_discretization_vector(self): + """Test discretization of a continuous vector field + - discretization with different topology + - multiple discretizations""" + ContinuousFieldTestCase.test_discretization_vector(self) + + def test_values(self): + """Test evaluation for different formulas""" + self.assertEqual(self.field_scalar.value(0.), 0.) + self.assertEqual(self.field_scalar.value(1.), 1.) + self.assertEqual(self.field_scalar.value(-1.), -1.) + self.assertEqual(self.field_vector.value(0., 0., 0.), (0., 1., 0.)) + self.assertEqual(self.field_vector.value(1., 1., 1.), (1., 1., -1.)) + self.assertEqual(self.field_vector.value(1., 2., 3.), (6., 1., -6.)) + + +if __name__ == "__main__": + unittest.TextTestRunner(verbosity=2).run( + unittest.TestLoader().loadTestsFromTestCase(AnalyticalFieldTestCase) + ) diff --git a/HySoP/hysop/test/test_field/test_continuous.py b/HySoP/hysop/test/test_field/test_continuous.py new file mode 100644 index 0000000000000000000000000000000000000000..2d66202fcf7c2867dd9eeb6933f5b38997eaf6aa --- /dev/null +++ b/HySoP/hysop/test/test_field/test_continuous.py @@ -0,0 +1,60 @@ +""" +Module for testing parmepy.field.continuous +""" + +import unittest +import parmepy as pp +import numpy as np + + +class ContinuousFieldTestCase(unittest.TestCase): + def setUp(self): + self.b = pp.Box() + self.nbElem = [10, 10, 10] + self.topo = pp.CartesianTopology(domain=self.b, + resolution=self.nbElem, + dim=len(self.nbElem)) + self.nbElem_bis = [10, 5, 5] + self.topo_bis = pp.CartesianTopology(domain=self.b, + resolution=self.nbElem_bis, + dim=len(self.nbElem)) + self.field_scalar = pp.fields.continuous.ContinuousField(self.b, "test_field_scalar") + self.field_vector = pp.fields.continuous.ContinuousField(self.b, "test_field_vector", vector=True) + + def tearDown(self): + pass + + def test_discretization_scalar(self): + """Test discretization of a continuous scalar field + - discretization with different topology + - multiple discretizations""" + self.assertEquals(self.field_scalar.discreteField, []) + self.assertRaises(ValueError, self.field_scalar.initialize) + df, df_id = self.field_scalar.discretize(self.topo) + self.assertEqual(len(self.field_scalar.discreteField), 1) + self.assertEqual(self.field_scalar.discreteField[df_id], df) + self.assertTrue(isinstance(df, pp.fields.discrete.ScalarField)) + df, df_id = self.field_scalar.discretize(self.topo_bis) + self.assertEqual(len(self.field_scalar.discreteField), 2) + self.assertEqual(self.field_scalar.discreteField[df_id], df) + self.assertTrue(isinstance(df, pp.ScalarField)) + + def test_discretization_vector(self): + """Test discretization of a continuous vector field + - discretization with different topology + - multiple discretizations""" + self.assertEquals(self.field_vector.discreteField, []) + self.assertRaises(ValueError, self.field_vector.initialize) + df, df_id = self.field_vector.discretize(self.topo) + self.assertEqual(len(self.field_vector.discreteField), 1) + self.assertEqual(self.field_vector.discreteField[df_id], df) + self.assertTrue(isinstance(df, pp.fields.discrete.VectorField)) + df, df_id = self.field_vector.discretize(self.topo_bis) + self.assertEqual(len(self.field_vector.discreteField), 2) + self.assertEqual(self.field_vector.discreteField[df_id], df) + self.assertTrue(isinstance(df, pp.VectorField)) + +if __name__ == "__main__": + unittest.TextTestRunner(verbosity=2).run( + unittest.TestLoader().loadTestsFromTestCase(ContinuousFieldTestCase) + ) diff --git a/HySoP/hysop/test/test_field/test_discrete.py b/HySoP/hysop/test/test_field/test_discrete.py new file mode 100644 index 0000000000000000000000000000000000000000..fabc6d482f84ecdcea5d76b2dc8ea9a5bc7664f6 --- /dev/null +++ b/HySoP/hysop/test/test_field/test_discrete.py @@ -0,0 +1,117 @@ +""" +Module for testing parmepy.field.discrete +""" + +import unittest +import parmepy as pp +import numpy as np + + +class ScalarFieldTestCase(unittest.TestCase): + def setUp(self): + self.b = pp.Box() + self.nbElem = [10, 10, 10] + topo = pp.CartesianTopology(domain=self.b, + resolution=self.nbElem, + dim=len(self.nbElem)) + self.formula = lambda x, y, z: x * y * z + field_scalar = pp.fields.analytical.AnalyticalField(self.b, + formula=self.formula, + name="test_field_scalar") + self.ds, self.ds_id = field_scalar.discretize(topo) + + def tearDown(self): + pass + + def test_constructor(self): + """Test ScalarField construction""" + np.testing.assert_array_equal(self.ds.data, np.zeros(tuple(self.nbElem), dtype=pp.constants.PARMES_REAL)) + self.assertEqual(self.ds.data.shape, tuple(self.nbElem)) + self.assertTrue(not self.ds.contains_data) + + def test_initialization(self): + """Scalar initialization""" + self.ds.initialize(self.formula) + true_res = np.zeros_like(self.ds.data) + for i in np.arange(10): + for j in np.arange(10): + for k in np.arange(10): + true_res[i, j, k] = self.formula(i / 10., j / 10., k / 10.) + np.testing.assert_array_almost_equal(self.ds.data, true_res) + + +class VectorFieldTestCase(unittest.TestCase): + def setUp(self): + self.b = pp.Box() + self.nbElem = [10, 10, 10] + topo = pp.CartesianTopology(domain=self.b, + resolution=self.nbElem, + dim=len(self.nbElem)) + self.formula = lambda x, y, z: (y - x, - x * z - y, x * y - z) + field_vector = pp.fields.analytical.AnalyticalField(self.b, + formula=self.formula, + name="test_field_vector", vector=True) + self.dv, self.dv_id = field_vector.discretize(topo) + + def tearDown(self): + pass + + def test_constructor(self): + """Test VectorField construction""" + self.assertTrue(isinstance(self.dv.data, list)) + self.assertEqual(len(self.dv.data), 3) + for df in self.dv.data: + np.testing.assert_array_equal(df, np.zeros(tuple(self.nbElem), dtype=pp.constants.PARMES_REAL)) + self.assertEqual(df.shape, tuple(self.nbElem)) + self.assertTrue(not self.dv.contains_data) + + def test_initialization(self): + """Vector initialization""" + self.dv.initialize(self.formula) + true_res_x = np.zeros_like(self.dv.data[0]) + true_res_y = np.zeros_like(self.dv.data[1]) + true_res_z = np.zeros_like(self.dv.data[2]) + for i in np.arange(10): + for j in np.arange(10): + for k in np.arange(10): + true_res_x[i, j, k], true_res_y[i, j, k], true_res_z[i, j, k] = self.formula(i / 10., j / 10., k / 10.) + np.testing.assert_array_almost_equal(self.dv.data[0], true_res_x) + np.testing.assert_array_almost_equal(self.dv.data[1], true_res_y) + np.testing.assert_array_almost_equal(self.dv.data[2], true_res_z) + + def test_elementAcces(self): + """Vector element access""" + self.dv.initialize(self.formula) + true_res_x = np.zeros_like(self.dv.data[0]) + true_res_y = np.zeros_like(self.dv.data[1]) + true_res_z = np.zeros_like(self.dv.data[2]) + for i in np.arange(10): + for j in np.arange(10): + for k in np.arange(10): + true_res_x[i, j, k], true_res_y[i, j, k], true_res_z[i, j, k] = self.formula(i / 10., j / 10., k / 10.) + self.assertAlmostEqual(self.dv[0][i, j, k], true_res_x[i, j, k]) + self.assertAlmostEqual(self.dv[i, j, k, 1], true_res_y[i, j, k]) + np.testing.assert_array_almost_equal(self.dv[i, j, k], [true_res_x[i, j, k], true_res_y[i, j, k], true_res_z[i, j, k]]) + np.testing.assert_array_almost_equal(self.dv[0], true_res_x) + np.testing.assert_array_almost_equal(self.dv[1], true_res_y) + np.testing.assert_array_almost_equal(self.dv[2], true_res_z) + np.testing.assert_array_almost_equal(self.dv[0][:,1,2], true_res_x[:,1,2]) + np.testing.assert_array_almost_equal(self.dv[:,1,2,0], true_res_x[:,1,2]) + self.dv[1,2,3] = [1., 2., 3.] + np.testing.assert_array_almost_equal( self.dv[1,2,3], [1., 2., 3.]) + self.dv[0,1,:] = 5. + true_res = [np.ones_like(self.dv.data[0][0,1,:])*5., + np.ones_like(self.dv.data[0][0,1,:])*5., + np.ones_like(self.dv.data[0][0,1,:])*5.] + np.testing.assert_array_almost_equal( self.dv[0,1,:], true_res) + self.dv[0][...,9] = -1. + np.testing.assert_array_almost_equal(self.dv[0][...,9], np.ones_like(true_res_x[...,9])*-1.) + + +if __name__ == "__main__": + unittest.TextTestRunner(verbosity=2).run( + unittest.TestLoader().loadTestsFromTestCase(ScalarFieldTestCase) + ) + unittest.TextTestRunner(verbosity=2).run( + unittest.TestLoader().loadTestsFromTestCase(VectorFieldTestCase) + ) diff --git a/HySoP/hysop/test/test_operator/__init__.py b/HySoP/hysop/test/test_operator/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/HySoP/hysop/test/test_operator/test_transport_d.py b/HySoP/hysop/test/test_operator/test_transport_d.py new file mode 100644 index 0000000000000000000000000000000000000000..14585b5f530890c796df347639377276a517ff59 --- /dev/null +++ b/HySoP/hysop/test/test_operator/test_transport_d.py @@ -0,0 +1,122 @@ +""" +Module for testing parmepy.operator.transport_d +""" + +import unittest +import parmepy as pp +import numpy as np +import pyopencl as cl + + +class Transport_dTestCase(unittest.TestCase): + + def setUp_OpenCL_basic(self): + self.b = pp.Box() + self.nbElem = [32, 32, 32] + self.topo = pp.CartesianTopology(domain=self.b, + resolution=self.nbElem, + dim=len(self.nbElem)) + build_options = "-cl-single-precision-constant -cl-opt-disable" + build_options += " -D WIDTH=32" + build_options += " -D WGN=32" + build_options += " -D PADDING=0" + build_options += " -D BASIC=1" + self.prg_basic = cl.Program(self.ctx, self.gpu_src).build(build_options) + self.p_positions = pp.fields.continuous.ContinuousField(self.b, + name="test_field_positions") + self.p_scalar = pp.fields.continuous.ContinuousField(self.b, + name="test_field_scalar") + self.true_p_positions = pp.fields.analytical.AnalyticalField(self.b, + formula=lambda x,y,z:x, + name="test_field_true_positions") + self.g_velocity = pp.fields.analytical.AnalyticalField(self.b, + formula=lambda x, y, z: (0., 1., 0.), + name="test_field_g_velocity", vector=True) + self.g_scalar = pp.fields.analytical.AnalyticalField(self.b, + formula=lambda x, y, z: 1., + name="test_field_g_scalar") + self.b.discretize(self.topo.resolution) + self.pos, self.pos_id = self.p_positions.discretize(self.topo) + self.scal, self.velo_id = self.p_scalar.discretize(self.topo) + self.gvelo, self.pos_id = self.g_velocity.discretize(self.topo) + self.gscal, self.velo_id = self.g_scalar.discretize(self.topo) + self.true_pos, self.velo_id = self.true_p_positions.discretize(self.topo) + self.true_p_positions.initialize() + self.g_velocity.initialize() + self.g_scalar.initialize() + self.pos.data = np.asarray(self.pos.data, dtype=pp.constants.PARMES_REAL_GPU, order='F') + self.scal.data = np.asarray(self.scal.data, dtype=pp.constants.PARMES_REAL_GPU, order='F') + self.gvelo.data[0] = np.asarray(self.gvelo.data[0], dtype=pp.constants.PARMES_REAL_GPU, order='F') + self.gvelo.data[1] = np.asarray(self.gvelo.data[1], dtype=pp.constants.PARMES_REAL_GPU, order='F') + self.gvelo.data[2] = np.asarray(self.gvelo.data[2], dtype=pp.constants.PARMES_REAL_GPU, order='F') + self.gscal.data = np.asarray(self.gscal.data, dtype=pp.constants.PARMES_REAL_GPU, order='F') + self.pos.gpu_data = cl.Buffer(self.ctx, cl.mem_flags.READ_WRITE, + size=self.pos.data.nbytes) + self.scal.gpu_data = cl.Buffer(self.ctx, cl.mem_flags.READ_WRITE, + size=self.scal.data.nbytes) + self.gvelo.gpu_data = [cl.Buffer(self.ctx, cl.mem_flags.READ_WRITE, + size=gvelo.nbytes) for gvelo in self.gvelo.data] + self.gscal.gpu_data = cl.Buffer(self.ctx, cl.mem_flags.READ_WRITE, + size=self.gscal.data.nbytes) + cl.enqueue_copy(self.queue, self.gscal.gpu_data, self.gscal.data) + cl.enqueue_copy(self.queue, self.gvelo.gpu_data[0], self.gvelo.data[0]) + cl.enqueue_copy(self.queue, self.gvelo.gpu_data[1], self.gvelo.data[1]) + cl.enqueue_copy(self.queue, self.gvelo.gpu_data[2], self.gvelo.data[2]) + self.transport = pp.Transport(self.g_velocity, self.g_scalar) + self.transport.discretize(result_position=self.p_positions, result_scalar=self.p_scalar) + self.transport.setMethod(pp.particular_solvers.gpu.KernelLauncher(self.prg_basic.advection, + self.queue, + (32, 32, 32), None)) + self.transport.discreteOperator.init_copy = pp.particular_solvers.gpu.KernelLauncher(self.prg_basic.advec_init_copy, + self.queue, + (32, 32, 32), None) + self.transport.discreteOperator.init_transpose = pp.particular_solvers.gpu.KernelListLauncher([self.prg_basic.advec_init_transpose_3D_01, + self.prg_basic.advec_init_transpose_3D_02], + self.queue, + [(2 * int(self.nbElem[0]), + int(self.nbElem[1]) / 32, + int(self.nbElem[2])), + (2 * int(self.nbElem[0]), + int(self.nbElem[1]), + int(self.nbElem[2]) / 32) + ], + [None, + None]) + + def setUp(self): + try: + self.platform = cl.get_platforms()[0] + self.device = self.platform.get_devices(cl.device_type.GPU)[0] + self.ctx = cl.Context([self.device]) + self.queue = cl.CommandQueue(self.ctx, properties=cl.command_queue_properties.PROFILING_ENABLE) + f = open(pp.constants.GPU_SRC, 'r') + self.gpu_src = "".join(f.readlines()) + f.close() + self.test = True + print "Testing on " + self.device.name + except Exception: + self.test = False + print "No tests because no GPU" + + def tearDown(self): + pass + + def test_apply_basic(self): + """Test advection basic""" + if self.test: + self.setUp_OpenCL_basic() + self.transport.discreteOperator.apply(0., 0.1, 0) + print self.scal.domain.step + self.queue.finish() + cl.enqueue_copy(self.queue, self.pos.data, self.pos.gpu_data) + cl.enqueue_copy(self.queue, self.scal.data, self.scal.gpu_data) + self.queue.finish() + print np.max(self.pos.data),np.min(self.pos.data) + print self.pos.data[1,1,1], self.true_pos.data[1,1,1] + np.testing.assert_array_almost_equal(self.pos.data, self.true_pos.data) + np.testing.assert_array_almost_equal(self.scal.data, self.gscal.data) + +if __name__ == "__main__": + unittest.TextTestRunner(verbosity=2).run( + unittest.TestLoader().loadTestsFromTestCase(Transport_dTestCase) + ) diff --git a/HySoP/hysop/test/test_particular_solvers/__init__.py b/HySoP/hysop/test/test_particular_solvers/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/HySoP/hysop/test/test_particular_solvers/test_gpu.py b/HySoP/hysop/test/test_particular_solvers/test_gpu.py new file mode 100644 index 0000000000000000000000000000000000000000..7faf41c86625723641b7f48fbd0d021d40768ca9 --- /dev/null +++ b/HySoP/hysop/test/test_particular_solvers/test_gpu.py @@ -0,0 +1,157 @@ +""" +Module for testing parmepy.operator.transport_d +""" + +import unittest +import parmepy as pp +import numpy as np +import pyopencl as cl + + +class GPUParticleSolverTestCase(unittest.TestCase): + + def setUp_OpenCL_basic(self): + self.b = pp.Box() + self.nbElem = [10, 10, 10] + self.topo = pp.CartesianTopology(domain=self.b, + resolution=self.nbElem, + dim=len(self.nbElem)) + build_options = "-cl-single-precision-constant -cl-opt-disable" + build_options += " -D WIDTH=10" + build_options += " -D WGN=10" + build_options += " -D PADDING=0" + build_options += " -D BASIC=1" + self.prg_basic = cl.Program(self.ctx, self.gpu_src).build(build_options) + self.p_positions = pp.fields.continuous.ContinuousField(self.b, + name="test_field_positions") + self.true_p_positions = pp.fields.analytical.AnalyticalField(self.b, + formula=lambda x,y,z:x, + name="test_field_true_positions") + self.p_vitesse = pp.fields.analytical.AnalyticalField(self.b, + formula=lambda x, y, z: 0., + name="test_field_velocity") + self.pos, self.pos_id = self.p_positions.discretize(self.topo) + self.velo, self.velo_id = self.p_vitesse.discretize(self.topo) + self.true_pos, self.velo_id = self.true_p_positions.discretize(self.topo) + self.true_p_positions.initialize() + self.pos.data = np.asarray(self.pos.data, dtype=pp.constants.PARMES_REAL_GPU, order='F') + self.velo.data = np.asarray(self.velo.data, dtype=pp.constants.PARMES_REAL_GPU, order='F') + self.pos.gpu_data = cl.Buffer(self.ctx, cl.mem_flags.READ_WRITE, + size=self.pos.data.nbytes) + self.velo.gpu_data = cl.Buffer(self.ctx, cl.mem_flags.READ_WRITE, + size=self.velo.data.nbytes) + cl.enqueue_copy(self.queue, self.velo.gpu_data, self.velo.data) + + + def setUp_OpenCL_opt(self): + self.b = pp.Box() + self.nbElem = [256, 256, 256] + self.topo = pp.CartesianTopology(domain=self.b, + resolution=self.nbElem, + dim=len(self.nbElem)) + build_options = "-cl-single-precision-constant -cl-opt-disable" + build_options += " -D WIDTH=256" + build_options += " -D WGN=64" + build_options += " -D PADDING=0" + self.prg_opt = cl.Program(self.ctx, self.gpu_src).build(build_options) + self.p_positions = pp.fields.continuous.ContinuousField(self.b, + name="test_field_positions") + self.true_p_positions = pp.fields.analytical.AnalyticalField(self.b, + formula=lambda x,y,z:x, + name="test_field_true_positions") + self.p_vitesse = pp.fields.analytical.AnalyticalField(self.b, + formula=lambda x, y, z: 0., + name="test_field_velocity") + self.pos, self.pos_id = self.p_positions.discretize(self.topo) + self.velo, self.velo_id = self.p_vitesse.discretize(self.topo) + self.true_pos, self.velo_id = self.true_p_positions.discretize(self.topo) + self.true_p_positions.initialize() + self.pos.data = np.asarray(self.pos.data, dtype=pp.constants.PARMES_REAL_GPU, order='F') + self.velo.data = np.asarray(self.velo.data, dtype=pp.constants.PARMES_REAL_GPU, order='F') + self.pos.gpu_data = cl.Buffer(self.ctx, cl.mem_flags.READ_WRITE, + size=self.pos.data.nbytes) + self.velo.gpu_data = cl.Buffer(self.ctx, cl.mem_flags.READ_WRITE, + size=self.velo.data.nbytes) + cl.enqueue_copy(self.queue, self.velo.gpu_data, self.velo.data) + + def setUp(self): + try: + self.platform = cl.get_platforms()[0] + self.device = self.platform.get_devices(cl.device_type.GPU)[0] + self.ctx = cl.Context([self.device]) + self.queue = cl.CommandQueue(self.ctx, properties=cl.command_queue_properties.PROFILING_ENABLE) + f = open(pp.constants.GPU_SRC, 'r') + self.gpu_src = "".join(f.readlines()) + f.close() + self.test = True + print "Testing on " + self.device.name + except Exception: + self.test = False + print "No tests because no GPU" + + def tearDown(self): + pass + + def test_advection_basic_kernel(self): + """Test advection basic kernel""" + if self.test: + self.setUp_OpenCL_basic() + self.queue.finish() + self.prg_basic.advection(self.queue, (10, 10, 10), None, + self.velo.gpu_data, self.pos.gpu_data, + pp.constants.PARMES_REAL_GPU(0.1), + pp.constants.PARMES_REAL_GPU(0.), + pp.constants.PARMES_REAL_GPU(1/10.)) + self.pos.data[...] = 0. + self.queue.finish() + cl.enqueue_copy(self.queue, self.pos.data, self.pos.gpu_data) + self.queue.finish() + np.testing.assert_array_almost_equal(self.pos.data, self.true_pos.data) + self.velo.data[...] = 1. + cl.enqueue_copy(self.queue, self.velo.gpu_data, self.velo.data) + self.queue.finish() + self.prg_basic.advection(self.queue, (10, 10, 10), None, + self.velo.gpu_data, self.pos.gpu_data, + pp.constants.PARMES_REAL_GPU(0.1), + pp.constants.PARMES_REAL_GPU(0.), + pp.constants.PARMES_REAL_GPU(1/10.)) + self.pos.data[...] = 0. + self.queue.finish() + cl.enqueue_copy(self.queue, self.pos.data, self.pos.gpu_data) + self.queue.finish() + np.testing.assert_array_almost_equal(self.pos.data, self.true_pos.data+.1) + + def test_advection_opt_kernel(self): + """Test advection basic kernel""" + if self.test: + self.setUp_OpenCL_opt() + self.queue.finish() + self.prg_opt.advection(self.queue, (64, 256, 256), (64, 1, 1), + self.velo.gpu_data, self.pos.gpu_data, + pp.constants.PARMES_REAL_GPU(0.1), + pp.constants.PARMES_REAL_GPU(0.), + pp.constants.PARMES_REAL_GPU(1/256.)) + self.pos.data[...] = 0. + self.queue.finish() + cl.enqueue_copy(self.queue, self.pos.data, self.pos.gpu_data) + self.queue.finish() + np.testing.assert_array_almost_equal(self.pos.data, self.true_pos.data) + self.velo.data[...] = 1. + cl.enqueue_copy(self.queue, self.velo.gpu_data, self.velo.data) + self.queue.finish() + self.prg_opt.advection(self.queue, (64, 256, 256), (64, 1, 1), + self.velo.gpu_data, self.pos.gpu_data, + pp.constants.PARMES_REAL_GPU(0.1), + pp.constants.PARMES_REAL_GPU(0.), + pp.constants.PARMES_REAL_GPU(1/256.)) + self.pos.data[...] = 0. + self.queue.finish() + cl.enqueue_copy(self.queue, self.pos.data, self.pos.gpu_data) + self.queue.finish() + np.testing.assert_array_almost_equal(self.pos.data, self.true_pos.data+.1) + + +if __name__ == "__main__": + unittest.TextTestRunner(verbosity=2).run( + unittest.TestLoader().loadTestsFromTestCase(GPUParticleSolverTestCase) + ) diff --git a/HySoP/hysop/tools/explore_hardware.py b/HySoP/hysop/tools/explore_hardware.py new file mode 100644 index 0000000000000000000000000000000000000000..cd57323f31bd3a50b981556225ceae8314d7e69e --- /dev/null +++ b/HySoP/hysop/tools/explore_hardware.py @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- +""" +@package parmepy.tools.explore_hardware +Module for exploring hardware with OpenCL. + +Find all platforms and all devices availables. +Gives some informations. +""" +import pyopencl as cl + + +def explore(): + """Explore hardware.""" + print "OpenCL exploration : " + platforms = cl.get_platforms() + platforms_info = ["name", "version", "vendor", "profile", "extensions"] + devices_info = ["name", "version", "vendor", "profile", "extensions", + "available", "type", "compiler_available", "double_fp_config", "single_fp_config", + "global_mem_size", "global_mem_cache_type", "global_mem_cache_size", "global_mem_cacheline_size", + "local_mem_size", "local_mem_type", "max_clock_frequency", "max_compute_units", + "max_constant_buffer_size", "max_mem_alloc_size", "max_work_group_size", + "max_work_item_dimensions", "max_work_item_sizes", + "preferred_vector_width_double", "preferred_vector_width_float", "preferred_vector_width_int"] + for pltfm in platforms: + print "Platform:", pltfm.name + for pltfm_info in platforms_info: + print " |-", pltfm_info, ':', eval("pltfm." + pltfm_info) + devices = pltfm.get_devices() + for dvc in devices: + print " |- Device:", dvc.name + for dvc_info in devices_info: + print " |-", dvc_info, ':', eval("dvc." + dvc_info) diff --git a/HySoP/setup.py.in b/HySoP/setup.py.in index e9ff02d77a1d1f319c0f5c4bdbe5f5ad7cb701f6..38e3520a1303a8df93fabedf8ea7df98e7caccf2 100644 --- a/HySoP/setup.py.in +++ b/HySoP/setup.py.in @@ -5,6 +5,7 @@ setup.py file for @PYPACKAGE_NAME@ """ from numpy.distutils.core import setup, Extension +from numpy.distutils.misc_util import Configuration import os import glob import sys @@ -20,7 +21,12 @@ packages = ['parmepy', 'parmepy.operator', 'parmepy.problem', 'parmepy.particular_solvers', - 'parmepy.tools'] + 'parmepy.tools', + 'parmepy.test', + 'parmepy.test.test_domain', + 'parmepy.test.test_field', + 'parmepy.test.test_operator', + 'parmepy.test.test_particular_solvers'] # 'examples'] # Enable this to get debug info @@ -51,7 +57,7 @@ enable_fortran = False withfftw = "@WITH_FFTW@" if(withfftw is "ON"): #fortran_src = glob.glob('@CMAKE_SOURCE_DIR@/parmepy/f2py/*.f90') - + fortran_src = [fortran_dir+'parameters.f90',fortran_dir+'fftw2py.f90'] enable_fortran = True fftwdir = '@FFTWLIB@' @@ -59,7 +65,7 @@ if(withfftw is "ON"): parmeslib.append('fftw3') parmeslib.append('fftw3_mpi') parmes_libdir.append(fftwdir) - + withscales = '@WITH_SCALES@' if(withscales is "ON"): fortran_src.append(fortran_dir+'scales2py.f90') @@ -77,8 +83,8 @@ if(enable_fortran): define_macros=[('F2PY_REPORT_ON_ARRAY_COPY', '1')]) ext_modules.append(parpyModule) -setup(name=name, - version='1.0.0', +config = Configuration(name=name, + version='@PYPACKAGE_VERSION@', description='Particular Methods implementation in Python', author='Jean-Matthieu Etancelin, Franck Pérignon, Christophe Picard', author_email='parmes-devel@lists.forge.imag.fr', @@ -89,3 +95,15 @@ setup(name=name, packages=packages, data_files=[('./parmepy/particular_solvers', ['@CMAKE_SOURCE_DIR@/parmepy/particular_solvers/gpu_src.cl'])] ) + +setup(**config.todict()) + +cTestFile = open('@CMAKE_CURRENT_BINARY_DIR@/CTestTestfile.cmake','r') +cTestStr = "" +for line in cTestFile: + cTestStr += line.replace('BUILD_MAIN_PYTEST', config.get_build_temp_dir().replace('temp','lib')+'/parmepy/test/main_unit_tests.py') +cTestFile.close() +cTestFile = open('@CMAKE_CURRENT_BINARY_DIR@/CTestTestfile.cmake','w') +cTestFile.write(cTestStr) +cTestFile.close() + diff --git a/HySoP/src/CMakeLists.txt b/HySoP/src/CMakeLists.txt index ccf746ce1bafc0a4077edd248f76cad4b8c3c10e..df4317d6d5aa9ad24cb143539f0a96d535908ce0 100644 --- a/HySoP/src/CMakeLists.txt +++ b/HySoP/src/CMakeLists.txt @@ -1,25 +1,25 @@ #======================================================= -# cmake utility to compile,link and install : +# cmake utility to compile,link and install : # - parmes library (libparmes...) # - library particular solver from scales -# +# #======================================================= # --- Set a version number for the package --- set(${PARMES_LIBRARY_NAME}_version 1.0.0) # --- The name of the exe to be created (test purpose) -# This exe will be linked with libPARMES_LIBRARY_NAME +# This exe will be linked with libPARMES_LIBRARY_NAME set(EXE_NAME ${PARMES_LIBRARY_NAME}Run) # The list of all dirs containing sources to be compiled for the Parmes lib # Any file in those dirs will be used to create libparmes -set(${PARMES_LIBRARY_NAME}_SRCDIRS +set(${PARMES_LIBRARY_NAME}_SRCDIRS . poisson ) # --- scales --- if(WITH_SCALES) - set(${PARMES_LIBRARY_NAME}_SRCDIRS + set(${PARMES_LIBRARY_NAME}_SRCDIRS ${${PARMES_LIBRARY_NAME}_SRCDIRS} scalesInterface/ scalesInterface/layout @@ -32,22 +32,22 @@ endif() # A main file to create an executable (test purpose) # Any files in these dirs will be used to create Parmes exec (linked with libparmes) set(${EXE_NAME}_SRCDIRS main) -# Matching expr for files to be compiled. +# Matching expr for files to be compiled. set(EXTS *.f90 *.f95) # Matching expr for headers (install purpose) set(EXTS_HDRS *.hpp *.h) # Note FP : we can also use cmake vars ${CMAKE_Fortran_SOURCE_FILE_EXTENSIONS} ${CMAKE_C_SOURCE_FILE_EXTENSIONS} ${CMAKE_CXX_SOURCE_FILE_EXTENSIONS} # ============= The project ============= -# Set project name and project languages +# Set project name and project languages # => this automatically defines: # - ${PARMES_LIBRARY_NAME}_BINARY_DIR : where you have run cmake, i.e. the place for compilation # - ${PARMES_LIBRARY_NAME}_SOURCE_DIR : where sources (.f and .h and this CMakeLists.txt) are located -# Note that because of OutOfSourceBuild, binary_dir and source_dir must be different. +# Note that because of OutOfSourceBuild, binary_dir and source_dir must be different. project(${PARMES_LIBRARY_NAME} Fortran) # ============= Search for libraries ============= -# We search for libraries Parmes depends on and +# We search for libraries Parmes depends on and # set the compile/link conf (-I and -L opt) # --- Boost --- @@ -61,11 +61,11 @@ project(${PARMES_LIBRARY_NAME} Fortran) # Force a default build type if not provided by user # CMAKE_BUILD_TYPE = empty, Debug, Release, RelWithDebInfo or MinSizeRel. if (NOT CMAKE_BUILD_TYPE) - set (CMAKE_BUILD_TYPE RELEASE CACHE STRING "Choose the type of build, options are: None, Debug, Release, RelWithDebInfo or MinSizeRel." FORCE) + set (CMAKE_BUILD_TYPE RELEASE CACHE STRING "Choose the type of build, options are: None, Debug, Release, RelWithDebInfo or MinSizeRel." FORCE) endif (NOT CMAKE_BUILD_TYPE) # If the project uses Fortran ... -# Set module files directory (i.e. where .mod will be created) +# Set module files directory (i.e. where .mod will be created) set(CMAKE_Fortran_MODULE_DIRECTORY ${CMAKE_BINARY_DIR}/Modules) # Add compilation flags: append_Fortran_FLAGS("-Wall -fPIC") @@ -94,7 +94,7 @@ if(EXISTS ${CMAKE_SOURCE_DIR}/config.hpp.cmake) endif() # ============= Source and header files list ============= -# We scan all files with matching extension in directories +# We scan all files with matching extension in directories # containing sources. # Source and header files list: @@ -125,7 +125,7 @@ foreach(_DIR ${${EXE_NAME}_SRCDIRS}) list(APPEND ${EXE_NAME}_SRC ${_DIR_FILES_EXT}) endif() endforeach() - foreach(_EXT ${EXTS_HDRS}) + foreach(_EXT ${EXTS_HDRS}) file(GLOB _DIR_FILES_EXT ${_DIR}/${_EXT}) if(_DIR_FILES_EXT) list(APPEND ${EXE_NAME}_HDRS ${_DIR_FILES_EXT}) @@ -142,7 +142,7 @@ include_directories(${CMAKE_Fortran_MODULE_DIRECTORY}) # Cmake tools to handle fortran-c interface. It will generate F2CMangle.hpp, a file # that will contain some useful macros to deal with fortran-C name mangling. -# See cmake doc for this module. +# See cmake doc for this module. #include(FortranCInterface) #FortranCInterface_HEADER(${CMAKE_Fortran_MODULE_DIRECTORY}/F2CMangle.hpp # MACRO_NAMESPACE "F2C_" @@ -169,14 +169,14 @@ target_link_libraries(${EXE_NAME} ${LIBS}) # ============== Add tests ============== if(WITH_TESTS) message(STATUS "Enable testing ...") - begin_test(src/tests/F2003) - new_test(testAllocatedPtr userMod.f90 wrapper.f90 testAllocatedPtr.cxx) - new_test(testNullPtr userMod.f90 wrapper.f90 testNullPtr.cxx) - end_test() - begin_test(src/tests/Particles) - new_test(testCreate3D testCreate3D.f90) - new_test(testCreate2D testCreate2D.f90) - end_test() +# begin_test(src/tests/F2003) +# new_test(testAllocatedPtr userMod.f90 wrapper.f90 testAllocatedPtr.cxx) +# new_test(testNullPtr userMod.f90 wrapper.f90 testNullPtr.cxx) +# end_test() +# begin_test(src/tests/Particles) +# new_test(testCreate3D testCreate3D.f90) +# new_test(testCreate2D testCreate2D.f90) +# end_test() endif(WITH_TESTS) # ============= Prepare install ============= @@ -190,7 +190,7 @@ if(${PARMES_LIBRARY_NAME}_HDRS}) else() install_package(${PACKAGE_NAME} ${PARMES_LIBRARY_NAME}) endif() -#install(TARGETS ${EXE_NAME} +#install(TARGETS ${EXE_NAME} #RUNTIME DESTINATION bin # executables # )