diff --git a/setup.py b/setup.py index b87b13a808514f6cf666837b5570337f8a721e28..6f8712d727e90d1af93e599ed618d67ad68da860 100644 --- a/setup.py +++ b/setup.py @@ -1,28 +1,36 @@ #!/usr/bin/env python3 -descr = """ -Wrapper around the SPH cosmological simulation code SWIFT -""" - from setuptools import setup, find_packages, Extension import sys import os from glob import glob import numpy +descr = """ +Wrapper around the SPH cosmological simulation code SWIFT +""" + +with_omp = True os.environ["CC"] = "mpicc" -cflags = ["-Werror", - "-Wall", - "-Wextra", - # disables some warnings due to python - "-Wno-unused-parameter", - "-Wno-strict-prototypes", - "-Wno-unused-function", - "-Wno-incompatible-pointer-types", - "-Wno-missing-field-initializers", +cflags = [ + "-Werror", + "-Wall", + "-Wextra", + # disables some warnings due to python + "-Wno-unused-parameter", + "-Wno-strict-prototypes", + "-Wno-unused-function", + "-Wno-incompatible-pointer-types", + "-Wno-missing-field-initializers", + "-fopenmp" ] +lflags = [ + "-fopenmp" + ] + + # deal with arguments def parseCmdLine(arg, store=False): ret = False @@ -37,11 +45,12 @@ def parseCmdLine(arg, store=False): sys.argv.remove(arg) return ret - + + swift_path = parseCmdLine("--with-swift", store=True) # python lib dependency -install_requires=["numpy"] +install_requires = ["numpy"] def getValueFromMakefile(swift_root, value): @@ -51,7 +60,7 @@ def getValueFromMakefile(swift_root, value): with open(makefile, "r") as f: for line in f.readlines(): if value == line[:N]: - return line[N:-1] # remove \n + return line[N:-1] # remove \n raise ValueError("Value %s not found in Makefile" % value) @@ -80,9 +89,10 @@ if swift_path: include.append(grackle_inc) # C libraries -lib = ["m", - "swiftsim", - "hdf5", +lib = [ + "m", + "swiftsim", + "hdf5", ] lib_dir = [] @@ -90,7 +100,7 @@ lib_dir = [] if swift_path: lib_dir.append(swift_path + "/src/.libs") lib_dir.append(hdf5_root + "/lib") - + # src files c_src = [] @@ -99,7 +109,7 @@ data_files = [] ############## -## C ext +# C ext ############## c_src = glob("src/*.c") @@ -108,45 +118,41 @@ ext_modules = Extension("pyswiftsim.wrapper", include_dirs=include, libraries=lib, library_dirs=lib_dir, - extra_compile_args=cflags) + extra_compile_args=cflags, + extra_link_args=lflags) ext_modules = [ext_modules] - + ############## -## data +# data ############## data_files = [] ############## -## scripts +# scripts ############## list_scripts = [] ############## -## Setup +# Setup ############## setup( - name = "pyswiftsim", - version = "0.1", - author = "Hausammann Loic", - author_email = "loic.hausammann@epfl.ch", - description = descr, - license = "GPLv3", - keywords = "nbody sph simulation hpc", - url = "", - - packages = find_packages(), - - data_files = data_files, - - scripts = list_scripts, - - install_requires = install_requires, - - dependency_links = dependency_links, - - ext_modules = ext_modules, + name="pyswiftsim", + version="0.1", + author="Hausammann Loic", + author_email="loic.hausammann@epfl.ch", + description=descr, + license="GPLv3", + keywords="nbody sph simulation hpc", + url="", + + packages=find_packages(), + data_files=data_files, + scripts=list_scripts, + install_requires=install_requires, + dependency_links=dependency_links, + ext_modules=ext_modules, ) diff --git a/src/config_wrapper.h b/src/config_wrapper.h index 3bc7a954e0d8a3fef33088317b767caa9c1d0f14..5a17aeb3c933dc9b36a7884bc11125c7a2b5c9ef 100644 --- a/src/config_wrapper.h +++ b/src/config_wrapper.h @@ -16,13 +16,17 @@ PyObject* config_get_cooling() { /* grackle */ #elif defined(COOLING_GRACKLE) -#ifdef CONFIG_BFLOAT_4 - cooling_name = "grackle_float"; -#elif CONFIG_BFLOAT_8 - cooling_name = "grackle_double"; +#if COOLING_GRACKLE_MODE == 0 + cooling_name = "grackle"; +#elif COOLING_GRACKLE_MODE == 1 + cooling_name = "grackle1"; +#elif COOLING_GRACKLE_MODE == 2 + cooling_name = "grackle2"; +#elif COOLING_GRACKLE_MODE == 3 + cooling_name = "grackle3"; #else - error("Impossible to config for grackle"); -#endif // CONFIG_BFLOAT + error("Grackle mode unknown"); +#endif // COOLING_GRACKLE_MODE #endif // COOLING_GRACKLE return PyUnicode_FromString(cooling_name); diff --git a/src/cooling_wrapper.c b/src/cooling_wrapper.c index 6047370445aeb18143381f2586068b51384a294c..11f5bdb97a6d694e8f3c396553034d31bc723015 100644 --- a/src/cooling_wrapper.c +++ b/src/cooling_wrapper.c @@ -1,7 +1,18 @@ #include "pyswiftsim_tools.h" #include "cooling_wrapper.h" - - +#include <omp.h> + + +/** + * @brief Initialize the cooling + * + * args is expecting pyswiftsim classes in the following order: + * SwiftParams, UnitSystem and PhysConst. + * + * @param self calling object + * @param args arguments + * @return CoolingFunctionData + */ PyObject* pycooling_init(PyObject* self, PyObject* args) { PyObject *pyparams; PyObject *pyus; @@ -35,6 +46,52 @@ PyObject* pycooling_init(PyObject* self, PyObject* args) { return pycooling; } +/** + * @brief Set the cooling element fractions + * + * @param xp The #xpart to set + * @param frac The numpy array containing the fractions (id, element) + * @param idx The id (in frac) of the particle to set + */ +void pycooling_set_fractions(struct xpart *xp, PyArrayObject* frac, const int idx) { + struct cooling_xpart_data *data = &xp->cooling_data; + data->metal_frac = *(float*)PyArray_GETPTR2(frac, idx, 0); + +#ifdef COOLING_GRACKLE +#if COOLING_GRACKLE_MODE > 0 + data->HI_frac = *(float*)PyArray_GETPTR2(frac, idx, 1); + data->HII_frac = *(float*)PyArray_GETPTR2(frac, idx, 2); + data->HeI_frac = *(float*)PyArray_GETPTR2(frac, idx, 3); + data->HeII_frac = *(float*)PyArray_GETPTR2(frac, idx, 4); + data->HeIII_frac = *(float*)PyArray_GETPTR2(frac, idx, 5); + data->e_frac = *(float*)PyArray_GETPTR2(frac, idx, 6); +#endif // COOLING_GRACKLE_MODE +#if COOLING_GRACKLE_MODE > 1 + data->HM_frac = *(float*)PyArray_GETPTR2(frac, idx, 7); + data->H2I_frac = *(float*)PyArray_GETPTR2(frac, idx, 8); + data->H2II_frac = *(float*)PyArray_GETPTR2(frac, idx, 9); +#endif // COOLING_GRACKLE_MODE +#if COOLING_GRACKLE_MODE > 2 + data->DI_frac = *(float*)PyArray_GETPTR2(frac, idx, 10); + data->DII_frac = *(float*)PyArray_GETPTR2(frac, idx, 11); + data->HDI_frac = *(float*)PyArray_GETPTR2(frac, idx, 12); +#endif // COOLING_GRACKLE_MODE +#endif // COOLING_GRACKLE + +} + +/** + * @brief Compute cooling rate + * + * args is expecting pyswiftsim classes in the following order: + * PhysConst, UnitSystem and CoolingFunctionData. + * Then two numpy arrays (density and specific energy) and an optional + * float for the time step + * + * @param self calling object + * @param args arguments + * @return cooling rate + */ PyArrayObject* pycooling_rate(PyObject* self, PyObject* args) { import_array(); @@ -44,35 +101,40 @@ PyArrayObject* pycooling_rate(PyObject* self, PyObject* args) { PyArrayObject *rho; PyArrayObject *energy; + PyArrayObject *fractions = NULL; float dt = 1e-3; /* parse argument */ if (!PyArg_ParseTuple(args, - "OOOOO|f", + "OOOOO|fOO", &pypconst, &pyus, &pycooling, &rho, &energy, - &dt)) + &dt, + &fractions + )) return NULL; /* check numpy array */ if (pytools_check_array(energy, 1, NPY_FLOAT) != SUCCESS) - { - return NULL; - } + return NULL; if (pytools_check_array(rho, 1, NPY_FLOAT) != SUCCESS) - { - return NULL; - } + return NULL; + + if (fractions != NULL && + pytools_check_array(fractions, 2, NPY_FLOAT) != SUCCESS) + return NULL; if (PyArray_DIM(energy, 0) != PyArray_DIM(rho, 0)) - { - pyerror("Density and energy should have the same dimension"); - } + pyerror("Density and energy should have the same dimension"); + + if (fractions != NULL && + PyArray_DIM(fractions, 0) != PyArray_DIM(rho,0)) + pyerror("Fractions should have the same first dimension than the others"); size_t N = PyArray_DIM(energy, 0); @@ -101,7 +163,11 @@ PyArrayObject* pycooling_rate(PyObject* self, PyObject* args) { /* return object */ PyArrayObject *rate = PyArray_SimpleNew(PyArray_NDIM(energy), PyArray_DIMS(energy), NPY_FLOAT); + /* Release GIL */ + Py_BEGIN_ALLOW_THREADS; + /* loop over all particles */ +#pragma omp for for(size_t i = 0; i < N; i++) { /* set particle data */ @@ -109,8 +175,11 @@ PyArrayObject* pycooling_rate(PyObject* self, PyObject* args) { float u = *(float*) PyArray_GETPTR1(energy, i); p.entropy = gas_entropy_from_internal_energy(p.rho, u); - cooling_first_init_part(&p, &xp, cooling); - + if (fractions != NULL) + pycooling_set_fractions(&xp, fractions, i); + else + cooling_first_init_part(&p, &xp, cooling); + /* compute cooling rate */ float *tmp = PyArray_GETPTR1(rate, i); #ifdef COOLING_GRACKLE @@ -120,6 +189,9 @@ PyArrayObject* pycooling_rate(PyObject* self, PyObject* args) { #endif } + /* Acquire GIL */ + Py_END_ALLOW_THREADS; + return rate; } diff --git a/src/cooling_wrapper.h b/src/cooling_wrapper.h index 4fbdd8abbc746d5d42aa4e32baa707c7770aa602..95717e8ac5d2867b25ddcebe33548fe86ecfa6cc 100644 --- a/src/cooling_wrapper.h +++ b/src/cooling_wrapper.h @@ -3,30 +3,8 @@ #include "pyswiftsim_tools.h" -/** - * @brief Initialize the cooling - * - * args is expecting pyswiftsim classes in the following order: - * SwiftParams, UnitSystem and PhysConst. - * - * @param self calling object - * @param args arguments - * @return CoolingFunctionData - */ PyObject* pycooling_init(PyObject* self, PyObject* args); -/** - * @brief Compute cooling rate - * - * args is expecting pyswiftsim classes in the following order: - * PhysConst, UnitSystem and CoolingFunctionData. - * Then two numpy arrays (density and specific energy) and an optional - * float for the time step - * - * @param self calling object - * @param args arguments - * @return cooling rate - */ PyArrayObject* pycooling_rate(PyObject* self, PyObject* args); #endif // __PYSWIFTSIM_COOLING_H__ diff --git a/src/wrapper.c b/src/wrapper.c index 12e7ef2b12653c9648e91bdf1c727cddb6993395..46076c5cb627eaed51654bb02107fcaeefcbbfb6 100644 --- a/src/wrapper.c +++ b/src/wrapper.c @@ -30,7 +30,21 @@ static PyMethodDef wrapper_methods[] = { "Initialize cooling."}, {"coolingRate", pycooling_rate, METH_VARARGS, - "Compute the cooling rate."}, + "Compute the cooling rate.\n\n" + "Parameters\n" + "----------\n\n" + "pyconst: swift physical constant\n" + "pyus: swift unit system\n" + "cooling: swift cooling structure\n" + "rho: np.array\n" + "\t Mass density in pyus units\n" + "energy: np.array\n" + "\t Internal energy in pyus units\n" + "dt: float, optional\n" + "\t Time step in pyus units\n" + "fractions: np.array, optional\n" + "\t Fraction of each cooling element (including metals)\n" + }, {"configGetCooling", config_get_cooling, METH_VARARGS, "Get the cooling type."},