diff --git a/.gitignore b/.gitignore index e4e5f6c8b2deb54bf38312dd9e2f53489b60d6a6..68ac6223c076dcd2a3315a51b721e0515a6f2a8a 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -*~ \ No newline at end of file +*~ +*.hdf5 \ No newline at end of file diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000000000000000000000000000000000000..d202675ba9a917e0cd9db1c0fd569fc037c444cd --- /dev/null +++ b/AUTHORS @@ -0,0 +1,2 @@ +Loic Hausammann loic.hausammann@epfl.ch +Yves Revaz yves.revaz@epfl.ch diff --git a/COPYING b/COPYING new file mode 120000 index 0000000000000000000000000000000000000000..88798ab60d0071429c816e50551d74789c45a51a --- /dev/null +++ b/COPYING @@ -0,0 +1 @@ +/usr/share/automake-1.15/COPYING \ No newline at end of file diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/INSTALL b/INSTALL new file mode 120000 index 0000000000000000000000000000000000000000..ddcdb76b36bd0e6c66dda2e2a0b0f48bfffc7109 --- /dev/null +++ b/INSTALL @@ -0,0 +1 @@ +/usr/share/automake-1.15/INSTALL \ No newline at end of file diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000000000000000000000000000000000000..3195eae8221667b0734e984c6c8ee4d21a187856 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,21 @@ +# This file is part of PySWIFTsim. +# Copyright (c) 2019 loic.hausammann@epfl.ch +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# Automake stuff +ACLOCAL_AMFLAGS = -I m4 + +# Show the way... +SUBDIRS = src diff --git a/NEWS b/NEWS new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/README b/README new file mode 120000 index 0000000000000000000000000000000000000000..602d87dfd9405502dcd988b9dab5bb724dc4471d --- /dev/null +++ b/README @@ -0,0 +1 @@ +Readme.md \ No newline at end of file diff --git a/Readme.md b/Readme.md index 4cb9fdfb8e46e71cebb31aff1b97db3b923ae2ee..35a4f470363f3463f9600b28f85ce3bf5a6d001c 100644 --- a/Readme.md +++ b/Readme.md @@ -6,6 +6,13 @@ This code is a python wrapper around the cosmological hydrodynamical code SWIFT A few examples are given in test and the API is trying to follow the SWIFT API, therefore a developer of SWIFT should be able to quickly learn how to use it. +Install +======= + +To install PySWIFT, you can run the following command: `python3 setup.py install --with-swift SWIFT_PATH --user`. +The setup script will read all your parameters in the config file of swift, therefore you need to reinstall PySWIFT with each configuration of SWIFT. +You may need to remove the build directory to recompile PySWIFT. + Adding a new structure ====================== diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000000000000000000000000000000000000..f9353c57a215829c97255817266d01f20f2d2c5b --- /dev/null +++ b/configure.ac @@ -0,0 +1,145 @@ +# This file is part of SWIFT. +# Copyright (C) 2012 pedro.gonnet@durham.ac.uk. +# 2016 p.w.draper@durham.ac.uk. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# Init the project. +AC_INIT([PySWIFTsim],[0.1.0],[https://gitlab.cosma.dur.ac.uk/swift/PySWIFTsim]) + +swift_config_flags="$*" + +# We want to stop when given unrecognised options. No subdirs so this is safe. +enable_option_checking=${enable_option_checking:-fatal} +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) + ;; + fatal) + { $as_echo "$as_me: error: unrecognized options: $ac_unrecognized_opts" >&2 + { (exit 1); exit 1; }; } + ;; + *) + $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 + ;; + esac +fi + +AC_COPYRIGHT +AC_CONFIG_SRCDIR([src/wrapper.c]) +AC_CONFIG_AUX_DIR([.]) +AM_INIT_AUTOMAKE([subdir-objects]) + +# Add local macro collection. +AC_CONFIG_MACRO_DIR([m4]) + +# Stop default CFLAGS from anyone except the environment. +: ${CFLAGS=""} + +# Generate header file. +AM_CONFIG_HEADER(config.h) + +# Find and test the compiler. +AX_CHECK_ENABLE_DEBUG +AC_PROG_CC +AM_PROG_CC_C_O + +# Enable POSIX and platform extension preprocessor macros. +AC_USE_SYSTEM_EXTENSIONS + +# Check for compiler version and vendor. +AX_COMPILER_VENDOR +AX_COMPILER_VERSION + +# Restrict support. +AC_C_RESTRICT + + +# Add libtool support (now that CC is defined). +LT_INIT + +# Need C99 and inline support. +AC_PROG_CC_C99 +AC_C_INLINE + +# Need fortran for grackle and velociraptor +AC_PROG_FC +AC_FC_LIBRARY_LDFLAGS + + +# Define HAVE_POSIX_MEMALIGN if it works. +AX_FUNC_POSIX_MEMALIGN + +# Autoconf stuff. +AC_PROG_INSTALL +AC_PROG_MAKE_SET +AC_HEADER_STDC + +SWIFT_ADD_LIBRARIES + +SWIFT_ADD_SPECIAL_FLAGS + +# this one should be at the beginning +# it overwrites all the required parameters +SWIFT_ADD_SUBGRID_MODELS + + + +SWIFT_ADD_GRAVITY + +SWIFT_ADD_HYDRO + +SWIFT_ADD_STARS + +SWIFT_ADD_KERNEL + +SWIFT_ADD_DIMENSION + +SWIFT_ADD_EQUATION_OF_STATE + +SWIFT_ADD_CHEMISTRY + +SWIFT_ADD_COOLING + +SWIFT_ADD_RIEMANN + +SWIFT_ADD_TRACER + +PYSWIFT_ADD_PYTHON + +# Check for git, needed for revision stamps. +AC_PATH_PROG([GIT_CMD], [git]) +AC_SUBST([GIT_CMD]) + +# Make the documentation. Add conditional to handle disable option. +DX_INIT_DOXYGEN(libswift,doc/Doxyfile,doc/) +AM_CONDITIONAL([HAVE_DOXYGEN], [test "$ac_cv_path_ac_pt_DX_DOXYGEN" != ""]) + +# Check if using EAGLE cooling +AM_CONDITIONAL([HAVEEAGLECOOLING], [test $with_cooling = "EAGLE"]) + +# Handle .in files. +AC_CONFIG_FILES([Makefile src/Makefile]) + +# Save the compilation options +AC_DEFINE_UNQUOTED([PYSWIFT_CONFIG_FLAGS],["$swift_config_flags"],[Flags passed to configure]) + +# Make sure the latest git revision string gets included, when we are +# working in a checked out repository. +test -d ${srcdir}/.git && touch ${srcdir}/src/version.c + +AC_DEFINE([PYSWIFT_PACKAGE_URL],["www.swiftsim.com"], [Package web pages]) + +# Generate output. +AC_OUTPUT diff --git a/examples/cooling_box/CloudyData_UVB=HM2012.h5 b/examples/cooling_box/CloudyData_UVB=HM2012.h5 new file mode 100644 index 0000000000000000000000000000000000000000..1e35a914e33cb6465b48babba8730ba47a92f6f2 Binary files /dev/null and b/examples/cooling_box/CloudyData_UVB=HM2012.h5 differ diff --git a/examples/cooling_box/cooling.yml b/examples/cooling_box/cooling.yml new file mode 100644 index 0000000000000000000000000000000000000000..cbcb4c555033d6204cd1fbffcd1a70e613a3d47c --- /dev/null +++ b/examples/cooling_box/cooling.yml @@ -0,0 +1,60 @@ +# Define the system of units to use internally. +InternalUnitSystem: + UnitMass_in_cgs: 2.e33 # Grams + UnitLength_in_cgs: 3.085e21 # Centimeters + UnitVelocity_in_cgs: 1e5 # Centimeters per second + UnitCurrent_in_cgs: 1 # Amperes + UnitTemp_in_cgs: 1 # Kelvin + +# Parameters governing the time integration +TimeIntegration: + time_begin: 0. # The starting time of the simulation (in internal units). + time_end: 5e-2 # The end time of the simulation (in internal units). + dt_min: 1e-7 # The minimal time-step size of the simulation (in internal units). + dt_max: 1e-4 # The maximal time-step size of the simulation (in internal units). + +# Parameters governing the snapshots +Snapshots: + basename: sedov # Common part of the name of output files + time_first: 0. # Time of the first output (in internal units) + delta_time: 1e-2 # Time difference between consecutive outputs (in internal units) + +# Parameters governing the conserved quantities statistics +Statistics: + delta_time: 1e-3 # Time between statistics output + tasks_per_cell: 1000 + +# Parameters for the hydrodynamics scheme +SPH: + resolution_eta: 1.2348 # Target smoothing length in units of the mean inter-particle separation (1.2348 == 48Ngbs with the cubic spline kernel). + CFL_condition: 0.1 # Courant-Friedrich-Levy condition for time integration. + +# Parameters related to the initial conditions +InitialConditions: + file_name: ./sedov.hdf5 # The file to read + h_scaling: 3.33 + + +# Cooling with Grackle 2.0 +GrackleCooling: + CloudyTable: CloudyData_UVB=HM2012.h5 # Name of the Cloudy Table + WithUVbackground: 1 # Enable or not the UV background + Redshift: 0 # Redshift to use (-1 means time based redshift) + WithMetalCooling: 1 # Enable or not the metal cooling + ProvideVolumetricHeatingRates: 0 # User provide volumetric heating rates + ProvideSpecificHeatingRates: 0 # User provide specific heating rates + SelfShieldingMethod: 0 # Grackle (<= 3) or Gear self shielding method + OutputMode: 0 # Write in output corresponding primordial chemistry mode + MaxSteps: 1000 + ConvergenceLimit: 1e-2 + +Gravity: + eta: 0.025 # Constant dimensionless multiplier for time integration. + theta: 0.7 # Opening angle (Multipole acceptance criterion) + epsilon: 0.1 # Softening length (in internal units). + a_smooth: 1.25 # (Optional) Smoothing scale in top-level cell sizes to smooth the long-range forces over (this is the default value). + r_cut_max: 4.5 # (Optional) Cut-off in number of top-level cells beyond which no FMM forces are computed (this is the default value). + r_cut_min: 0.1 # (Optional) Cut-off in number of top-level cells below which no truncation of FMM forces are performed (this is the default value). + +GearChemistry: + InitialMetallicity: 0.01295 \ No newline at end of file diff --git a/examples/cooling_box/generate_grackle_data.py b/examples/cooling_box/generate_grackle_data.py new file mode 100644 index 0000000000000000000000000000000000000000..e9ed1bb77a4e05a2534773fdbfb8d40d51f8e152 --- /dev/null +++ b/examples/cooling_box/generate_grackle_data.py @@ -0,0 +1,262 @@ +#!/usr/bin/env python +######################################################################## +# +# Cooling rate data generation. This code is a modified version +# of a code developed by the Grackle Team. +# +# +# Copyright (c) 2013-2016, Grackle Development Team. +# +# Distributed under the terms of the Enzo Public Licence. +# +# The full license is in the file LICENSE, distributed with this +# software. +######################################################################## + +""" +Generate (or update) a hdf5 file containing +the grackle data for each primordial chemistry +""" + +import numpy as np +from h5py import File + +from pygrackle import \ + chemistry_data, \ + setup_fluid_container + +from pygrackle.utilities.physical_constants import \ + mass_hydrogen_cgs + +filename = "grackle.hdf5" + +# metal_mass_fraction = 1e-10 +metal_mass_fraction = 0.01295 + +tolerance = 1e-1 +max_iter = 1e8 + +t_end = 1. # in cooling time +N_time = 1000 + +part_density = 1.0 # in atom/cc +part_temperature = 1e6 # in K + + +def generate_data(primordial_chemistry): + """ + Compute the cooling a single particles and save its evolution + to an hdf5 file + """ + current_redshift = 0. + + # Set solver parameters + my_chemistry = chemistry_data() + my_chemistry.use_grackle = 1 + my_chemistry.with_radiative_cooling = 1 + my_chemistry.primordial_chemistry = primordial_chemistry + my_chemistry.metal_cooling = 1 + my_chemistry.UVbackground = 1 + my_chemistry.self_shielding_method = 0 + my_chemistry.H2_self_shielding = 0 + my_chemistry.grackle_data_file = "CloudyData_UVB=HM2012.h5" + + # Set units + my_chemistry.comoving_coordinates = 0 # proper units + my_chemistry.a_units = 1.0 + my_chemistry.a_value = 1.0 / (1.0 + current_redshift) / \ + my_chemistry.a_units + my_chemistry.length_units = 3.085e21 + my_chemistry.density_units = 2.0e33 / my_chemistry.length_units**3 + my_chemistry.velocity_units = 1e5 + my_chemistry.time_units = my_chemistry.length_units / \ + my_chemistry.velocity_units + + density = np.array([part_density * mass_hydrogen_cgs]) + # Call convenience function for setting up a fluid container. + # This container holds the solver parameters, units, and fields. + temperature = np.array([part_temperature]) + fc = setup_fluid_container(my_chemistry, + metal_mass_fraction=metal_mass_fraction, + temperature=temperature, + density=density, + converge=True, + tolerance=tolerance, + max_iterations=max_iter) + + # compute time steps + fc.calculate_cooling_time() + t_max = t_end * abs(fc["cooling_time"]) + + t = np.linspace(0, t_max, N_time) + + f, data = write_input( + fc, my_chemistry, primordial_chemistry) + + dt = t[1] - t[0] + + # compute evolution + E = np.zeros(t.shape) + E[0] = fc["energy"] + for i in range(N_time-1): + fc.solve_chemistry(dt) + E[i+1] = fc["energy"] + + write_output(f, data, fc, t, E) + + +def write_output(f, data, fc, t, E): + """ + Write the output of the simulation + """ + data.create_group("Output") + tmp = data["Output"] + + # Energy + dset = tmp.create_dataset("Energy", E.shape, + dtype=E.dtype) + dset[:] = E + + # Time + dset = tmp.create_dataset("Time", t.shape, + dtype=t.dtype) + dset[:] = t + + f.close() + + +def simulationAreEqual(fields, data): + """ + Check if current simulation has already + been run + """ + test = True + for key in fields.keys(): + if data.attrs[key] != fields[key]: + test = False + break + + return test + + +def getSameSimulation(data, density, my_chemistry): + """ + Get indice of the same simulation. + returns -1 if not found + """ + fields = { + "MetalCooling": my_chemistry.metal_cooling, + "UVBackground": my_chemistry.UVbackground, + "SelfShieldingMethod": my_chemistry.self_shielding_method, + "MetalMassFraction": metal_mass_fraction, + "ScaleFactor": my_chemistry.a_value, + "Temperature": part_temperature, + "Density": density, + } + ind = 0 + for d in data: + if "Params" in data[d]: + tmp = data[d]["Params"] + if simulationAreEqual(fields, tmp): + return ind + ind += 1 + + return -1 + + +def write_input(fc, my_chemistry, primordial_chemistry): + """ + Write the simulation input in the HDF5 file + """ + f = File(filename, "a") + data_name = "PrimordialChemistry%i" % primordial_chemistry + if data_name in f: + data = f[data_name] + else: + print("Creating Dataset") + data = f.create_group(data_name) + + i = getSameSimulation(data, fc["density"], my_chemistry) + if i != -1: + print("Updating Simulation") + data.pop(data.keys()[i]) + data = data.create_group("Simulation %i" % len(data)) + + # Units + data.create_group("Units") + tmp = data["Units"] + tmp.attrs["Length"] = my_chemistry.length_units + tmp.attrs["Density"] = my_chemistry.density_units + tmp.attrs["Velocity"] = my_chemistry.velocity_units + tmp.attrs["Time"] = my_chemistry.time_units + + # Parameters + data.create_group("Params") + tmp = data["Params"] + tmp.attrs["MetalCooling"] = my_chemistry.metal_cooling + tmp.attrs["UVBackground"] = my_chemistry.UVbackground + tmp.attrs["SelfShieldingMethod"] = my_chemistry.self_shielding_method + tmp.attrs["MetalMassFraction"] = metal_mass_fraction + tmp.attrs["ScaleFactor"] = my_chemistry.a_value + tmp.attrs["Tolerance"] = tolerance + tmp.attrs["MaxIter"] = max_iter + tmp.attrs["Density"] = fc["density"] + tmp.attrs["Temperature"] = part_temperature + tmp.attrs["Energy"] = fc["energy"][0] + + # Inputs + data.create_group("Input") + tmp = data["Input"] + + write_fractions(tmp, fc, primordial_chemistry) + + return f, data + + +def write_fractions(tmp, fc, primordial_chemistry): + """ + Write the element fractions in the HDF5 file + """ + fields = get_fields(primordial_chemistry) + for i in fields: + dset = tmp.create_dataset(i, fc[i].shape, + dtype=fc[i].dtype) + dset[:] = fc[i] / fc["density"] + + +def get_fields(primordial_chemistry): + """ + Return the fields present in grackle + """ + fields = [ + "metal" + ] + if primordial_chemistry > 0: + fields.extend([ + "HI", + "HII", + "HeI", + "HeII", + "HeIII", + "de"]) + + if primordial_chemistry > 1: + fields.extend([ + "HM", + "H2I", + "H2II" + ]) + + if primordial_chemistry > 2: + fields.extend([ + "DI", + "DII", + "HDI" + ]) + return fields + + +if __name__ == "__main__": + for i in range(4): + print("Computing Primordial Chemistry %i" % i) + generate_data(i) diff --git a/examples/cooling_box/getCoolingTable.sh b/examples/cooling_box/getCoolingTable.sh new file mode 100644 index 0000000000000000000000000000000000000000..809958bfc236e5ab0f7be924c62789fa13b3ac29 --- /dev/null +++ b/examples/cooling_box/getCoolingTable.sh @@ -0,0 +1,2 @@ +#!/bin/bash +wget http://virgodb.cosma.dur.ac.uk/swift-webstorage/CoolingTables/CloudyData_UVB=HM2012.h5 diff --git a/examples/cooling_box/plot_cooling.py b/examples/cooling_box/plot_cooling.py new file mode 100644 index 0000000000000000000000000000000000000000..917ea82d48a324c1a5fbceb076b89f865129a5dd --- /dev/null +++ b/examples/cooling_box/plot_cooling.py @@ -0,0 +1,335 @@ +#!/usr/bin/env python3 +""" +This file is part of PYSWIFTSIM. +Copyright (c) 2018 Loic Hausammann (loic.hausammann@epfl.ch) + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published +by the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +""" + +from pyswiftsim import wrapper + +import numpy as np +import matplotlib.pyplot as plt +from os.path import isfile +from h5py import File +from glob import glob + +plt.rc('text', usetex=True) + +# PARAMETERS + +# grackle primordial chemistry (for comparison) +primordial_chemistry = 0 + +# reference data +grackle_filename = "grackle.hdf5" +compute_equilibrium = False + +# swift params filename +filename = "cooling.yml" + +# particle data +# in atom/cc if generating +# if reading => same than in grackle.hdf5 +part_density = 2.4570967948472597e7 +part_temperature = 1e6 # in K +gamma = 5./3. + +# default parameters +t_end = 1. +N_time = 100000 + +# cooling output +swift_output_filename = "swift.hdf5" + +# simulations +simulations = { + "SWIFT": "/home/loikki/data/swiftsim/examples/CoolingBox/coolingBox_*.hdf5" +} +# SCRIPT + + +def get_fields(primordial_chemistry): + fields = [ + "metal" + ] + if primordial_chemistry > 0: + fields.extend([ + "HI", + "HII", + "HeI", + "HeII", + "HeIII", + "de"]) + + if primordial_chemistry > 1: + fields.extend([ + "HM", + "H2I", + "H2II" + ]) + + if primordial_chemistry > 2: + fields.extend([ + "DI", + "DII", + "HDI" + ]) + return fields + + +def generate_default_initial_condition(us, pconst): + print("Generating default initial conditions") + d = {} + # generate grid + d["temperature"] = part_temperature + + # Deal with units + rho = part_density * us.UnitLength_in_cgs**3 * pconst.const_proton_mass + d["density"] = [rho] + + energy = pconst.const_boltzmann_k * part_temperature \ + / us.UnitTemperature_in_cgs + energy /= (gamma - 1.) * pconst.const_proton_mass + d["energy"] = energy + + d["time"] = np.linspace(0, t_end, N_time) + + return d + + +def get_io_fields(cooling, chemistry, output): + a = 1. / (1. + cooling.redshift) + fields = { + "MetalCooling": cooling.with_metal_cooling, + "UVBackground": cooling.with_uv_background, + "SelfShieldingMethod": cooling.self_shielding_method, + "MetalMassFraction": chemistry.initial_metallicity, + "ScaleFactor": a, + "Temperature": part_temperature, + "Density": part_density, + } + + if output: + fields.update({ + "MaxIter": cooling.max_step, + "Tolerance": cooling.convergence_limit, + }) + return fields + + +def getSimulationIndice(data, cooling, chemistry, output): + + fields = get_io_fields(cooling, chemistry, output) + + ind = 0 + for name in data: + test = True + d = data[name] + if "Params" in d: + tmp = d["Params"] + for key in fields.keys(): + check = abs(tmp.attrs[key] - fields[key]) > \ + 1e-3 * tmp.attrs[key] + if check: + test = False + break + if test: + break + ind += 1 + if ind == len(data): + return -1 + else: + return ind + + +def read_grackle_data(filename, us, pconst, primordial_chemistry, + cooling, chemistry): + print("Reading initial conditions") + f = File(filename, "r") + data = f["PrimordialChemistry%i" % primordial_chemistry] + + i = getSimulationIndice(data, cooling, chemistry, output=False) + if i < 0: + raise IOError("Unable to locate corresponding grackle simulation") + else: + tmp = list(data.keys()) + data = data[tmp[i]] + + # read units + tmp = data["Units"].attrs + + u_len = tmp["Length"] / us.UnitLength_in_cgs + u_time = tmp["Time"] / us.UnitTime_in_cgs + u_den = tmp["Density"] * us.UnitLength_in_cgs**3 / us.UnitMass_in_cgs + + # read input + tmp = data["Params"] + energy = tmp.attrs["Energy"] * u_len**2 / u_time**2 + d["energy"] = energy + + density = tmp.attrs["Density"] * u_den + d["density"] = density + + # # read fractions + # tmp = data["Input"] + # for i in get_fields(primordial_chemistry): + # d[i] = tmp[i][:] + + # read output + tmp = data["Output"] + + energy = tmp["Energy"][:] * u_len**2 / u_time**2 + d["out_energy"] = energy + + t = tmp["Time"][:] * u_time + d["time"] = t + + f.close() + return d + + +def initialize_swift(filename): + print("Initialization of SWIFT") + d = {} + + # parse swift params + params = wrapper.parserReadFile(filename) + d["params"] = params + + # init units + us, pconst = wrapper.unitSystemInit(params) + d["us"] = us + d["pconst"] = pconst + + cosmo = wrapper.cosmologyInit(params, us, pconst) + d["cosmo"] = cosmo + + # init cooling + cooling = wrapper.coolingInit(params, us, pconst) + d["cooling"] = cooling + + # init chemistry + chemistry = wrapper.chemistryInit(params, us, pconst) + d["chemistry"] = chemistry + + return d + + +def plot_solution(energy, data, us): + print("Plotting solution") + rho = data["density"] + time = data["time"] + + ref = False + if "out_energy" in data: + ref = True + grackle_energy = data["out_energy"] + + # change units => cgs + rho *= us.UnitMass_in_cgs / us.UnitLength_in_cgs**3 + + energy *= us.UnitLength_in_cgs**2 / us.UnitTime_in_cgs**2 + + if ref: + grackle_energy *= us.UnitLength_in_cgs**2 / us.UnitTime_in_cgs**2 + + time *= us.UnitTime_in_cgs + + # do plot + + plt.figure() + plt.plot(time, energy, label="PySWIFTsim, %s" % wrapper.configGetCooling()) + if ref: + plt.plot(time, grackle_energy, + label="Grackle, Prim. Chem. %i" % primordial_chemistry) + + for i in simulations: + files = glob(simulations[i]) + files.sort() + E = np.zeros([len(files)]) + t = np.zeros([len(files)]) + j = 0 + for f in files: + f = File(f) + tmp = f["Units"] + UL = tmp.attrs["Unit length in cgs (U_L)"] + UT = tmp.attrs["Unit time in cgs (U_t)"] + UE = UL**2 / UT**2 + tmp = f["PartType0"] + E[j] = np.mean(tmp["InternalEnergy"]) * UE + t[j] = f["Header"].attrs["Time"] * UT + print(t[j]) + j += 1 + cooling_type = f["SubgridScheme"].attrs["Cooling Model"] + plt.plot(t, E, label=i + ": " + cooling_type.decode("utf8")) + plt.xlabel("Time [s]") + plt.ylabel("Energy [erg]") + plt.legend() + plt.show() + + +if __name__ == "__main__": + + d = initialize_swift(filename) + pconst = d["pconst"] + us = d["us"] + params = d["params"] + cosmo = d["cosmo"] + cooling = d["cooling"] + chemistry = d["chemistry"] + + if isfile(grackle_filename) and False: + d = read_grackle_data(grackle_filename, us, pconst, + primordial_chemistry, cooling, + chemistry) + else: + d = generate_default_initial_condition(us, pconst) + + t = d["time"] + dt = t[1] - t[0] + + # du / dt + print("Computing cooling...") + + N = len(t) + energy = np.zeros(t.shape) + energy[0] = d["energy"] + rho = np.array(d["density"], dtype=np.float32) + for i in range(N-1): + ene = np.array([energy[i]], dtype=np.float32) + if not compute_equilibrium: + energy[i+1] = wrapper.doCooling(pconst, us, + cosmo, + cooling, + chemistry, + rho, + ene, + dt) + else: + fields = get_fields(primordial_chemistry) + N = len(fields) + frac = np.zeros([1, N]) + for j in range(N): + frac[:, j] = d[fields[j]] + energy[i+1] = wrapper.doCooling(pconst, us, + cosmo, + cooling, + chemistry, + rho, + ene, + dt, + frac.astype(np.float32)) + + plot_solution(energy, d, us) diff --git a/examples/cooling_box/run.sh b/examples/cooling_box/run.sh new file mode 100644 index 0000000000000000000000000000000000000000..d2f01dae43b010839cddca2d11d20d474dd76f0f --- /dev/null +++ b/examples/cooling_box/run.sh @@ -0,0 +1,17 @@ +#!/bin/bash + +# Get the Grackle cooling table +if [ ! -e CloudyData_UVB=HM2012.h5 ] +then + echo "Fetching the Cloudy tables required by Grackle..." + ./getCoolingTable.sh +fi + +# generate grackle data +if [ ! -e grackle.hdf5 ] +then + echo "Generating Grackle data..." + ./generate_grackle_data.py +fi + +./plot_cooling.py diff --git a/examples/cooling_rate/cooling.yml b/examples/cooling_rate/cooling.yml index 54c4cf3c2ecdfe33e16cb28ebe16243206ecffac..10608d34b8e2fcdb2ad2db441e5b0ae655195541 100644 --- a/examples/cooling_rate/cooling.yml +++ b/examples/cooling_rate/cooling.yml @@ -34,6 +34,17 @@ InitialConditions: file_name: ./sedov.hdf5 # The file to read h_scaling: 3.33 +# Cosmological parameters +Cosmology: + h: 0.6777 # Reduced Hubble constant + a_begin: 0.0078125 # Initial scale-factor of the simulation + a_end: 1.0 # Final scale factor of the simulation + Omega_m: 0.307 # Matter density parameter + Omega_lambda: 0.693 # Dark-energy density parameter + Omega_b: 0.0455 # Baryon density parameter + Omega_r: 0. # (Optional) Radiation density parameter + w_0: -1.0 # (Optional) Dark-energy equation-of-state parameter at z=0. + w_a: 0. # (Optional) Dark-energy equation-of-state time evolution parameter. # Cooling with Grackle 2.0 GrackleCooling: @@ -44,9 +55,9 @@ GrackleCooling: ProvideVolumetricHeatingRates: 0 # User provide volumetric heating rates ProvideSpecificHeatingRates: 0 # User provide specific heating rates SelfShieldingMethod: 0 # Grackle (<= 3) or Gear self shielding method - OutputMode: 0 # Write in output corresponding primordial chemistry mode - ConvergenceLimit: 1e-3 - MaxSteps: 100000 + ConvergenceLimit: 1e-4 + MaxSteps: 20000 + Omega: 0.8 Gravity: eta: 0.025 # Constant dimensionless multiplier for time integration. @@ -55,3 +66,6 @@ Gravity: a_smooth: 1.25 # (Optional) Smoothing scale in top-level cell sizes to smooth the long-range forces over (this is the default value). r_cut_max: 4.5 # (Optional) Cut-off in number of top-level cells beyond which no FMM forces are computed (this is the default value). r_cut_min: 0.1 # (Optional) Cut-off in number of top-level cells below which no truncation of FMM forces are performed (this is the default value). + +GearChemistry: + InitialMetallicity: 0.01295 \ No newline at end of file diff --git a/examples/cooling_rate/generate_grackle_data.py b/examples/cooling_rate/generate_grackle_data.py index 3ebb364bf9d227113b781cbf068ea2c86290219f..290c6611dd5a454242de02f94d8a6efa97291cca 100644 --- a/examples/cooling_rate/generate_grackle_data.py +++ b/examples/cooling_rate/generate_grackle_data.py @@ -34,8 +34,18 @@ filename = "grackle.hdf5" debug = 1 +# metal_mass_fraction = 1e-10 +metal_mass_fraction = 0.01295 + +tolerance = 1e-5 +max_iter = 1e8 + def generate_data(primordial_chemistry): + """ + Compute the cooling rate of a bunch of particles and save + them to an hdf5 file + """ current_redshift = 0. # Set solver parameters @@ -66,12 +76,12 @@ def generate_data(primordial_chemistry): # This container holds the solver parameters, units, and fields. temperature = np.logspace(1, 9, 1000) fc = setup_fluid_container(my_chemistry, - metal_mass_fraction=0.01295, + metal_mass_fraction=metal_mass_fraction, temperature=temperature, density=density, converge=True, - tolerance=1e-5, - max_iterations=1e8) + tolerance=tolerance, + max_iterations=max_iter) f, data = write_input( fc, my_chemistry, temperature, dt, primordial_chemistry) @@ -84,6 +94,9 @@ def generate_data(primordial_chemistry): def write_output(f, data, fc, rate): + """ + Write the output of the simulation + """ data.create_group("Output") tmp = data["Output"] # Rate @@ -98,17 +111,60 @@ def write_output(f, data, fc, rate): f.close() +def simulationAreEqual(fields, data): + """ + Check if current simulation has already + been run + """ + test = True + for key in fields.keys(): + if data.attrs[key] != fields[key]: + test = False + break + + return test + + +def getSameSimulation(data, my_chemistry): + """ + Get indice of the same simulation. + returns -1 if not found + """ + fields = { + "MetalCooling": my_chemistry.metal_cooling, + "UVBackground": my_chemistry.UVbackground, + "SelfShieldingMethod": my_chemistry.self_shielding_method, + "MetalMassFraction": metal_mass_fraction, + "ScaleFactor": my_chemistry.a_value + } + ind = 0 + for d in data: + if "Params" in data[d]: + tmp = data[d]["Params"] + if simulationAreEqual(fields, tmp): + return ind + ind += 1 + + return -1 + + def write_input(fc, my_chemistry, temperature, dt, primordial_chemistry): + """ + Write the simulation input in the HDF5 file + """ f = File(filename, "a") data_name = "PrimordialChemistry%i" % primordial_chemistry if data_name in f: - print("Updating Dataset") data = f[data_name] - f.pop(data_name) else: print("Creating Dataset") + data = f.create_group(data_name) - data = f.create_group(data_name) + i = getSameSimulation(data, my_chemistry) + if i != -1: + print("Updating Simulation") + data.pop(data.keys()[i]) + data = data.create_group("Simulation %i" % len(data)) # Units data.create_group("Units") @@ -124,7 +180,11 @@ def write_input(fc, my_chemistry, temperature, dt, primordial_chemistry): tmp.attrs["MetalCooling"] = my_chemistry.metal_cooling tmp.attrs["UVBackground"] = my_chemistry.UVbackground tmp.attrs["SelfShieldingMethod"] = my_chemistry.self_shielding_method + tmp.attrs["MetalMassFraction"] = metal_mass_fraction + tmp.attrs["ScaleFactor"] = my_chemistry.a_value tmp.attrs["TimeStep"] = dt + tmp.attrs["Tolerance"] = tolerance + tmp.attrs["MaxIter"] = max_iter # Inputs data.create_group("Input") @@ -148,6 +208,9 @@ def write_input(fc, my_chemistry, temperature, dt, primordial_chemistry): def write_fractions(tmp, fc, primordial_chemistry): + """ + Write the element fractions in the HDF5 file + """ fields = get_fields(primordial_chemistry) for i in fields: dset = tmp.create_dataset(i, fc[i].shape, @@ -156,6 +219,9 @@ def write_fractions(tmp, fc, primordial_chemistry): def get_fields(primordial_chemistry): + """ + Return the fields present in grackle + """ fields = [ "metal" ] diff --git a/examples/cooling_rate/plot_cooling.py b/examples/cooling_rate/plot_cooling.py index 1cf9aae0de8a26b35591506e3ab289d17933c53a..62bc5377c5de9357a543ac34faeb92c4de7ef063 100644 --- a/examples/cooling_rate/plot_cooling.py +++ b/examples/cooling_rate/plot_cooling.py @@ -1,24 +1,44 @@ #!/usr/bin/env python3 +""" +This file is part of PYSWIFTSIM. +Copyright (c) 2018 Loic Hausammann (loic.hausammann@epfl.ch) -from pyswiftsim import wrapper +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published +by the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +""" + +from libpyswiftsim import coolingRate from copy import deepcopy import numpy as np import matplotlib.pyplot as plt -from astropy import units +from astropy import units, constants from os.path import isfile from h5py import File +import yaml plt.rc('text', usetex=True) # PARAMETERS +# cosmology +with_cosmo = 0 -# grackle primordial chemistry -primordial_chemistry = 1 +# grackle primordial chemistry (for comparison) +primordial_chemistry = 0 # reference data grackle_filename = "grackle.hdf5" -compute_equilibrium = True +compute_equilibrium = False # swift params filename filename = "cooling.yml" @@ -36,7 +56,7 @@ else: default_density = np.logspace(-3, 1, N_rho) # temperature in K -N_T = 10 +N_T = 1000 default_temperature = np.logspace(1, 9, N_T) # time step in s @@ -46,6 +66,9 @@ default_dt = default_dt.to("s") / units.s # adiabatic index gamma = 5. / 3. +# cooling output +swift_output_filename = "swift.hdf5" + # SCRIPT @@ -78,7 +101,7 @@ def get_fields(primordial_chemistry): return fields -def generate_default_initial_condition(us, pconst): +def generate_default_initial_condition(us): print("Generating default initial conditions") d = {} # generate grid @@ -88,38 +111,60 @@ def generate_default_initial_condition(us, pconst): d["temperature"] = T # Deal with units - rho *= us.UnitLength_in_cgs**3 * pconst.const_proton_mass + m_p = constants.m_p.to("{} g".format(us["UnitLength_in_cgs"])) + rho *= us["UnitLength_in_cgs"]**3 * m_p d["density"] = rho - energy = pconst.const_boltzmann_k * T / us.UnitTemperature_in_cgs - energy /= (gamma - 1.) * pconst.const_proton_mass + unit_time = us["UnitLength_in_cgs"] / us["UnitVelocity_in_cgs"] + unit_energy = us["UnitMass_in_cgs"] * us["UnitLength_in_cgs"]**2 + unit_energy /= unit_time**2 + k_B = constants.k_B.to("{} J / {} K".format( + unit_energy, us["UnitTemp_in_cgs"] + )) + energy = k_B * T / us["UnitTemp_in_cgs"] + energy /= (gamma - 1.) * m_p d["energy"] = energy - dt = default_dt / us.UnitTime_in_cgs + dt = default_dt / unit_time d["time_step"] = dt return d -def read_grackle_data(filename, us, primordial_chemistry): +def read_grackle_data(filename, us): print("Reading initial conditions") f = File(filename, "r") data = f["PrimordialChemistry%i" % primordial_chemistry] +<<<<<<< HEAD + print(cooling) + i = getSimulationIndice(data, cooling, chemistry, output=False) + if i < 0: + raise IOError("Unable to locate corresponding grackle simulation") + else: + tmp = list(data.keys()) + data = data[tmp[i]] +======= + data = data[grackle_simulation] +>>>>>>> 083548de07e9dd7ccb17d962bb3e253d656c0a83 + # read units tmp = data["Units"].attrs - u_len = tmp["Length"] / us.UnitLength_in_cgs - u_den = tmp["Density"] * us.UnitLength_in_cgs**3 / us.UnitMass_in_cgs - u_time = tmp["Time"] / us.UnitTime_in_cgs + u_len = tmp["Length"] / float(us["UnitLength_in_cgs"]) + u_den = tmp["Density"] * float(us["UnitLength_in_cgs"])**3 + u_den /= float(us["UnitMass_in_cgs"]) + u_time = float(us["UnitLength_in_cgs"]) / float(us["UnitVelocity_in_cgs"]) + u_time = tmp["Time"] / u_time # read input tmp = data["Input"] + d = {} energy = tmp["Energy"][:] * u_len**2 / u_time**2 d["energy"] = energy - T = tmp["Temperature"][:] / us.UnitTemperature_in_cgs + T = tmp["Temperature"][:] / float(us["UnitTemp_in_cgs"]) d["temperature"] = T density = tmp["Density"][:] * u_den @@ -145,23 +190,10 @@ def read_grackle_data(filename, us, primordial_chemistry): return d -def initialize_swift(filename): - print("Initialization of SWIFT") - d = {} - - # parse swift params - params = wrapper.parserReadFile(filename) - d["params"] = params - - # init units - us, pconst = wrapper.unitSystemInit(params) - d["us"] = us - d["pconst"] = pconst - - # init cooling - cooling = wrapper.coolingInit(params, us, pconst) - d["cooling"] = cooling - return d +def getParser(filename): + with open(filename, "r") as stream: + stream = yaml.load(stream) + return stream def plot_solution(rate, data, us): @@ -176,16 +208,19 @@ def plot_solution(rate, data, us): grackle_rate = data["rate"] # change units => cgs - rho *= us.UnitMass_in_cgs / us.UnitLength_in_cgs**3 + u_m = float(us["UnitMass_in_cgs"]) + u_l = float(us["UnitLength_in_cgs"]) + u_t = float(us["UnitLength_in_cgs"]) / float(us["UnitVelocity_in_cgs"]) + rho *= u_m / u_l**3 - T *= us.UnitTemperature_in_cgs + T *= float(us["UnitTemp_in_cgs"]) - energy *= us.UnitLength_in_cgs**2 / us.UnitTime_in_cgs**2 + energy *= u_l**2 / u_t**2 - rate *= us.UnitLength_in_cgs**2 / us.UnitTime_in_cgs**3 + rate *= u_l**2 / u_t**3 if ref: - grackle_rate *= us.UnitLength_in_cgs**2 / us.UnitTime_in_cgs**3 + grackle_rate *= u_l**2 / u_t**3 # lambda cooling lam = rate * rho @@ -198,7 +233,7 @@ def plot_solution(rate, data, us): # plot Lambda vs T plt.figure() plt.loglog(T, np.abs(lam), - label="SWIFT, %s" % wrapper.configGetCooling()) + label="SWIFT") if ref: # plot reference plt.loglog(T, np.abs(grackle_lam), @@ -247,32 +282,38 @@ def plot_solution(rate, data, us): tc = np.arange(_min, _max, 1.5) cbar.set_ticks(tc) cbar.set_ticklabels(tc) + cbar.ax.set_ylabel("Log( Cooling Length / kpc )") plt.show() if __name__ == "__main__": - d = initialize_swift(filename) - pconst = d["pconst"] - us = d["us"] - params = d["params"] - cooling = d["cooling"] + parser = getParser(filename) + us = parser["InternalUnitSystem"] - if isfile(grackle_filename): - d = read_grackle_data(grackle_filename, us, primordial_chemistry) + if isfile(grackle_filename) and N_rho == 1: + d = read_grackle_data(grackle_filename, us) else: - d = generate_default_initial_condition(us, pconst) + d = generate_default_initial_condition(us) # du / dt print("Computing cooling...") rate = np.zeros(d["density"].shape) if compute_equilibrium: - rate = wrapper.coolingRate(pconst, us, cooling, - d["density"].astype(np.float32), - d["energy"].astype(np.float32), - d["time_step"]) +<<<<<<< HEAD + rate = wrapper.coolingRate( + filename, + d["density"].astype(np.float32), + d["energy"].astype(np.float32), + d["time_step"]) +======= + rate = coolingRate(filename, with_cosmo, + d["density"].astype(np.float32), + d["energy"].astype(np.float32), + d["time_step"]) +>>>>>>> 083548de07e9dd7ccb17d962bb3e253d656c0a83 else: fields = get_fields(primordial_chemistry) N = len(fields) @@ -280,10 +321,10 @@ if __name__ == "__main__": for i in range(N): frac[:, i] = d[fields[i]] - rate = wrapper.coolingRate(pconst, us, cooling, - d["density"].astype(np.float32), - d["energy"].astype(np.float32), - d["time_step"], - frac.astype(np.float32)) + rate = coolingRate(filename, with_cosmo, + d["density"].astype(np.float32), + d["energy"].astype(np.float32), + d["time_step"], + frac.astype(np.float32)) plot_solution(rate, d, us) diff --git a/pyswiftsim/__init__.py b/pyswiftsim/__init__.py index 50a5cb6cd4d2eec05cc57e8c426c001cd68b2db3..526dbce334dd759ae3af7299c78404f02c44fa8d 100644 --- a/pyswiftsim/__init__.py +++ b/pyswiftsim/__init__.py @@ -1,2 +1,19 @@ +""" +This file is part of PYSWIFT. +Copyright (c) 2018 Loic Hausammann (loic.hausammann@epfl.ch) + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published +by the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +""" from pyswiftsim import * diff --git a/pyswiftsim/dev.py b/pyswiftsim/dev.py index 6646ecf4235022217387f0775c6fdf17ad3dd730..64561b3bcb36adc66df701352e5705d95afead36 100644 --- a/pyswiftsim/dev.py +++ b/pyswiftsim/dev.py @@ -1,4 +1,23 @@ #!/usr/bin/env python3 +""" +This file is part of PYSWIFT. +Copyright (c) 2018 Loic Hausammann (loic.hausammann@epfl.ch) + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published +by the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +""" + +from sys import argv symbol_table = { " int ": "i", @@ -6,6 +25,7 @@ symbol_table = { " char ": "c", } + def _generateFormatString(filename): """ Open a file containing a single struct and generate a format string @@ -14,7 +34,7 @@ def _generateFormatString(filename): struct_format = "" struct_attribute = [] - + with open(filename, "r") as f: line = "" # skip until reaching struct @@ -46,21 +66,20 @@ def _generateFormatString(filename): j = line.index(";") struct_attribute.append(line[i:j]) - return struct_format, struct_attribute - + if __name__ == "__main__": - filename = "chemistry_data.h" + filename = argv[-1] struct_format, struct_attribute = _generateFormatString(filename) attr = "[\n" for i in struct_attribute: attr += "\t'%s',\n" % i attr += "]" - + txt = """ _format = "{form}" _name = {attr} diff --git a/pyswiftsim/structure.py b/pyswiftsim/structure.py index 78a35b781e6062e2f133bbcdccb5d726ae67b440..184dff7107432e44cf71836d197c732db18a9ef0 100644 --- a/pyswiftsim/structure.py +++ b/pyswiftsim/structure.py @@ -1,3 +1,20 @@ +""" +This file is part of PYSWIFT. +Copyright (c) 2018 Loic Hausammann (loic.hausammann@epfl.ch) + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published +by the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +""" from pyswiftsim import wrapper import struct @@ -286,7 +303,7 @@ class UnitSystem(SwiftStruct): class ChemistryPartData(SwiftStruct): _format = "f" _name = [ - "he_density" + "initial_metallicity" ] def __init__(self, data, parent=None): @@ -330,14 +347,16 @@ class Part(SwiftStruct): # # ###################################################################### class Parameter(SwiftStruct): - _format = "{line_size}c{line_size}c".format( + _format = "{line_size}c{line_size}cii".format( line_size=PARSER_MAX_LINE_SIZE ) _name = [ - "name", - "value" - ] + "name", + "value", + "used", + "is_default" + ] def __init__(self, data, parent=None): super().__init__(self.struct_format, data, parent) @@ -406,14 +425,16 @@ class SwiftParams(SwiftStruct): # # ###################################################################### class PhysConst(SwiftStruct): - _format = "dddddddddddddddd" + _format = "ddddddddddddddddddddd" _name = [ "const_newton_G", "const_speed_light_c", "const_planck_h", "const_planck_hbar", "const_boltzmann_k", + "const_avogadro_number", "const_thomson_cross_section", + "const_stefan_boltzmann", "const_electron_charge", "const_electron_volt", "const_electron_mass", @@ -424,79 +445,9 @@ class PhysConst(SwiftStruct): "const_light_year", "const_solar_mass", "const_earth_mass", - ] - - def __init__(self, data, parent=None): - super().__init__(self.struct_format, data, parent) - - -class GrackleCodeUnits(SwiftStruct): - cooling_type = wrapper.configGetCooling() - _format = "idddddd" - if cooling_type == "grackle_float": - _format = _format.replace("d", "f") - _name = [ - "comoving_coordinates", - "density_units", - "length_units", - "time_units", - "velocity_units", - "a_units", - "a_value" - ] - - def __init__(self, data, parent=None): - super().__init__(self.struct_format, data, parent) - - -class GrackleChemistryData(SwiftStruct): - cooling_type = wrapper.configGetCooling() - _format = "iiiiiPidiidiiiiiiidddiiddiddiiddddddiiiiii" - if cooling_type == "grackle_float": - _format = _format.replace("d", "f") - _name = [ - 'use_grackle', - 'with_radiative_cooling', - 'primordial_chemistry', - 'metal_cooling', - 'UVbackground', - 'grackle_data_file', - 'cmb_temperature_floor', - 'Gamma', - 'h2_on_dust', - 'photoelectric_heating', - 'photoelectric_heating_rate', - 'use_volumetric_heating_rate', - 'use_specific_heating_rate', - 'three_body_rate', - 'cie_cooling', - 'h2_optical_depth_approximation', - 'ih2co', - 'ipiht', - 'HydrogenFractionByMass', - 'DeuteriumToHydrogenRatio', - 'SolarMetalFractionByMass', - 'NumberOfTemperatureBins', - 'CaseBRecombination', - 'TemperatureStart', - 'TemperatureEnd', - 'NumberOfDustTemperatureBins', - 'DustTemperatureStart', - 'DustTemperatureEnd', - 'Compton_xray_heating', - 'LWbackground_sawtooth_suppression', - 'LWbackground_intensity', - 'UVbackground_redshift_on', - 'UVbackground_redshift_off', - 'UVbackground_redshift_fullon', - 'UVbackground_redshift_drop', - 'cloudy_electron_fraction_factor', - 'use_radiative_transfer', - 'radiative_transfer_coupled_rate_solver', - 'radiative_transfer_intermediate_step', - 'radiative_transfer_hydrogen_only', - 'self_shielding_method', - 'H2_self_shielding', + "const_T_CMB_0", + "const_primordial_He_fraction", + "const_reduced_hubble" ] def __init__(self, data, parent=None): @@ -515,38 +466,98 @@ class CoolingFunctionData(SwiftStruct): "cooling_tstep_mult" ] elif "grackle" in cooling_type: - _format = "200cidd{code_units}s{chemistry}s".format( - code_units=struct.calcsize(GrackleCodeUnits._format), - chemistry=struct.calcsize(GrackleChemistryData._format) + _format = "200cid{code_units}c{chemistry}ciiiifif".format( + code_units=56, + chemistry=248 ) _name = [ - "GrackleCloudyTable", - "UVbackground", - "GrackleRedshift", - "GrackleHSShieldingDensityThreshold", + "cloudy_table", + "with_uv_background", + "redshift", "code_units", "chemistry", + "with_metal_cooling", + "provide_volumetric_heating_rate", + "provide_specificy_heating_rate", + "self_shielding_method", + "convergence_limit", + "max_step", + "omega" ] - @property - def struct_substruct(self): - chemistry = { - "class": GrackleChemistryData, - "size": 1 - } - - units = { - "class": GrackleCodeUnits, - "size": 1 - } - return { - "units": units, - "chemistry": chemistry - } - else: raise ValueError( "Cooling Type %s not implemented" % cooling_type) def __init__(self, data, parent=None): super().__init__(self.struct_format, data, parent) + + +class ChemistryGlobalData(SwiftStruct): + _format = "f" + _name = [ + "initial_metallicity", + ] + + def __init__(self, data, parent=None): + super().__init__(self.struct_format, data, parent) + +###################################################################### +# # +# PhysConst # +# # +###################################################################### + + +class Cosmology(SwiftStruct): + _format = "ddddddddddddddddddddddddddddddddddddppppdd" + _name = [ + 'a', + 'a_inv', + 'a2_inv', + 'a3_inv', + 'a_factor_internal_energy', + 'a_factor_pressure', + 'a_factor_sound_speed', + 'a_factor_mu', + 'a_factor_Balsara_eps', + 'a_factor_grav_accel', + 'a_factor_hydro_accel', + 'z', + 'H', + 'critical_density', + 'critical_density_0', + 'time_step_factor', + 'a_dot', + 'time', + 'lookback_time', + 'w', + 'a_begin', + 'a_end', + 'time_begin', + 'time_end', + 'time_base', + 'time_base_inv', + 'h', + 'H0', + 'Hubble_time', + 'Omega_m', + 'Omega_b', + 'Omega_lambda', + 'Omega_r', + 'Omega_k', + 'w_0', + 'w_a', + 'log_a_begin', + 'log_a_end', + 'drift_fac_interp_table', + 'grav_kick_fac_interp_table', + 'hydro_kick_fac_interp_table', + 'hydro_kick_corr_interp_table', + 'time_interp_table', + 'time_interp_table_offset', + 'universe_age_at_present_day', + ] + + def __init__(self, data, parent=None): + super().__init__(self.struct_format, data, parent) diff --git a/setup.py b/setup.py index 6f8712d727e90d1af93e599ed618d67ad68da860..919adee2849f4fc5dcc55e8dd88d25a6b2ccf337 100644 --- a/setup.py +++ b/setup.py @@ -17,13 +17,15 @@ cflags = [ "-Werror", "-Wall", "-Wextra", + "-Wshadow", # disables some warnings due to python "-Wno-unused-parameter", + "-Wno-maybe-uninitialized", "-Wno-strict-prototypes", "-Wno-unused-function", "-Wno-incompatible-pointer-types", "-Wno-missing-field-initializers", - "-fopenmp" + "-fopenmp", ] lflags = [ @@ -82,11 +84,14 @@ if swift_path: ]) # hdf5 + if "bin" in hdf5_root: + hdf5_root = hdf5_root.split("bin")[0] include.append(hdf5_root + "/include") # grackle - grackle_inc = getValueFromMakefile(swift_path, "GRACKLE_INCS = -I") - include.append(grackle_inc) + if parseCmdLine("--with-grackle", store=True): + grackle_inc = getValueFromMakefile(swift_path, "GRACKLE_INCS = -I") + include.append(grackle_inc) # C libraries lib = [ diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000000000000000000000000000000000000..a77473fd9cf45fb642c0175a3d22490b9b7f9084 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,68 @@ +# This file is part of PySWIFTsim. +# Copyright (c) 2019 Loic Hausammann (loic.hausammann@epfl.ch). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# Add the non-standard paths to the included library headers +AM_CFLAGS = -I$(top_srcdir)/../src $(HDF5_CPPFLAGS) $(GSL_INCS) $(FFTW_INCS) $(NUMA_INCS) $(GRACKLE_INCS) $(PYTHON_INCS) + +# Assign a "safe" version number +AM_LDFLAGS = $(HDF5_LDFLAGS) $(FFTW_LIBS) -version-info 0:0:0 + +# The git command, if available. +GIT_CMD = @GIT_CMD@ + +# Additional dependencies for shared libraries. +EXTRA_LIBS = $(HDF5_LIBS) $(FFTW_LIBS) $(NUMA_LIBS) $(PROFILER_LIBS) $(TCMALLOC_LIBS) \ + $(JEMALLOC_LIBS) $(TBBMALLOC_LIBS) $(GRACKLE_LIBS) $(GSL_LIBS) $(PYTHON_LIBS) \ + $(top_srcdir)/src/.libs + +# MPI libraries. +MPI_LIBS = $(PARMETIS_LIBS) $(METIS_LIBS) $(MPI_THREAD_LIBS) +MPI_FLAGS = -DWITH_MPI $(PARMETIS_INCS) $(METIS_INCS) + +# Build the libswiftsim library +lib_LTLIBRARIES = libpyswiftsim.la +# Build a MPI-enabled version too? +if HAVEMPI +lib_LTLIBRARIES += libpyswiftsim_mpi.la +endif + +# List required headers +include_HEADERS = chemistry_wrapper.h cooling_wrapper.h \ + cosmology_wrapper.h parser_wrapper.h part_wrapper.h \ + pyswiftsim_tools.h units_wrapper.h + + +# Common source files +AM_SOURCES = chemistry_wrapper.c cooling_wrapper.c cosmology_wrapper.c \ + parser_wrapper.c part_wrapper.c pyswiftsim_tools.c \ + units_wrapper.c wrapper.c + +# Include files for distribution, not installation. +nobase_noinst_HEADERS = + +# Sources and flags for regular library +libpyswiftsim_la_SOURCES = $(AM_SOURCES) +libpyswiftsim_la_CFLAGS = $(AM_CFLAGS) +libpyswiftsim_la_LDFLAGS = $(AM_LDFLAGS) $(EXTRA_LIBS) -lswiftsim +libpyswiftsim_la_LIBADD = $(GRACKLE_LIBS) $(VELOCIRAPTOR_LIBS) + +# Sources and flags for MPI library +libpyswiftsim_mpi_la_SOURCES = $(AM_SOURCES) +libpyswiftsim_mpi_la_CFLAGS = $(AM_CFLAGS) $(MPI_FLAGS) +libpyswiftsim_mpi_la_LDFLAGS = $(AM_LDFLAGS) $(MPI_LIBS) $(EXTRA_LIBS) -lswiftsim_mpi +libpyswiftsim_mpi_la_SHORTNAME = mpi +libpyswiftsim_mpi_la_LIBADD = $(GRACKLE_LIBS) $(VELOCIRAPTOR_LIBS) + diff --git a/src/chemistry_wrapper.c b/src/chemistry_wrapper.c new file mode 100644 index 0000000000000000000000000000000000000000..9c6cdc09f6f3919de4d69aa5ab1bab516808ed79 --- /dev/null +++ b/src/chemistry_wrapper.c @@ -0,0 +1,63 @@ +/******************************************************************************* + * This file is part of PYSWIFTSIM. + * Copyright (c) 2018 loic hausammann (loic.hausammann@epfl.ch) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + ******************************************************************************/ + +#include "pyswiftsim_tools.h" +#include "chemistry_wrapper.h" + +/** + * @brief Initialize the chemistry + * + * args is expecting pyswiftsim classes in the following order: + * SwiftParams, UnitSystem and PhysConst. + * + * @param self calling object + * @param args arguments + * @return ChemistryGlobalData + */ +PyObject* pychemistry_init(PyObject* self, PyObject* args) { + PyObject *pyparams; + PyObject *pyus; + PyObject *pypconst; + + /* parse arguments */ + if (!PyArg_ParseTuple(args, "OOO", &pyparams, &pyus, &pypconst)) + return NULL; + + struct swift_params *params = (struct swift_params*) pytools_construct(pyparams, class_swift_params); + if (params == NULL) + return NULL; + + struct unit_system *us = (struct unit_system*) pytools_construct(pyus, class_unit_system); + if (us == NULL) + return NULL; + + struct phys_const *pconst = (struct phys_const*) pytools_construct(pypconst, class_phys_const); + if (pconst == NULL) + return NULL; + + struct chemistry_global_data chemistry; + + /* init cooling */ + chemistry_init_backend(params, us, pconst, &chemistry); + + /* construct python object */ + PyObject *pychemistry = pytools_return(&chemistry, class_chemistry_global_data); + + return pychemistry; +} diff --git a/src/chemistry_wrapper.h b/src/chemistry_wrapper.h new file mode 100644 index 0000000000000000000000000000000000000000..31ab1593f820845104c044fb64a312c767bcdd6b --- /dev/null +++ b/src/chemistry_wrapper.h @@ -0,0 +1,27 @@ +/******************************************************************************* + * This file is part of PYSWIFTSIM. + * Copyright (c) 2018 loic hausammann (loic.hausammann@epfl.ch) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + ******************************************************************************/ +#ifndef __PYSWIFTSIM_CHEMISTRY_H__ +#define __PYSWIFTSIM_CHEMISTRY_H__ + +#include "pyswiftsim_tools.h" + +PyObject* pychemistry_init(PyObject* self, PyObject* args); + +#endif // __PYSWIFTSIM_CHEMISTRY_H__ + diff --git a/src/config_wrapper.h b/src/config_wrapper.h deleted file mode 100644 index 5a17aeb3c933dc9b36a7884bc11125c7a2b5c9ef..0000000000000000000000000000000000000000 --- a/src/config_wrapper.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef __PYSWIFTSIM_CONFIG_H__ -#define __PYSWIFTSIM_CONFIG_H__ - -#include "pyswiftsim_tools.h" - -/** - * @brief give the cooling type name - * - * @return Cooling name (PyUnicode) - */ -PyObject* config_get_cooling() { - char *cooling_name; - /* lambda */ -#ifdef COOLING_CONST_LAMBDA - cooling_name = "const_lambda"; - - /* grackle */ -#elif defined(COOLING_GRACKLE) -#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("Grackle mode unknown"); -#endif // COOLING_GRACKLE_MODE -#endif // COOLING_GRACKLE - - return PyUnicode_FromString(cooling_name); -}; - - -#endif // __PYSWIFTSIM_CONFIG_H__ diff --git a/src/cooling_wrapper.c b/src/cooling_wrapper.c index 11f5bdb97a6d694e8f3c396553034d31bc723015..8def5d2d1e23507a0edd4f438816df7a02aff522 100644 --- a/src/cooling_wrapper.c +++ b/src/cooling_wrapper.c @@ -1,50 +1,27 @@ -#include "pyswiftsim_tools.h" -#include "cooling_wrapper.h" -#include <omp.h> - - -/** - * @brief Initialize the cooling +/******************************************************************************* + * This file is part of PYSWIFTSIM. + * Copyright (c) 2018 loic hausammann (loic.hausammann@epfl.ch) * - * args is expecting pyswiftsim classes in the following order: - * SwiftParams, UnitSystem and PhysConst. + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * @param self calling object - * @param args arguments - * @return CoolingFunctionData - */ -PyObject* pycooling_init(PyObject* self, PyObject* args) { - PyObject *pyparams; - PyObject *pyus; - PyObject *pypconst; - - /* parse arguments */ - if (!PyArg_ParseTuple(args, "OOO", &pyparams, &pyus, &pypconst)) - return NULL; - - struct swift_params *params = (struct swift_params*) pytools_construct(pyparams, class_swift_params); - if (params == NULL) - return NULL; - - struct unit_system *us = (struct unit_system*) pytools_construct(pyus, class_unit_system); - if (us == NULL) - return NULL; - - struct phys_const *pconst = (struct phys_const*) pytools_construct(pypconst, class_phys_const); - if (pconst == NULL) - return NULL; - - - struct cooling_function_data cooling; + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + ******************************************************************************/ +#include "cooling_wrapper.h" - /* init cooling */ - cooling_init_backend(params, us, pconst, &cooling); +/* Local includes */ +#include "pyswiftsim_tools.h" +#include "part_wrapper.h" - /* construct python object */ - PyObject *pycooling = pytools_return(&cooling, class_cooling_function_data); - - return pycooling; -} /** * @brief Set the cooling element fractions @@ -54,6 +31,7 @@ PyObject* pycooling_init(PyObject* self, PyObject* args) { * @param idx The id (in frac) of the particle to set */ void pycooling_set_fractions(struct xpart *xp, PyArrayObject* frac, const int idx) { +#ifdef COOLING_GRACKLE struct cooling_xpart_data *data = &xp->cooling_data; data->metal_frac = *(float*)PyArray_GETPTR2(frac, idx, 0); @@ -78,6 +56,9 @@ void pycooling_set_fractions(struct xpart *xp, PyArrayObject* frac, const int id #endif // COOLING_GRACKLE_MODE #endif // COOLING_GRACKLE +#else + message("Not implemented"); +#endif } /** @@ -92,41 +73,34 @@ void pycooling_set_fractions(struct xpart *xp, PyArrayObject* frac, const int id * @param args arguments * @return cooling rate */ -PyArrayObject* pycooling_rate(PyObject* self, PyObject* args) { +PyObject* pycooling_rate(PyObject* self, PyObject* args) { import_array(); - PyObject *pycooling; - PyObject *pyus; - PyObject *pypconst; + + char *filename; PyArrayObject *rho; PyArrayObject *energy; PyArrayObject *fractions = NULL; float dt = 1e-3; + int with_cosmo = 0; /* parse argument */ - if (!PyArg_ParseTuple(args, - "OOOOO|fOO", - &pypconst, - &pyus, - &pycooling, - &rho, - &energy, - &dt, - &fractions - )) + if (!PyArg_ParseTuple( + args, "siOO|fO", &filename, &with_cosmo, + &rho, &energy, &dt, &fractions)) return NULL; /* check numpy array */ - if (pytools_check_array(energy, 1, NPY_FLOAT) != SUCCESS) + if (pytools_check_array(energy, 1, NPY_FLOAT, "Energy") != SUCCESS) return NULL; - if (pytools_check_array(rho, 1, NPY_FLOAT) != SUCCESS) + if (pytools_check_array(rho, 1, NPY_FLOAT, "Density") != SUCCESS) return NULL; if (fractions != NULL && - pytools_check_array(fractions, 2, NPY_FLOAT) != SUCCESS) + pytools_check_array(fractions, 2, NPY_FLOAT, "Fractions") != SUCCESS) return NULL; if (PyArray_DIM(energy, 0) != PyArray_DIM(rho, 0)) @@ -138,36 +112,42 @@ PyArrayObject* pycooling_rate(PyObject* self, PyObject* args) { size_t N = PyArray_DIM(energy, 0); - /* transform PyObject to C struct */ - struct cooling_function_data *cooling = (struct cooling_function_data*) pytools_construct(pycooling, class_cooling_function_data); - if (cooling == NULL) - return NULL; + /* Initialize everything */ + struct swift_params params; + parser_read_file(filename, ¶ms); - struct unit_system *us = (struct unit_system*) pytools_construct(pyus, class_unit_system); - if (us == NULL) - return NULL; + struct unit_system us; + units_init_from_params(&us, ¶ms, "InternalUnitSystem"); - struct phys_const *pconst = (struct phys_const*) pytools_construct(pypconst, class_phys_const); - if (pconst == NULL) - return NULL; + struct phys_const pconst; + phys_const_init(&us, ¶ms, &pconst); + + struct cooling_function_data cooling; + + /* init cooling */ + cooling_init_backend(¶ms, &us, &pconst, &cooling); + + struct chemistry_global_data chemistry; + chemistry_init_backend(¶ms, &us, &pconst, &chemistry); + + struct cosmology cosmo; + + if (with_cosmo) + cosmology_init(¶ms, &us, &pconst, &cosmo); + else + cosmology_init_no_cosmo(&cosmo); struct part p; struct xpart xp; -#ifdef COOLING_GRACKLE - /* set grackle_data */ - grackle_data = &cooling->chemistry; -#endif - + pyswift_part_set_to_zero(&p, &xp); + hydro_first_init_part(&p, &xp); + /* return object */ - PyArrayObject *rate = PyArray_SimpleNew(PyArray_NDIM(energy), PyArray_DIMS(energy), NPY_FLOAT); + PyArrayObject *rate = (PyArrayObject *)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 */ @@ -178,20 +158,22 @@ PyArrayObject* pycooling_rate(PyObject* self, PyObject* args) { if (fractions != NULL) pycooling_set_fractions(&xp, fractions, i); else - cooling_first_init_part(&p, &xp, cooling); + cooling_first_init_part(&pconst, &us, &cosmo, &cooling, &p, &xp); + + chemistry_first_init_part(&pconst, &us, &cosmo, &chemistry, &p, &xp); /* compute cooling rate */ - float *tmp = PyArray_GETPTR1(rate, i); #ifdef COOLING_GRACKLE - *tmp = cooling_rate(pconst, us, cooling, &p, &xp, dt); + float *tmp = PyArray_GETPTR1(rate, i); + *tmp = cooling_new_energy(&pconst, &us, &cosmo, &cooling, &p, &xp, dt); + *tmp = *tmp - hydro_get_physical_internal_energy(&p, &xp, &cosmo); + *tmp /= dt; #else - *tmp = cooling_rate(pconst, us, cooling, &p, &xp); + message("Not implemented"); + //*tmp = cooling_rate(pconst, us, cosmo, cooling, &p, &xp); #endif } - /* Acquire GIL */ - Py_END_ALLOW_THREADS; - - return rate; + return (PyObject *) rate; } diff --git a/src/cooling_wrapper.h b/src/cooling_wrapper.h index 95717e8ac5d2867b25ddcebe33548fe86ecfa6cc..a9eeeb4d6a5061637795536f76af71cc439c6747 100644 --- a/src/cooling_wrapper.h +++ b/src/cooling_wrapper.h @@ -1,11 +1,27 @@ +/******************************************************************************* + * This file is part of PYSWIFTSIM. + * Copyright (c) 2018 loic hausammann (loic.hausammann@epfl.ch) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + ******************************************************************************/ #ifndef __PYSWIFTSIM_COOLING_H__ #define __PYSWIFTSIM_COOLING_H__ #include "pyswiftsim_tools.h" -PyObject* pycooling_init(PyObject* self, PyObject* args); - -PyArrayObject* pycooling_rate(PyObject* self, PyObject* args); +PyObject* pycooling_rate(PyObject* self, PyObject* args); #endif // __PYSWIFTSIM_COOLING_H__ diff --git a/src/cosmology_wrapper.c b/src/cosmology_wrapper.c new file mode 100644 index 0000000000000000000000000000000000000000..d9789187106f40ef505d72e3d1a2456ebbb59c63 --- /dev/null +++ b/src/cosmology_wrapper.c @@ -0,0 +1,67 @@ +/******************************************************************************* + * This file is part of SWIFT. + * Copyright (c) 2017 Matthieu Schaller (matthieu.schaller@durham.ac.uk) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + ******************************************************************************/ + +#include "pyswiftsim_tools.h" +#include "cosmology_wrapper.h" + +/** + * @brief Initialize the chemistry + * + * args is expecting pyswiftsim classes in the following order: + * SwiftParams, UnitSystem and PhysConst. + * + * @param self calling object + * @param args arguments + * @return Cosmology + */ +PyObject* pycosmology_init(PyObject* self, PyObject* args) { + PyObject *pyparams; + PyObject *pyus; + PyObject *pypconst; + int with_cosmo = 0; + + /* parse arguments */ + if (!PyArg_ParseTuple(args, "OOO|i", &pyparams, &pyus, &pypconst, &with_cosmo)) + return NULL; + + struct swift_params *params = (struct swift_params*) pytools_construct(pyparams, class_swift_params); + if (params == NULL) + return NULL; + + struct unit_system *us = (struct unit_system*) pytools_construct(pyus, class_unit_system); + if (us == NULL) + return NULL; + + struct phys_const *pconst = (struct phys_const*) pytools_construct(pypconst, class_phys_const); + if (pconst == NULL) + return NULL; + + struct cosmology cosmo; + + /* init cooling */ + if (with_cosmo) + cosmology_init(params, us, pconst, &cosmo); + else + cosmology_init_no_cosmo(&cosmo); + + /* construct python object */ + PyObject *pycosmo = pytools_return(&cosmo, class_cosmology); + + return pycosmo; +} diff --git a/src/cosmology_wrapper.h b/src/cosmology_wrapper.h new file mode 100644 index 0000000000000000000000000000000000000000..8a674060e1c79f01090f441ac2ad7e8cdc1ff340 --- /dev/null +++ b/src/cosmology_wrapper.h @@ -0,0 +1,27 @@ +/******************************************************************************* + * This file is part of PYSWIFTSIM. + * Copyright (c) 2018 loic hausammann (loic.hausammann@epfl.ch) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + ******************************************************************************/ +#ifndef __PYSWIFTSIM_COSMOLOGY_H__ +#define __PYSWIFTSIM_COSMOLOGY_H__ + +#include "pyswiftsim_tools.h" + +PyObject* pycosmology_init(PyObject* self, PyObject* args); + +#endif // __PYSWIFTSIM_COSMOLOGY_H__ + diff --git a/src/parser_wrapper.c b/src/parser_wrapper.c index 3bf033f208428b2480f796ccdf415f7a09f8a2b7..9f4920fa55529604c19f02c8c0d591af9cb50bac 100644 --- a/src/parser_wrapper.c +++ b/src/parser_wrapper.c @@ -1,3 +1,21 @@ +/******************************************************************************* + * This file is part of PYSWIFTSIM. + * Copyright (c) 2018 loic hausammann (loic.hausammann@epfl.ch) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + ******************************************************************************/ #include "parser_wrapper.h" #include "pyswiftsim_tools.h" diff --git a/src/parser_wrapper.h b/src/parser_wrapper.h index 529d352a7698f9180688033ca913efd870ddd272..223e6663d1e042857d2552bc7e5fe27ee2014b0f 100644 --- a/src/parser_wrapper.h +++ b/src/parser_wrapper.h @@ -1,3 +1,21 @@ +/******************************************************************************* + * This file is part of PYSWIFTSIM. + * Copyright (c) 2018 loic hausammann (loic.hausammann@epfl.ch) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + ******************************************************************************/ #ifndef __PYSWIFTSIM_PARSER_H__ #define __PYSWIFTSIM_PARSER_H__ diff --git a/src/part_wrapper.c b/src/part_wrapper.c index 76d4512ae235c880ecd52d4c993f58f7e8ac1dbd..d8cefd848401a1e5eedb5839e5f12188e2c7738c 100644 --- a/src/part_wrapper.c +++ b/src/part_wrapper.c @@ -1,37 +1,30 @@ +/******************************************************************************* + * This file is part of PYSWIFTSIM. + * Copyright (c) 2018 loic hausammann (loic.hausammann@epfl.ch) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + ******************************************************************************/ #include "pyswiftsim_tools.h" #include <Python.h> #include <stdlib.h> #include <string.h> -PyObject* pypart_test_struct(PyObject *self, PyObject *args) -{ - - size_t N = sizeof(struct part); - - /* initialize particle */ - struct part *p = malloc(N); - p->id = 0; - for(size_t k = 0; k < DIM; k++) - { - p->x[k] = 1. + k; - p->v[k] = 4. + k; - p->a_hydro[k] = 7. + k; - } - - p->h = 10; - p->mass = 11.; - p->rho = 12.; - p->entropy = 13; - p->entropy_dt = 14; - - hydro_init_part(p, NULL); - - /* create python object */ - PyObject *object = pytools_return(p, class_part); - - free(p); - - return object; +void pyswift_part_set_to_zero(struct part *p, struct xpart *xp) { + p->v[0] = 0; + p->v[1] = 0; + p->v[2] = 0; + p->entropy = 0; } - diff --git a/src/part_wrapper.h b/src/part_wrapper.h index 5875f59da06cc9aba5ca9605a3ac4b377cc1a673..bdc3d52b5807871a4c0e656150686032917f17d8 100644 --- a/src/part_wrapper.h +++ b/src/part_wrapper.h @@ -1,17 +1,27 @@ +/******************************************************************************* + * This file is part of PYSWIFTSIM. + * Copyright (c) 2018 loic hausammann (loic.hausammann@epfl.ch) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + ******************************************************************************/ #ifndef __PYSWIFTSIM_PART_H__ #define __PYSWIFTSIM_PART_H__ #include <Python.h> +#include "pyswiftsim_tools.h" -/** - * @brief Test function for the struct - * - * args is expecting no argument. - * - * @param self calling object - * @param args arguments - * @return Part - */ -PyObject* pypart_test_struct(PyObject *self, PyObject *args); - +void pyswift_part_set_to_zero(struct part *p, struct xpart *xp); + #endif // __PYSWIFTSIM_PART_H__ diff --git a/src/pyswiftsim.h b/src/pyswiftsim.h new file mode 100644 index 0000000000000000000000000000000000000000..f215e81490bd56169a241e862d8ad6056c42cf38 --- /dev/null +++ b/src/pyswiftsim.h @@ -0,0 +1,32 @@ +/******************************************************************************* + * This file is part of PYSWIFTSIM. + * Copyright (c) 2018 loic hausammann (loic.hausammann@epfl.ch) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + ******************************************************************************/ +#ifndef __PYSWIFTSIM_H__ +#define __PYSWIFTSIM_H__ + +#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION + +#include <Python.h> +#include <numpy/arrayobject.h> + +/* Assert is already defined in Python.h */ +#undef assert +#include "swift.h" + + +#endif // __PYSWIFTSIM_H__ diff --git a/src/pyswiftsim_tools.c b/src/pyswiftsim_tools.c index b8673de8a40465ef1806f847c9381b04bbd8dcff..5b872ec5a283030da0420dbb0bf05a38b43e774d 100644 --- a/src/pyswiftsim_tools.c +++ b/src/pyswiftsim_tools.c @@ -1,3 +1,21 @@ +/******************************************************************************* + * This file is part of PYSWIFTSIM. + * Copyright (c) 2018 loic hausammann (loic.hausammann@epfl.ch) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + ******************************************************************************/ #include "pyswiftsim_tools.h" @@ -6,7 +24,9 @@ const size_t class_size[class_count] = { sizeof(struct part), sizeof(struct swift_params), sizeof(struct phys_const), - sizeof(struct cooling_function_data) + sizeof(struct cooling_function_data), + sizeof(struct chemistry_global_data), + sizeof(struct cosmology) }; char *class_name[class_count] = { @@ -14,22 +34,28 @@ char *class_name[class_count] = { "Part", "SwiftParams", "PhysConst", - "CoolingFunctionData" + "CoolingFunctionData", + "ChemistryGlobalData", + "Cosmology" }; +/** + * @brief Import a python library/function + * + * @param module Module name + * @param object_name object to import from module + * @return (PyObject) imported object + */ PyObject* pytools_import(char* module_name, char* object_name) { /* load module */ PyObject *module; module = PyImport_ImportModule(module_name); - if (module == NULL) - { - pyerror("Failed to import module '%s'.", module_name); - } - + pyerror("Failed to import module '%s'.", module_name); + /* get module dictionary */ PyObject *dict; @@ -37,21 +63,25 @@ PyObject* pytools_import(char* module_name, char* object_name) Py_DECREF(module); if (dict == NULL) - { - pyerror("Failed to get module '%s' dictionary", module_name); - } + pyerror("Failed to get module '%s' dictionary", module_name); /* get right object */ PyObject *python_obj = PyDict_GetItemString(dict, object_name); - Py_DECREF(dict); - if (python_obj == NULL) pyerror("Object %s does not exist in module %s", object_name, module_name); + Py_INCREF(python_obj); return python_obj; } +/** + * @brief Construct a python object from a C struct + * + * @param p pointer to the C struct + * @param class #swift_class of the pointer + * @return PyObject of the required class + */ PyObject* pytools_return(void *p, int class) { @@ -70,14 +100,14 @@ PyObject* pytools_return(void *p, int class) /* import python class */ python_class = pytools_import(module_name, class_pyname); - - if (python_class == NULL) + if (!python_class) return NULL; if (!PyCallable_Check(python_class)) { Py_DECREF(python_class); - pyerror("Unable to import class %s from %s", class_pyname, module_name); + message("Redo"); + pyerror("Unable to import class %30s from %.30s", class_pyname, module_name); } /* create object */ @@ -94,21 +124,26 @@ PyObject* pytools_return(void *p, int class) } +/** + * @brief get type name in C + * + * @param obj PyObject from which to get the name0 + * @return type name + */ char* pytools_get_type_name(PyObject *obj) { + /* check input */ + if (!obj) + pyerror("Requires a non null object"); + /* get object type */ - PyObject *type = PyObject_Type(obj); + PyObject *type = (PyObject *)obj->ob_type; if (type == NULL) - { - Py_DECREF(type); pyerror("Unable to get type"); - } /* get object name */ PyObject* recv = PyObject_Str(type); - Py_DECREF(type); - - if (recv == NULL) + if (!recv) { Py_DECREF(recv); pyerror("Unable to get string representation"); @@ -119,15 +154,20 @@ char* pytools_get_type_name(PyObject *obj) char *name = PyUnicode_AsUTF8AndSize(recv, &size); Py_DECREF(recv); - if (name == NULL) - { + if (!name) pyerror("Unable to convert string to char"); - } return name; } +/** + * @brief Construct a C struct from a python object + * + * @param obj pointer to the python object + * @param class #swift_class of the pointer + * @return pointer to the required struct + */ char* pytools_construct(PyObject* obj, int class) { char *module_name = "pyswiftsim.structure"; @@ -142,6 +182,8 @@ char* pytools_construct(PyObject* obj, int class) /* import class */ PyObject *pyclass = pytools_import(module_name, class_pyname); + if (!pyclass) + return NULL; /* check if classes correspond */ int test = PyObject_IsInstance(obj, pyclass); @@ -149,16 +191,15 @@ char* pytools_construct(PyObject* obj, int class) if (!test) { char *recv = pytools_get_type_name(obj); - if (recv == NULL) + if (!recv) return NULL; pyerror("Expecting class %s, received %s", class_pyname, recv); } - /* copy python class' data to C */ PyObject* data = PyObject_GetAttrString(obj, "data"); - if (data == NULL) + if (!data) pyerror("Unable to get the attribute 'data'"); char *ret = PyBytes_AsString(data); @@ -168,26 +209,35 @@ char* pytools_construct(PyObject* obj, int class) } -int pytools_check_array(PyArrayObject *obj, int dim, int type) +/** + * @brief Check if object is the expected PyArray type + * + * @param obj PyArray to check + * @param dim required dimension + * @param int required type + * @param name Name to print for errors + * @return #error_code result of the test + */ +int pytools_check_array(PyArrayObject *obj, int dim, int type, const char* name) { IMPORT_ARRAY1(1); /* check if array */ if (!PyArray_Check(obj)) { - pyerror("Expecting a numpy array"); + pyerror("Expecting a numpy array for %s", name); } /* check if required dim */ if (PyArray_NDIM(obj) != dim) { - pyerror("Array should be a %i dimensional object", dim); + pyerror("Array should be a %i dimensional object for %s", dim, name); } /* check data type */ if (PyArray_TYPE(obj) != type) { - pyerror("Wrong array type"); + pyerror("Wrong array type for %s", name); } return SUCCESS; diff --git a/src/pyswiftsim_tools.h b/src/pyswiftsim_tools.h index 65cb3df581181723e2df87a3d5ff42f79a27059d..3cc461c5019251511dfc91d04b73da64d3b49d5b 100644 --- a/src/pyswiftsim_tools.h +++ b/src/pyswiftsim_tools.h @@ -1,22 +1,33 @@ +/******************************************************************************* + * This file is part of PYSWIFTSIM. + * Copyright (c) 2018 loic hausammann (loic.hausammann@epfl.ch) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + ******************************************************************************/ #ifndef __PYSWIFTSIM_TOOLS_H__ #define __PYSWIFTSIM_TOOLS_H__ -#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION - -#include <Python.h> -#include <numpy/arrayobject.h> - -#undef assert -#include <swift.h> +#include "pyswiftsim.h" #define DIM 3 #define STRING_SIZE 200 -/* Set the error message for python (still need to return NULL) */ +/* Set the error message for python */ #define pyerror(s, ...) \ ({ \ char error_msg[STRING_SIZE]; \ - PyErr_Print(); \ sprintf(error_msg, "\n%s:%s():%i: " s, __FILE__, \ __FUNCTION__, __LINE__, ##__VA_ARGS__); \ PyErr_SetString(PyExc_RuntimeError, error_msg); \ @@ -26,7 +37,8 @@ /* debugging function */ #define pydebug(s, ...) \ ({ \ - PyErr_Print(); \ + if (!PyErr_Occurred()) \ + PyErr_Print(); \ fprintf(stderr, "\n%s:%s():%i: Test " s "\n", __FILE__, \ __FUNCTION__, __LINE__, ##__VA_ARGS__); \ }) @@ -49,6 +61,8 @@ enum swift_class { class_swift_params, class_phys_const, class_cooling_function_data, + class_chemistry_global_data, + class_cosmology, class_count /* should always be last! */ }; @@ -64,49 +78,14 @@ enum error_code { }; -/** - * @brief Construct a python object from a C struct - * - * @param p pointer to the C struct - * @param class #swift_class of the pointer - * @return PyObject of the required class - */ PyObject* pytools_return(void* p, int class); -/** - * @brief Construct a C struct from a python object - * - * @param obj pointer to the python object - * @param class #swift_class of the pointer - * @return pointer to the required struct - */ char* pytools_construct(PyObject* obj, int class); -/** - * @brief Import a python library/function - * - * @param module Module name - * @param object_name object to import from module - * @return (PyObject) imported object - */ PyObject* pytools_import(char* module, char* object_name); -/** - * @brief get type name in C - * - * @param obj PyObject from which to get the name0 - * @return type name - */ char* pytools_get_type_name(PyObject *obj); -/** - * @brief Check if object is the expected PyArray type - * - * @param obj PyArray to check - * @param dim required dimension - * @param int required type - * @return #error_code result of the test - */ -int pytools_check_array(PyArrayObject *obj, int dim, int type); +int pytools_check_array(PyArrayObject *obj, int dim, int type, const char* name); #endif // __PYSWIFTSIM_TOOLS_H__ diff --git a/src/units_wrapper.c b/src/units_wrapper.c index fe3a23a0cac0ed011cbaf9417d77c0d933e4721c..5fc066f1e28e155e9cf268a50b564ab4ae8d9a42 100644 --- a/src/units_wrapper.c +++ b/src/units_wrapper.c @@ -1,3 +1,21 @@ +/******************************************************************************* + * This file is part of PYSWIFTSIM. + * Copyright (c) 2018 loic hausammann (loic.hausammann@epfl.ch) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + ******************************************************************************/ #include "pyswiftsim_tools.h" #include <Python.h> @@ -20,8 +38,6 @@ PyObject* pyunit_system_test_struct(PyObject *self, PyObject *args) /* construct python object */ PyObject *object = pytools_return(us, class_unit_system); free(us); - if (object == NULL) - return NULL; return object; } @@ -29,9 +45,10 @@ PyObject* pyunit_system_test_struct(PyObject *self, PyObject *args) PyObject* pyunit_system_init(PyObject *self, PyObject *args) { PyObject* parser; + char* section = "InternalUnitSystem"; /* parse arguement */ - if (!PyArg_ParseTuple(args, "O", &parser)) + if (!PyArg_ParseTuple(args, "O|s", &parser, §ion)) return NULL; struct swift_params *params = (struct swift_params*) pytools_construct(parser, class_swift_params); @@ -41,11 +58,12 @@ PyObject* pyunit_system_init(PyObject *self, PyObject *args) /* initialize units */ struct unit_system us; - units_init(&us, params, "InternalUnitSystem"); + units_init_from_params(&us, params, section); /* initialize phys_const */ struct phys_const pconst; - phys_const_init(&us, &pconst); + + phys_const_init(&us, params, &pconst); /* create python object to return */ PyObject *pyus = pytools_return(&us, class_unit_system); @@ -58,5 +76,3 @@ PyObject* pyunit_system_init(PyObject *self, PyObject *args) return PyTuple_Pack(2, pyus, pypconst); } - - diff --git a/src/units_wrapper.h b/src/units_wrapper.h index 867e055863d24203dbfb41213ef6fd837252a28e..fa42a09dda6961ba1065dbd65bc785c3cacc04ea 100644 --- a/src/units_wrapper.h +++ b/src/units_wrapper.h @@ -1,3 +1,21 @@ +/******************************************************************************* + * This file is part of PYSWIFTSIM. + * Copyright (c) 2018 loic hausammann (loic.hausammann@epfl.ch) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + ******************************************************************************/ #ifndef __PYSWIFTSIM_UNITS_H__ #define __PYSWIFTSIM_UNITS_H__ diff --git a/src/wrapper.c b/src/wrapper.c index 46076c5cb627eaed51654bb02107fcaeefcbbfb6..65dbad5592af49b1ca4900b3c99ad357edd56031 100644 --- a/src/wrapper.c +++ b/src/wrapper.c @@ -1,9 +1,28 @@ +/******************************************************************************* + * This file is part of PYSWIFTSIM. + * Copyright (c) 2018 loic hausammann (loic.hausammann@epfl.ch) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + ******************************************************************************/ #include "units_wrapper.h" #include "part_wrapper.h" #include "parser_wrapper.h" #include "cooling_wrapper.h" +#include "cosmology_wrapper.h" +#include "chemistry_wrapper.h" #include "pyswiftsim_tools.h" -#include "config_wrapper.h" #include <Python.h> #include <math.h> @@ -14,20 +33,17 @@ static PyMethodDef wrapper_methods[] = { - {"partTestStruct", pypart_test_struct, METH_VARARGS, - "Construct a part object and return it."}, - - {"unitSystemTestStruct", pyunit_system_test_struct, METH_VARARGS, - "Construct a unit_system object and return it."}, - {"parserReadFile", pyparser_read_file, METH_VARARGS, "Read a swift params file."}, {"unitSystemInit", pyunit_system_init, METH_VARARGS, "Construct a unit_system object and return it."}, - {"coolingInit", pycooling_init, METH_VARARGS, - "Initialize cooling."}, + {"chemistryInit", pychemistry_init, METH_VARARGS, + "Initialize chemistry."}, + + {"cosmologyInit", pycosmology_init, METH_VARARGS, + "Initialize cosmology."}, {"coolingRate", pycooling_rate, METH_VARARGS, "Compute the cooling rate.\n\n" @@ -44,11 +60,13 @@ static PyMethodDef wrapper_methods[] = { "\t Time step in pyus units\n" "fractions: np.array, optional\n" "\t Fraction of each cooling element (including metals)\n" + "Returns\n" + "-------\n\n" + "rate: np.array\n" + "\t Cooling rate\n" }, - {"configGetCooling", config_get_cooling, METH_VARARGS, - "Get the cooling type."}, - + {NULL, NULL, 0, NULL} /* Sentinel */ }; @@ -59,11 +77,15 @@ static struct PyModuleDef wrapper_cmodule = { "wrapper", "Wrapper around the SPH cosmological simulation code SWIFT", -1, - wrapper_methods + wrapper_methods, + NULL, /* m_slots */ + NULL, /* m_traverse */ + NULL, /* m_clear */ + NULL, /* m_free */ }; -PyMODINIT_FUNC PyInit_wrapper(void) +PyMODINIT_FUNC PyInit_libpyswiftsim(void) { PyObject *m; @@ -74,8 +96,5 @@ PyMODINIT_FUNC PyInit_wrapper(void) Py_Initialize(); m = PyModule_Create(&wrapper_cmodule); - if (m == NULL) - return NULL; - return m; } diff --git a/test/test_struct.py b/test/test_struct.py index 7c228d849979d2229cfd9d741862f54535f63744..2d9df52e88b5a247619ce1df6065bf7c72b6076f 100644 --- a/test/test_struct.py +++ b/test/test_struct.py @@ -1,46 +1,29 @@ #!/usr/bin/env python3 +""" +This file is part of PYSWIFT. +Copyright (c) 2018 Loic Hausammann (loic.hausammann@epfl.ch) -from pyswiftsim import wrapper -from pyswiftsim import structure - -us = wrapper.unitSystemTestStruct() - -print(us) - -part = wrapper.partTestStruct() - -print(part) - -#us = structure.Units(t) - -#print(type(us), us.struct_name) -#print(us.struct_size_format) +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published +by the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. -#for i in us.struct_name: -# print(i, getattr(us, i)) +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. +You should have received a copy of the GNU Lesser General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. """ -print(us.pos) -us.pos = [12., 16., 11.] -#us.pos[0] = 10. - -print(us) -print(us.pos) -print("setitem") -us.pos[2] = 20. +from pyswiftsim import wrapper -print(us.pos) -print(us) +filename = "parameter_example.yml" +params = wrapper.parserReadFile(filename) -d = {} -d["UnitMass_in_cgs"] = 1. -d["UnitLength_in_cgs"] = 2. -d["UnitTime_in_cgs"] = 3. -d["UnitCurrent_in_cgs"] = 4. -d["UnitTemperature_in_cgs"] = 5. +print(params) -us = structure.UnitSystem(d) +us = wrapper.unitSystemInit(params) print(us) -"""