diff --git a/configure.ac b/configure.ac index 28a74d547225ff010eb29cd43182d57bac699e82..338edec60f956c37f666f7592a931b2c20a9f6e8 100644 --- a/configure.ac +++ b/configure.ac @@ -1390,24 +1390,21 @@ AM_CONDITIONAL([HAVESTANDALONEFOF],[test $enable_standalone_fof = "yes"]) # Gravity scheme. AC_ARG_WITH([gravity], [AS_HELP_STRING([--with-gravity=<scheme>], - [Gravity scheme to use @<:@default, with-potential, default: default@:>@] + [Gravity scheme to use @<:@basic, with-potential, with-multi-softening default: with-multi-softening@:>@] )], [with_gravity="$withval"], - [with_gravity="default"] + [with_gravity="with-multi-softening"] ) -if test "$with_subgrid" = "EAGLE"; then - if test "$with_gravity" = "default"; then - with_gravity="with-potential" - fi -fi - case "$with_gravity" in with-potential) - AC_DEFINE([POTENTIAL_GRAVITY], [1], [Gravity scheme with potential calculation]) + AC_DEFINE([POTENTIAL_GRAVITY], [1], [Basic gravity scheme with potential calculation]) ;; - default) - AC_DEFINE([DEFAULT_GRAVITY], [1], [Default gravity scheme]) + with-multi-softening) + AC_DEFINE([MULTI_SOFTENING_GRAVITY], [1], [Gravity scheme with per-particle type softening value and background particles]) + ;; + basic) + AC_DEFINE([DEFAULT_GRAVITY], [1], [Basic gravity scheme]) ;; *) AC_MSG_ERROR([Unknown gravity scheme: $with_gravity]) @@ -1982,13 +1979,6 @@ AC_DEFINE_UNQUOTED([SELF_GRAVITY_MULTIPOLE_ORDER], [$with_multipole_order], [Mul AC_PATH_PROG([GIT_CMD], [git]) AC_SUBST([GIT_CMD]) -# Check that the gravity model is compatible with the subgrid -if test $with_black_holes = "EAGLE"; then - if test $with_gravity != "with-potential"; then - AC_MSG_ERROR([The EAGLE BH model needs the gravity scheme to provide potentials. The code must be compile with --with-gravity=with-potential.]) - fi -fi - # 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" != ""]) diff --git a/doc/RTD/source/InitialConditions/index.rst b/doc/RTD/source/InitialConditions/index.rst index e585c9aa55f269ebbbf9b2d83034b96a688a99f4..4532fdde8818088cf89cee5fac7cacfbee2dd67b 100644 --- a/doc/RTD/source/InitialConditions/index.rst +++ b/doc/RTD/source/InitialConditions/index.rst @@ -44,27 +44,29 @@ There are several groups that contain 'auxiliary' information, such as the particles. Some types are currently ignored by SWIFT but are kept in the file format for compatibility reasons. -+---------------------+------------------------+----------------------------+ -| HDF5 Group Name | Physical Particle Type | In code ``enum part_type`` | -+=====================+========================+============================+ -| ``/PartType0/`` | Gas | ``swift_type_gas`` | -+---------------------+------------------------+----------------------------+ -| ``/PartType1/`` | Dark Matter | ``swift_type_dark_matter`` | -+---------------------+------------------------+----------------------------+ -| ``/PartType2/`` | Ignored | | -+---------------------+------------------------+----------------------------+ -| ``/PartType3/`` | Ignored | | -+---------------------+------------------------+----------------------------+ -| ``/PartType4/`` | Stars | ``swift_type_star`` | -+---------------------+------------------------+----------------------------+ -| ``/PartType5/`` | Black Holes | ``swift_type_black_hole`` | -+---------------------+------------------------+----------------------------+ ++---------------------+------------------------+----------------------------------------+ +| HDF5 Group Name | Physical Particle Type | In code ``enum part_type`` | ++=====================+========================+========================================+ +| ``/PartType0/`` | Gas | ``swift_type_gas`` | ++---------------------+------------------------+----------------------------------------+ +| ``/PartType1/`` | Dark Matter | ``swift_type_dark_matter`` | ++---------------------+------------------------+----------------------------------------+ +| ``/PartType2/`` | Background Dark Matter | ``swift_type_dark_matter_background`` | ++---------------------+------------------------+----------------------------------------+ +| ``/PartType3/`` | Ignored | | ++---------------------+------------------------+----------------------------------------+ +| ``/PartType4/`` | Stars | ``swift_type_star`` | ++---------------------+------------------------+----------------------------------------+ +| ``/PartType5/`` | Black Holes | ``swift_type_black_hole`` | ++---------------------+------------------------+----------------------------------------+ The last column in the table gives the ``enum`` value from ``part_type.h`` corresponding to a given entry in the files. -Note that the only particles that have hydrodynamical forces calculated between -them are those in ``PartType0``. +Note that the only particles that have hydrodynamical forces calculated +between them are those in ``PartType0``. The background dark matter +particles are used for zoom-in simulations and can have different masses +(and as a consequence softening length) within the ``/PartType2`` arrays. Necessary Components @@ -137,8 +139,8 @@ individual particle type (e.g. ``/PartType0/``) that have the following *dataset within [0, L)^3 where L is the side-length of the simulation volume. In the case of cosmological simulations, these are the co-moving positions. + ``Velocities``, an array of shape (N, 3) that is the cartesian velocities of - the particles. When running cosmological simulations, these are the peculiar - velocities. Note that this is different from GADGET which uses peculiar + the particles. When running cosmological simulations, these are the **peculiar + velocities**. Note that this is different from GADGET which uses peculiar velocities divided by ``sqrt(a)`` (see below for a fix). + ``ParticleIDs``, an array of length N that are unique identifying numbers for each particle. Note that these have to be unique to a particle, and cannot be diff --git a/doc/RTD/source/ParameterFiles/parameter_description.rst b/doc/RTD/source/ParameterFiles/parameter_description.rst index b90c2c26b8fe01ad306106fd3fd2f65612002d8f..16938a0fa14d5cfa9b8bb14fa9d784eb0ed08c82 100644 --- a/doc/RTD/source/ParameterFiles/parameter_description.rst +++ b/doc/RTD/source/ParameterFiles/parameter_description.rst @@ -174,7 +174,7 @@ use the following parameters: h: 0.6777 Omega_m: 0.307 Omega_lambda: 0.693 - Omega_b: 0.0455 + Omega_b: 0.0482519 Omega_r: 0. # (Optional) w_0: -1.0 # (Optional) w_a: 0. # (Optional) @@ -191,12 +191,32 @@ The behaviour of the self-gravity solver can be modified by the parameters provided in the ``Gravity`` section. The theory document puts these parameters into the context of the equations being solved. We give a brief overview here. -* The Plummer-equivalent co-moving softening length used for all particles :math:`\epsilon_{com}`: ``comoving_softening``, -* The Plummer-equivalent maximal physical softening length used for all particles :math:`\epsilon_{max}`: ``comoving_softening``, - -At any redshift :math:`z`, the Plummer-equivalent softening length used by the -code will be :math:`\epsilon=\min(\epsilon_{max}, -\frac{\epsilon_{com}}{z+1})`. This is expressed in internal units. +* The Plummer-equivalent co-moving softening length used for all dark matter particles :math:`\epsilon_{\rm com,DM}`: ``comoving_DM_softening``, +* The Plummer-equivalent co-moving softening length used for all baryon particles (gas, stars, BHs) :math:`\epsilon_{\rm com,bar}`: ``comoving_baryon_softening``, +* The Plummer-equivalent maximal physical softening length used for all dark matter particles :math:`\epsilon_{\rm max,DM}`: ``max_physical_DM_softening``, +* The Plummer-equivalent maximal physical softening length used for all baryon particles (gas, stars, BHs) :math:`\epsilon_{\rm max,bar}`: ``max_physical_baryon_softening``, + +At any redshift :math:`z`, the Plummer-equivalent softening length used by +the code will be :math:`\epsilon=\min(\epsilon_{max}, +\frac{\epsilon_{com}}{z+1})`. The same calculation is performed +independently for the dark matter and baryon particles. All the softening +quantities are expressed in internal units. Calculations that only involve +DM or baryons can leave the unused quantities out of the parameter +file. For non-cosmological runs, only the physical softening lengths need +to be supplied. + +In case of zoom simulations, the softening of the additional, more massive, background +particles is specified via the parameter +``softening_ratio_background``. Since these particles will typically have +different masses to degrade the resolution away from the zoom region, the +particles won't have a single softening value. Instead, we specify the +fraction of the mean inter-particle separation to use. The code will then +derive the softening length of each particle assuming the mean density of +the Universe. That is :math:`\epsilon_{\rm background} = +f\sqrt[3]{\frac{m}{\Omega_m\rho_{\rm crit}}}`, where :math:`f` is the +user-defined value (typically of order 0.05). + +The accuracy of the gravity calculation is governed by the following two parameters: * The opening angle (multipole acceptance criterion) used in the FMM :math:`\theta`: ``theta``, * The time-step size pre-factor :math:`\eta`: ``eta``, @@ -236,15 +256,17 @@ simulation: # Parameters for the self-gravity scheme for the EAGLE-100 box Gravity: - eta: 0.025 - theta: 0.7 - comoving_softening: 0.0026994 # 0.7 proper kpc at z=2.8. - max_physical_softening: 0.0007 # 0.7 proper kpc - rebuild_frequency: 0.01 # Default optional value + eta: 0.025 + theta: 0.7 mesh_side_length: 512 - a_smooth: 1.25 # Default optional value - r_cut_max: 4.5 # Default optional value - r_cut_min: 0.1 # Default optional value + comoving_DM_softening: 0.0026994 # 0.7 proper kpc at z=2.8. + max_physical_DM_softening: 0.0007 # 0.7 proper kpc + comoving_baryon_softening: 0.0026994 # 0.7 proper kpc at z=2.8. + max_physical_baryon_softening: 0.0007 # 0.7 proper kpc + rebuild_frequency: 0.01 # Default optional value + a_smooth: 1.25 # Default optional value + r_cut_max: 4.5 # Default optional value + r_cut_min: 0.1 # Default optional value .. _Parameters_SPH: diff --git a/doc/RTD/source/Snapshots/index.rst b/doc/RTD/source/Snapshots/index.rst index 32317aa19b8a216659317d4ae457a2dbfd040571..fa11058edfa202b548936dac3ca55ada86eb9e84 100644 --- a/doc/RTD/source/Snapshots/index.rst +++ b/doc/RTD/source/Snapshots/index.rst @@ -107,17 +107,19 @@ There are several groups that contain 'auxiliary' information, such as the particles. The type use the naming convention of Gadget-2 (with the OWLS and EAGLE extensions). -+---------------------+------------------------+----------------------------+ -| HDF5 Group Name | Physical Particle Type | In code ``enum part_type`` | -+=====================+========================+============================+ -| ``/PartType0/`` | Gas | ``swift_type_gas`` | -+---------------------+------------------------+----------------------------+ -| ``/PartType1/`` | Dark Matter | ``swift_type_dark_matter`` | -+---------------------+------------------------+----------------------------+ -| ``/PartType4/`` | Stars | ``swift_type_star`` | -+---------------------+------------------------+----------------------------+ -| ``/PartType5/`` | Black Holes | ``swift_type_black_hole`` | -+---------------------+------------------------+----------------------------+ ++---------------------+------------------------+----------------------------------------+ +| HDF5 Group Name | Physical Particle Type | In code ``enum part_type`` | ++=====================+========================+========================================+ +| ``/PartType0/`` | Gas | ``swift_type_gas`` | ++---------------------+------------------------+----------------------------------------+ +| ``/PartType1/`` | Dark Matter | ``swift_type_dark_matter`` | ++---------------------+------------------------+----------------------------------------+ +| ``/PartType2/`` | Background Dark Matter | ``swift_type_dark_matter_background`` | ++---------------------+------------------------+----------------------------------------+ +| ``/PartType4/`` | Stars | ``swift_type_star`` | ++---------------------+------------------------+----------------------------------------+ +| ``/PartType5/`` | Black Holes | ``swift_type_black_hole`` | ++---------------------+------------------------+----------------------------------------+ The last column in the table gives the ``enum`` value from ``part_type.h`` corresponding to a given entry in the files. diff --git a/examples/Cosmology/ConstantCosmoVolume/constant_volume.yml b/examples/Cosmology/ConstantCosmoVolume/constant_volume.yml index ebfcc4ffd72121571fa1a69f900985917b440c65..a6ff72555ef68964508493856127d4cc739b7722 100644 --- a/examples/Cosmology/ConstantCosmoVolume/constant_volume.yml +++ b/examples/Cosmology/ConstantCosmoVolume/constant_volume.yml @@ -49,6 +49,8 @@ Gravity: mesh_side_length: 32 eta: 0.025 theta: 0.3 - comoving_softening: 0.08 # 80 kpc = 1/25 of mean inter-particle separation - max_physical_softening: 0.08 # 80 kpc = 1/25 of mean inter-particle separation + comoving_DM_softening: 0.08 # 80 kpc = 1/25 of mean inter-particle separation + max_physical_DM_softening: 0.08 # 80 kpc = 1/25 of mean inter-particle separation + comoving_baryon_softening: 0.08 # 80 kpc = 1/25 of mean inter-particle separation + max_physical_baryon_softening: 0.08 # 80 kpc = 1/25 of mean inter-particle separation diff --git a/examples/Cosmology/ZeldovichPancake_3D/zeldovichPancake.yml b/examples/Cosmology/ZeldovichPancake_3D/zeldovichPancake.yml index 6a7c5166635b7fa0ed5f69c41461d867c3b254ad..d43c78972b0bc8d1f250b95190dafef305abca3f 100644 --- a/examples/Cosmology/ZeldovichPancake_3D/zeldovichPancake.yml +++ b/examples/Cosmology/ZeldovichPancake_3D/zeldovichPancake.yml @@ -51,5 +51,7 @@ Gravity: eta: 0.025 theta: 0.3 r_cut_max: 5. - comoving_softening: 0.001 - max_physical_softening: 0.001 + comoving_DM_softening: 0.001 + max_physical_DM_softening: 0.001 + comoving_baryon_softening: 0.001 + max_physical_baryon_softening: 0.001 diff --git a/examples/EAGLE_DMO_low_z/EAGLE_DMO_100/eagle_100.yml b/examples/EAGLE_DMO_low_z/EAGLE_DMO_100/eagle_100.yml index 5a3066195647b79eeb6a6d67d037d15ce8370c39..5d449cfceb589e7580ba5f52375d115678f51321 100644 --- a/examples/EAGLE_DMO_low_z/EAGLE_DMO_100/eagle_100.yml +++ b/examples/EAGLE_DMO_low_z/EAGLE_DMO_100/eagle_100.yml @@ -23,7 +23,7 @@ TimeIntegration: dt_max: 1e-3 # The maximal time-step size of the simulation (in internal units). Scheduler: - max_top_level_cells: 80 + max_top_level_cells: 64 # Parameters governing the snapshots Snapshots: @@ -43,8 +43,9 @@ Statistics: Gravity: eta: 0.025 # Constant dimensionless multiplier for time integration. theta: 0.85 # Opening angle (Multipole acceptance criterion) - comoving_softening: 0.0026994 # Comoving softening length (in internal units). - max_physical_softening: 0.0007 # Physical softening length (in internal units). + mesh_side_length: 512 + comoving_DM_softening: 0.0026994 # Comoving DM softening length (in internal units). + max_physical_DM_softening: 0.0007 # Max physical DM softening length (in internal units). # Parameters related to the initial conditions InitialConditions: diff --git a/examples/EAGLE_DMO_low_z/EAGLE_DMO_12/eagle_12.yml b/examples/EAGLE_DMO_low_z/EAGLE_DMO_12/eagle_12.yml index 0660d98e87adfae62a2d795efec7ad6509cc1354..f232bb7e930a4977b65686424d04a7eed254761d 100644 --- a/examples/EAGLE_DMO_low_z/EAGLE_DMO_12/eagle_12.yml +++ b/examples/EAGLE_DMO_low_z/EAGLE_DMO_12/eagle_12.yml @@ -41,12 +41,11 @@ Statistics: # Parameters for the self-gravity scheme Gravity: - mesh_side_length: 32 eta: 0.025 # Constant dimensionless multiplier for time integration. theta: 0.7 # Opening angle (Multipole acceptance criterion) - comoving_softening: 0.0026994 # Comoving softening length (in internal units). - max_physical_softening: 0.0007 # Physical softening length (in internal units). mesh_side_length: 32 + comoving_DM_softening: 0.0026994 # Comoving DM softening length (in internal units). + max_physical_DM_softening: 0.0007 # Max physical DM softening length (in internal units). # Parameters related to the initial conditions InitialConditions: diff --git a/examples/EAGLE_DMO_low_z/EAGLE_DMO_25/eagle_25.yml b/examples/EAGLE_DMO_low_z/EAGLE_DMO_25/eagle_25.yml index 558c68ffaad204ebbe1d5781f945f0d95108d227..20f4c1eef17fafd8a87d1d251147438fc201a355 100644 --- a/examples/EAGLE_DMO_low_z/EAGLE_DMO_25/eagle_25.yml +++ b/examples/EAGLE_DMO_low_z/EAGLE_DMO_25/eagle_25.yml @@ -43,9 +43,9 @@ Statistics: Gravity: eta: 0.025 # Constant dimensionless multiplier for time integration. theta: 0.7 # Opening angle (Multipole acceptance criterion) - comoving_softening: 0.0026994 # Comoving softening length (in internal units). - max_physical_softening: 0.0007 # Physical softening length (in internal units). - mesh_side_length: 32 + mesh_side_length: 64 + comoving_DM_softening: 0.0026994 # Comoving DM softening length (in internal units). + max_physical_DM_softening: 0.0007 # Max physical DM softening length (in internal units). # Parameters related to the initial conditions InitialConditions: diff --git a/examples/EAGLE_DMO_low_z/EAGLE_DMO_50/eagle_50.yml b/examples/EAGLE_DMO_low_z/EAGLE_DMO_50/eagle_50.yml index 3cab2b1dc869b5187cf647caa7893281b783591a..0ccf061c2e942126bbc0c2c69998bbca6a9b824f 100644 --- a/examples/EAGLE_DMO_low_z/EAGLE_DMO_50/eagle_50.yml +++ b/examples/EAGLE_DMO_low_z/EAGLE_DMO_50/eagle_50.yml @@ -23,7 +23,7 @@ TimeIntegration: dt_max: 1e-3 # The maximal time-step size of the simulation (in internal units). Scheduler: - max_top_level_cells: 20 + max_top_level_cells: 32 # Parameters governing the snapshots Snapshots: @@ -42,9 +42,9 @@ Statistics: Gravity: eta: 0.025 # Constant dimensionless multiplier for time integration. theta: 0.7 # Opening angle (Multipole acceptance criterion) - comoving_softening: 0.0026994 # Comoving softening length (in internal units). - max_physical_softening: 0.0007 # Physical softening length (in internal units). - mesh_side_length: 64 + mesh_side_length: 128 + comoving_DM_softening: 0.0026994 # Comoving DM softening length (in internal units). + max_physical_DM_softening: 0.0007 # Max physical DM softening length (in internal units). # Parameters related to the initial conditions InitialConditions: diff --git a/examples/EAGLE_ICs/EAGLE_12/eagle_12.yml b/examples/EAGLE_ICs/EAGLE_12/eagle_12.yml index e94dce66f80b9b7c669e9095b7ce6f76aaf84551..93c8c740f58efb23a017a7d229f81a685e837b1a 100644 --- a/examples/EAGLE_ICs/EAGLE_12/eagle_12.yml +++ b/examples/EAGLE_ICs/EAGLE_12/eagle_12.yml @@ -39,9 +39,11 @@ Statistics: Gravity: eta: 0.025 # Constant dimensionless multiplier for time integration. theta: 0.7 # Opening angle (Multipole acceptance criterion) - comoving_softening: 0.0026994 # Comoving softening length (in internal units). - max_physical_softening: 0.0007 # Physical softening length (in internal units). mesh_side_length: 64 + comoving_DM_softening: 0.0026994 # Comoving DM softening length (in internal units). + max_physical_DM_softening: 0.0007 # Max physical DM softening length (in internal units). + comoving_baryon_softening: 0.0026994 # Comoving DM softening length (in internal units). + max_physical_baryon_softening: 0.0007 # Max physical DM softening length (in internal units). # Parameters for the hydrodynamics scheme SPH: diff --git a/examples/EAGLE_ICs/EAGLE_25/eagle_25.yml b/examples/EAGLE_ICs/EAGLE_25/eagle_25.yml index 4e6f7f6c49040fb2f39f443c7c1c7235570566f3..d5307533c0ffccae7644f06dbe33c27bf46f4114 100644 --- a/examples/EAGLE_ICs/EAGLE_25/eagle_25.yml +++ b/examples/EAGLE_ICs/EAGLE_25/eagle_25.yml @@ -39,9 +39,11 @@ Statistics: Gravity: eta: 0.025 # Constant dimensionless multiplier for time integration. theta: 0.7 # Opening angle (Multipole acceptance criterion) - comoving_softening: 0.0026994 # Comoving softening length (in internal units). - max_physical_softening: 0.0007 # Physical softening length (in internal units). mesh_side_length: 128 + comoving_DM_softening: 0.0026994 # Comoving DM softening length (in internal units). + max_physical_DM_softening: 0.0007 # Max physical DM softening length (in internal units). + comoving_baryon_softening: 0.0026994 # Comoving DM softening length (in internal units). + max_physical_baryon_softening: 0.0007 # Max physical DM softening length (in internal units). # Parameters for the hydrodynamics scheme SPH: diff --git a/examples/EAGLE_ICs/EAGLE_50/eagle_50.yml b/examples/EAGLE_ICs/EAGLE_50/eagle_50.yml index 9317e9603b106141e9c7a82b9cd2fc36f63698a8..f757dc9dcf104237c6ecc5e472d29f79375a1d53 100644 --- a/examples/EAGLE_ICs/EAGLE_50/eagle_50.yml +++ b/examples/EAGLE_ICs/EAGLE_50/eagle_50.yml @@ -39,9 +39,11 @@ Statistics: Gravity: eta: 0.025 # Constant dimensionless multiplier for time integration. theta: 0.7 # Opening angle (Multipole acceptance criterion) - comoving_softening: 0.0026994 # Comoving softening length (in internal units). - max_physical_softening: 0.0007 # Physical softening length (in internal units). mesh_side_length: 256 + comoving_DM_softening: 0.0026994 # Comoving DM softening length (in internal units). + max_physical_DM_softening: 0.0007 # Max physical DM softening length (in internal units). + comoving_baryon_softening: 0.0026994 # Comoving DM softening length (in internal units). + max_physical_baryon_softening: 0.0007 # Max physical DM softening length (in internal units). # Parameters for the hydrodynamics scheme SPH: diff --git a/examples/EAGLE_low_z/EAGLE_100/eagle_100.yml b/examples/EAGLE_low_z/EAGLE_100/eagle_100.yml index 746362eb7d573eed75018423b8e33f6835916ccd..f77036b5d55f33b4fd3f42c7bea0ccc124003a40 100644 --- a/examples/EAGLE_low_z/EAGLE_100/eagle_100.yml +++ b/examples/EAGLE_low_z/EAGLE_100/eagle_100.yml @@ -1,3 +1,6 @@ +MetaData: + run_name: EAGLE-L0100N1504-Ref + # Define the system of units to use internally. InternalUnitSystem: UnitMass_in_cgs: 1.98848e43 # 10^10 M_sun in grams @@ -42,9 +45,11 @@ Statistics: Gravity: eta: 0.025 # Constant dimensionless multiplier for time integration. theta: 0.85 # Opening angle (Multipole acceptance criterion) - comoving_softening: 0.0026994 # Comoving softening length (in internal units). - max_physical_softening: 0.0007 # Physical softening length (in internal units). mesh_side_length: 256 + comoving_DM_softening: 0.0026994 # Comoving DM softening length (in internal units). + max_physical_DM_softening: 0.0007 # Max physical DM softening length (in internal units). + comoving_baryon_softening: 0.0026994 # Comoving DM softening length (in internal units). + max_physical_baryon_softening: 0.0007 # Max physical DM softening length (in internal units). # Parameters for the hydrodynamics scheme SPH: diff --git a/examples/EAGLE_low_z/EAGLE_12/eagle_12.yml b/examples/EAGLE_low_z/EAGLE_12/eagle_12.yml index da6dfc0d094e45146e8bed3e536ca7a0874093fb..f470c691a5a76207998f6d854f6e8d44f0a1aebb 100644 --- a/examples/EAGLE_low_z/EAGLE_12/eagle_12.yml +++ b/examples/EAGLE_low_z/EAGLE_12/eagle_12.yml @@ -1,3 +1,6 @@ +MetaData: + run_name: EAGLE-L0012N0188-Ref + # Define the system of units to use internally. InternalUnitSystem: UnitMass_in_cgs: 1.98848e43 # 10^10 M_sun in grams @@ -43,9 +46,11 @@ Statistics: Gravity: eta: 0.025 # Constant dimensionless multiplier for time integration. theta: 0.7 # Opening angle (Multipole acceptance criterion) - comoving_softening: 0.0026994 # Comoving softening length (in internal units). - max_physical_softening: 0.0007 # Physical softening length (in internal units). mesh_side_length: 32 + comoving_DM_softening: 0.0026994 # Comoving DM softening length (in internal units). + max_physical_DM_softening: 0.0007 # Max physical DM softening length (in internal units). + comoving_baryon_softening: 0.0026994 # Comoving DM softening length (in internal units). + max_physical_baryon_softening: 0.0007 # Max physical DM softening length (in internal units). # Parameters for the hydrodynamics scheme SPH: diff --git a/examples/EAGLE_low_z/EAGLE_25/eagle_25.yml b/examples/EAGLE_low_z/EAGLE_25/eagle_25.yml index 1c2f62ef75209d8e6b3ed787b97d458e6b567dc6..07685bf783b34b2872df4a32610fa791db01cded 100644 --- a/examples/EAGLE_low_z/EAGLE_25/eagle_25.yml +++ b/examples/EAGLE_low_z/EAGLE_25/eagle_25.yml @@ -1,3 +1,6 @@ +MetaData: + run_name: EAGLE-L0025N0376-Ref + # Define the system of units to use internally. InternalUnitSystem: UnitMass_in_cgs: 1.98848e43 # 10^10 M_sun in grams @@ -49,10 +52,13 @@ Statistics: # Parameters for the self-gravity scheme Gravity: eta: 0.025 # Constant dimensionless multiplier for time integration. - theta: 0.7 # Opening angle (Multipole acceptance criterion) - comoving_softening: 0.0026994 # Comoving softening length (in internal units). - max_physical_softening: 0.0007 # Physical softening length (in internal units). + theta: 0.7 # Opening angle (Multipole acceptance criterion) mesh_side_length: 64 + comoving_DM_softening: 0.0026994 # Comoving DM softening length (in internal units). + max_physical_DM_softening: 0.0007 # Max physical DM softening length (in internal units). + comoving_baryon_softening: 0.0026994 # Comoving DM softening length (in internal units). + max_physical_baryon_softening: 0.0007 # Max physical DM softening length (in internal units). + # Parameters for the hydrodynamics scheme SPH: diff --git a/examples/EAGLE_low_z/EAGLE_50/eagle_50.yml b/examples/EAGLE_low_z/EAGLE_50/eagle_50.yml index 14844f49a5fe56607e0bd95dd57d44c42cb43f9d..943c64c7a29fd87b9b5f78a4edded6b14e0f3c57 100644 --- a/examples/EAGLE_low_z/EAGLE_50/eagle_50.yml +++ b/examples/EAGLE_low_z/EAGLE_50/eagle_50.yml @@ -1,3 +1,6 @@ +MetaData: + run_name: EAGLE-L0050N0752-Ref + # Define the system of units to use internally. InternalUnitSystem: UnitMass_in_cgs: 1.98848e43 # 10^10 M_sun in grams @@ -42,9 +45,11 @@ Statistics: Gravity: eta: 0.025 # Constant dimensionless multiplier for time integration. theta: 0.7 # Opening angle (Multipole acceptance criterion) - comoving_softening: 0.0026994 # Comoving softening length (in internal units). - max_physical_softening: 0.0007 # Physical softening length (in internal units). mesh_side_length: 128 + comoving_DM_softening: 0.0026994 # Comoving DM softening length (in internal units). + max_physical_DM_softening: 0.0007 # Max physical DM softening length (in internal units). + comoving_baryon_softening: 0.0026994 # Comoving DM softening length (in internal units). + max_physical_baryon_softening: 0.0007 # Max physical DM softening length (in internal units). # Parameters for the hydrodynamics scheme SPH: diff --git a/examples/EAGLE_low_z/EAGLE_6/eagle_6.yml b/examples/EAGLE_low_z/EAGLE_6/eagle_6.yml index 9aef75d741efa148f2397ba172d1ca6c86dd20d9..48a825750fd2a927ba08dfc5a8a4607a490fe0d8 100644 --- a/examples/EAGLE_low_z/EAGLE_6/eagle_6.yml +++ b/examples/EAGLE_low_z/EAGLE_6/eagle_6.yml @@ -1,3 +1,6 @@ +MetaData: + run_name: EAGLE-L0006N0094-Ref + # Define the system of units to use internally. InternalUnitSystem: UnitMass_in_cgs: 1.98848e43 # 10^10 M_sun in grams @@ -52,9 +55,11 @@ Statistics: Gravity: eta: 0.025 # Constant dimensionless multiplier for time integration. theta: 0.7 # Opening angle (Multipole acceptance criterion) - comoving_softening: 0.0026994 # Comoving softening length (in internal units). - max_physical_softening: 0.0007 # Physical softening length (in internal units). mesh_side_length: 16 + comoving_DM_softening: 0.0026994 # Comoving DM softening length (in internal units). + max_physical_DM_softening: 0.0007 # Max physical DM softening length (in internal units). + comoving_baryon_softening: 0.0026994 # Comoving DM softening length (in internal units). + max_physical_baryon_softening: 0.0007 # Max physical DM softening length (in internal units). # Parameters for the hydrodynamics scheme SPH: diff --git a/examples/GiantImpacts/GiantImpact/uranus_1e6.yml b/examples/GiantImpacts/GiantImpact/uranus_1e6.yml index 355748d847097623f171078c2ca8372e06a06efa..b98467616f659babb488352c87697a43fedcc0db 100644 --- a/examples/GiantImpacts/GiantImpact/uranus_1e6.yml +++ b/examples/GiantImpacts/GiantImpact/uranus_1e6.yml @@ -48,8 +48,8 @@ SPH: Gravity: eta: 0.025 # Constant dimensionless multiplier for time integration. theta: 0.7 # Opening angle (Multipole acceptance criterion) - comoving_softening: 0.003 # Comoving softening length (in internal units). - max_physical_softening: 0.003 # Physical softening length (in internal units). + comoving_baryon_softening: 0.003 # Comoving softening length (in internal units). + max_physical_baryon_softening: 0.003 # Physical softening length (in internal units). # Parameters for the task scheduling Scheduler: diff --git a/examples/IsolatedGalaxy/IsolatedGalaxy_dmparticles/isolated_galaxy.yml b/examples/IsolatedGalaxy/IsolatedGalaxy_dmparticles/isolated_galaxy.yml index dccfb28a3f1c888d2a83b5e28b759a30a6928754..27ab01d984319fea68d4d1ae8fb435a6adf895ce 100644 --- a/examples/IsolatedGalaxy/IsolatedGalaxy_dmparticles/isolated_galaxy.yml +++ b/examples/IsolatedGalaxy/IsolatedGalaxy_dmparticles/isolated_galaxy.yml @@ -8,11 +8,9 @@ InternalUnitSystem: # Parameters for the self-gravity scheme Gravity: - mesh_side_length: 32 # Number of cells along each axis for the periodic gravity mesh. eta: 0.025 # Constant dimensionless multiplier for time integration. theta: 0.7 # Opening angle (Multipole acceptance criterion). - comoving_softening: 0.0026994 # Comoving softening length (in internal units). - max_physical_softening: 0.0007 # Physical softening length (in internal units). + max_physical_DM_softening: 0.7 # Physical softening length (in internal units). # Parameters governing the time integration (Set dt_min and dt_max to the same value for a fixed time-step run.) TimeIntegration: diff --git a/examples/IsolatedGalaxy/IsolatedGalaxy_feedback/isolated_galaxy.yml b/examples/IsolatedGalaxy/IsolatedGalaxy_feedback/isolated_galaxy.yml index 4d3485d838f56067cbb8493c79d06dff8a3dceba..79fe5682692347127081f021ed6930df57bbfa02 100644 --- a/examples/IsolatedGalaxy/IsolatedGalaxy_feedback/isolated_galaxy.yml +++ b/examples/IsolatedGalaxy/IsolatedGalaxy_feedback/isolated_galaxy.yml @@ -10,8 +10,8 @@ InternalUnitSystem: Gravity: eta: 0.025 # Constant dimensionless multiplier for time integration. theta: 0.7 # Opening angle (Multipole acceptance criterion). - comoving_softening: 0.1 # Comoving softening length (in internal units). - max_physical_softening: 0.1 # Physical softening length (in internal units). + max_physical_DM_softening: 0.1 # Physical softening length (in internal units). + max_physical_baryon_softening: 0.1 # Physical softening length (in internal units). # Parameters governing the time integration (Set dt_min and dt_max to the same value for a fixed time-step run.) TimeIntegration: diff --git a/examples/IsolatedGalaxy/IsolatedGalaxy_potential/isolated_galaxy.yml b/examples/IsolatedGalaxy/IsolatedGalaxy_potential/isolated_galaxy.yml index deee132ee38ae5e04397839a21a677f4851e6bac..3bd743c2ec329057c7f63f987e4809744a07f7ba 100644 --- a/examples/IsolatedGalaxy/IsolatedGalaxy_potential/isolated_galaxy.yml +++ b/examples/IsolatedGalaxy/IsolatedGalaxy_potential/isolated_galaxy.yml @@ -8,11 +8,9 @@ InternalUnitSystem: # Parameters for the self-gravity scheme Gravity: - mesh_side_length: 32 # Number of cells along each axis for the periodic gravity mesh. eta: 0.025 # Constant dimensionless multiplier for time integration. theta: 0.7 # Opening angle (Multipole acceptance criterion). - comoving_softening: 0.0300 # Comoving softening length (in internal units). - max_physical_softening: 0.0300 # Physical softening length (in internal units). + max_physical_baryon_softening: 0.100 # Physical softening length (in internal units). # Parameters governing the time integration (Set dt_min and dt_max to the same value for a fixed time-step run.) TimeIntegration: @@ -34,7 +32,7 @@ Statistics: time_first: 0. # (Optional) Time of the first stats output if non-cosmological time-integration (in internal units) Scheduler: - max_top_level_cells: 96 + max_top_level_cells: 32 # Parameters related to the initial conditions InitialConditions: diff --git a/examples/IsolatedGalaxy/IsolatedGalaxy_starformation/isolated_galaxy.yml b/examples/IsolatedGalaxy/IsolatedGalaxy_starformation/isolated_galaxy.yml index d347e1ad5bd8ddf6c132fade07e5d50688a451b0..d917f926724c022cd15524058ddde2a7466acaab 100644 --- a/examples/IsolatedGalaxy/IsolatedGalaxy_starformation/isolated_galaxy.yml +++ b/examples/IsolatedGalaxy/IsolatedGalaxy_starformation/isolated_galaxy.yml @@ -8,11 +8,10 @@ InternalUnitSystem: # Parameters for the self-gravity scheme Gravity: - mesh_side_length: 32 # Number of cells along each axis for the periodic gravity mesh. - eta: 0.025 # Constant dimensionless multiplier for time integration. - theta: 0.7 # Opening angle (Multipole acceptance criterion). - comoving_softening: 0.01 # Comoving softening length (in internal units). - max_physical_softening: 0.01 # Physical softening length (in internal units). + eta: 0.025 # Constant dimensionless multiplier for time integration. + theta: 0.7 # Opening angle (Multipole acceptance criterion). + max_physical_DM_softening: 0.1 # Physical softening length (in internal units). + max_physical_baryon_softening: 0.1 # Physical softening length (in internal units). # Parameters governing the time integration (Set dt_min and dt_max to the same value for a fixed time-step run.) TimeIntegration: diff --git a/examples/PMillennium/PMillennium-1536/p-mill-1536.yml b/examples/PMillennium/PMillennium-1536/p-mill-1536.yml index 770cc4a03e8912eed51d1851b81578496a42070c..f343650452a24f620edef88e42666e09213dbd64 100644 --- a/examples/PMillennium/PMillennium-1536/p-mill-1536.yml +++ b/examples/PMillennium/PMillennium-1536/p-mill-1536.yml @@ -43,9 +43,9 @@ Statistics: Gravity: eta: 0.025 theta: 0.5 - comoving_softening: 0.0208333 # 20.8333 kpc = 1/25 mean inter-particle separation - max_physical_softening: 0.0208333 # 20.8333 kpc = 1/25 mean inter-particle separation - mesh_side_length: 256 + comoving_DM_softening: 0.0208333 # 20.8333 kpc = 1/25 mean inter-particle separation + max_physical_DM_softening: 0.0208333 # 20.8333 kpc = 1/25 mean inter-particle separation + mesh_side_length: 512 # Parameters related to the initial conditions InitialConditions: diff --git a/examples/PMillennium/PMillennium-384/p-mill-384.yml b/examples/PMillennium/PMillennium-384/p-mill-384.yml index 428f893300bf3431f20518a6a1259651b3c67226..0e68969d0b590cec8058805e4644b2763c543be1 100644 --- a/examples/PMillennium/PMillennium-384/p-mill-384.yml +++ b/examples/PMillennium/PMillennium-384/p-mill-384.yml @@ -43,9 +43,9 @@ Statistics: Gravity: eta: 0.025 theta: 0.5 - comoving_softening: 0.08333 # 83.333 kpc = 1/25 mean inter-particle separation - max_physical_softening: 0.08333 # 83.333 kpc = 1/25 mean inter-particle separation - mesh_side_length: 64 + comoving_DM_softening: 0.08333 # 83.333 kpc = 1/25 mean inter-particle separation + max_physical_DM_softening: 0.08333 # 83.333 kpc = 1/25 mean inter-particle separation + mesh_side_length: 128 # Parameters related to the initial conditions InitialConditions: diff --git a/examples/PMillennium/PMillennium-768/p-mill-768.yml b/examples/PMillennium/PMillennium-768/p-mill-768.yml index 339fad2c7059d8c8bcab2878fc8958a3bd1977d7..1cd9e63b1f03ac65baf72701de276b8ff43c9575 100644 --- a/examples/PMillennium/PMillennium-768/p-mill-768.yml +++ b/examples/PMillennium/PMillennium-768/p-mill-768.yml @@ -43,9 +43,9 @@ Statistics: Gravity: eta: 0.025 theta: 0.5 - comoving_softening: 0.041666 # 41.6666 kpc = 1/25 mean inter-particle separation - max_physical_softening: 0.041666 # 41.6666 kpc = 1/25 mean inter-particle separation - mesh_side_length: 128 + comoving_DM_softening: 0.041666 # 41.6666 kpc = 1/25 mean inter-particle separation + max_physical_DM_softening: 0.041666 # 41.6666 kpc = 1/25 mean inter-particle separation + mesh_side_length: 256 # Parameters related to the initial conditions InitialConditions: diff --git a/examples/SantaBarbara/SantaBarbara-128/santa_barbara.yml b/examples/SantaBarbara/SantaBarbara-128/santa_barbara.yml index 1221cefb92e51e54bfe73a0414b95a89fcda592a..e57617e149cb9f302d8fe08bd93d660059caa0ef 100644 --- a/examples/SantaBarbara/SantaBarbara-128/santa_barbara.yml +++ b/examples/SantaBarbara/SantaBarbara-128/santa_barbara.yml @@ -43,9 +43,11 @@ Statistics: Gravity: eta: 0.025 theta: 0.5 - comoving_softening: 0.02 # 20 kpc = 1/25 mean inter-particle separation - max_physical_softening: 0.00526 # 20 ckpc = 5.26 pkpc at z=2.8 (EAGLE-like evolution of softening). - mesh_side_length: 64 + comoving_DM_softening: 0.02 # 20 kpc = 1/25 mean inter-particle separation + max_physical_DM_softening: 0.00526 # 20 ckpc = 5.26 pkpc at z=2.8 (EAGLE-like evolution of softening). + comoving_baryon_softening: 0.02 # 20 kpc = 1/25 mean inter-particle separation + max_physical_baryon_softening: 0.00526 # 20 ckpc = 5.26 pkpc at z=2.8 (EAGLE-like evolution of softening). + mesh_side_length: 128 # Parameters of the hydro scheme SPH: diff --git a/examples/SantaBarbara/SantaBarbara-256/santa_barbara.yml b/examples/SantaBarbara/SantaBarbara-256/santa_barbara.yml index 04bb18191b750aa996e43b58b24451135bceedca..c95914d58ef01ac48f5db83ea4b3f3a1f93404f9 100644 --- a/examples/SantaBarbara/SantaBarbara-256/santa_barbara.yml +++ b/examples/SantaBarbara/SantaBarbara-256/santa_barbara.yml @@ -43,9 +43,11 @@ Statistics: Gravity: eta: 0.025 theta: 0.5 - comoving_softening: 0.01 # 10 kpc = 1/25 mean inter-particle separation - max_physical_softening: 0.00263 # 10 ckpc = 2.63 pkpc at z=2.8 (EAGLE-like evolution of softening). - mesh_side_length: 128 + comoving_DM_softening: 0.01 # 10 kpc = 1/25 mean inter-particle separation + max_physical_DM_softening: 0.00263 # 10 ckpc = 2.63 pkpc at z=2.8 (EAGLE-like evolution of softening). + comoving_baryon_softening: 0.01 # 10 kpc = 1/25 mean inter-particle separation + max_physical_baryon_softening: 0.00263 # 10 ckpc = 2.63 pkpc at z=2.8 (EAGLE-like evolution of softening). + mesh_side_length: 256 # Parameters of the hydro scheme SPH: diff --git a/examples/SmallCosmoVolume/SmallCosmoVolume_DM/small_cosmo_volume_dm.yml b/examples/SmallCosmoVolume/SmallCosmoVolume_DM/small_cosmo_volume_dm.yml index ebe3a78ee0d03eb53752b1dfa8fa749931a754a9..975ceac9c3c9404dc2c194abc4de40bf7d529a11 100644 --- a/examples/SmallCosmoVolume/SmallCosmoVolume_DM/small_cosmo_volume_dm.yml +++ b/examples/SmallCosmoVolume/SmallCosmoVolume_DM/small_cosmo_volume_dm.yml @@ -29,9 +29,9 @@ TimeIntegration: # Parameters for the self-gravity scheme Gravity: eta: 0.025 - theta: 0.3 - comoving_softening: 0.0889 # 1/25th of the mean inter-particle separation: 88.9 kpc - max_physical_softening: 0.0889 # 1/25th of the mean inter-particle separation: 88.9 kpc + theta: 0.5 + comoving_DM_softening: 0.0889 # 1/25th of the mean inter-particle separation: 88.9 kpc + max_physical_DM_softening: 0.0889 # 1/25th of the mean inter-particle separation: 88.9 kpc mesh_side_length: 64 # Parameters governing the snapshots diff --git a/examples/SmallCosmoVolume/SmallCosmoVolume_VELOCIraptor/small_cosmo_volume.yml b/examples/SmallCosmoVolume/SmallCosmoVolume_VELOCIraptor/small_cosmo_volume.yml index 15007ca8d39a328166a208a2d4cbbc6aea580009..f81c38a85f04b074f4cf5598bc3d09716b49f790 100644 --- a/examples/SmallCosmoVolume/SmallCosmoVolume_VELOCIraptor/small_cosmo_volume.yml +++ b/examples/SmallCosmoVolume/SmallCosmoVolume_VELOCIraptor/small_cosmo_volume.yml @@ -22,9 +22,11 @@ TimeIntegration: # Parameters for the self-gravity scheme Gravity: eta: 0.025 - theta: 0.3 - comoving_softening: 0.0889 # 1/25th of the mean inter-particle separation: 88.9 kpc - max_physical_softening: 0.0889 # 1/25th of the mean inter-particle separation: 88.9 kpc + theta: 0.5 + comoving_DM_softening: 0.0889 # 1/25th of the mean inter-particle separation: 88.9 kpc + max_physical_DM_softening: 0.0889 # 1/25th of the mean inter-particle separation: 88.9 kpc + comoving_baryon_softening: 0.0889 # 1/25th of the mean inter-particle separation: 88.9 kpc + max_physical_baryon_softening: 0.0889 # 1/25th of the mean inter-particle separation: 88.9 kpc mesh_side_length: 64 # Parameters of the hydro scheme diff --git a/examples/SmallCosmoVolume/SmallCosmoVolume_cooling/small_cosmo_volume.yml b/examples/SmallCosmoVolume/SmallCosmoVolume_cooling/small_cosmo_volume.yml index 5050f9e05e278df25b050c10d9897e29d4e21804..aea198bd789b48d608c6fc3fdc493303d6d9afd2 100644 --- a/examples/SmallCosmoVolume/SmallCosmoVolume_cooling/small_cosmo_volume.yml +++ b/examples/SmallCosmoVolume/SmallCosmoVolume_cooling/small_cosmo_volume.yml @@ -23,8 +23,10 @@ TimeIntegration: Gravity: eta: 0.025 theta: 0.3 - comoving_softening: 0.0889 # 1/25th of the mean inter-particle separation: 88.9 kpc - max_physical_softening: 0.0889 # 1/25th of the mean inter-particle separation: 88.9 kpc + comoving_DM_softening: 0.0889 # 1/25th of the mean inter-particle separation: 88.9 kpc + max_physical_DM_softening: 0.0889 # 1/25th of the mean inter-particle separation: 88.9 kpc + comoving_baryon_softening: 0.0889 # 1/25th of the mean inter-particle separation: 88.9 kpc + max_physical_baryon_softening: 0.0889 # 1/25th of the mean inter-particle separation: 88.9 kpc mesh_side_length: 64 # Parameters of the hydro scheme diff --git a/examples/SmallCosmoVolume/SmallCosmoVolume_hydro/small_cosmo_volume.yml b/examples/SmallCosmoVolume/SmallCosmoVolume_hydro/small_cosmo_volume.yml index e0d633079e941ade161b7e2fde0fbc063cbac254..5904a412f7bf63336de976baa6da4506bae4e36c 100644 --- a/examples/SmallCosmoVolume/SmallCosmoVolume_hydro/small_cosmo_volume.yml +++ b/examples/SmallCosmoVolume/SmallCosmoVolume_hydro/small_cosmo_volume.yml @@ -22,9 +22,11 @@ TimeIntegration: # Parameters for the self-gravity scheme Gravity: eta: 0.025 - theta: 0.3 - comoving_softening: 0.0889 # 1/25th of the mean inter-particle separation: 88.9 kpc - max_physical_softening: 0.0889 # 1/25th of the mean inter-particle separation: 88.9 kpc + theta: 0.5 + comoving_DM_softening: 0.0889 # 1/25th of the mean inter-particle separation: 88.9 kpc + max_physical_DM_softening: 0.0889 # 1/25th of the mean inter-particle separation: 88.9 kpc + comoving_baryon_softening: 0.0889 # 1/25th of the mean inter-particle separation: 88.9 kpc + max_physical_baryon_softening: 0.0889 # 1/25th of the mean inter-particle separation: 88.9 kpc mesh_side_length: 64 # Parameters of the hydro scheme diff --git a/examples/main.c b/examples/main.c index 491b1ac1e72895ba7f9028d7c0b1bf9181f70360..62e5e85ba13527f1119b73234e2ceb1122f9f397 100644 --- a/examples/main.c +++ b/examples/main.c @@ -440,6 +440,9 @@ int main(int argc, char *argv[]) { /* Genesis 1.1: And then, there was time ! */ clocks_set_cpufreq(cpufreq); + /* Are we running with gravity */ + const int with_gravity = (with_self_gravity || with_external_gravity); + /* How vocal are we ? */ const int talking = (verbose == 1 && myrank == 0) || (verbose == 2); @@ -745,12 +748,6 @@ int main(int argc, char *argv[]) { const int generate_gas_in_ics = parser_get_opt_param_int( params, "InitialConditions:generate_gas_in_ics", 0); - /* Some checks that we are not doing something stupid */ - if (generate_gas_in_ics && flag_entropy_ICs) - error("Can't generate gas if the entropy flag is set in the ICs."); - if (generate_gas_in_ics && !with_cosmology) - error("Can't generate gas if the run is not cosmological."); - /* Initialise the cosmology */ if (with_cosmology) cosmology_init(params, &us, &prog_const, &cosmo); @@ -811,12 +808,6 @@ int main(int argc, char *argv[]) { } else bzero(&black_holes_properties, sizeof(struct black_holes_props)); - /* Initialise the gravity properties */ - bzero(&gravity_properties, sizeof(struct gravity_props)); - if (with_self_gravity) - gravity_props_init(&gravity_properties, params, &prog_const, &cosmo, - with_cosmology, periodic); - /* Initialise the cooling function properties */ #ifdef COOLING_NONE if (with_cooling || with_temperature) { @@ -868,32 +859,33 @@ int main(int argc, char *argv[]) { fflush(stdout); /* Get ready to read particles of all kinds */ - size_t Ngas = 0, Ngpart = 0, Nspart = 0, Nbpart = 0; + size_t Ngas = 0, Ngpart = 0, Ngpart_background = 0, Nspart = 0, Nbpart = 0; double dim[3] = {0., 0., 0.}; + if (myrank == 0) clocks_gettime(&tic); #if defined(HAVE_HDF5) #if defined(WITH_MPI) #if defined(HAVE_PARALLEL_HDF5) read_ic_parallel(ICfileName, &us, dim, &parts, &gparts, &sparts, &bparts, - &Ngas, &Ngpart, &Nspart, &Nbpart, &flag_entropy_ICs, - with_hydro, (with_external_gravity || with_self_gravity), - with_stars, with_black_holes, cleanup_h, cleanup_sqrt_a, - cosmo.h, cosmo.a, myrank, nr_nodes, MPI_COMM_WORLD, - MPI_INFO_NULL, nr_threads, dry_run); + &Ngas, &Ngpart, &Ngpart_background, &Nspart, &Nbpart, + &flag_entropy_ICs, with_hydro, with_gravity, with_stars, + with_black_holes, cleanup_h, cleanup_sqrt_a, cosmo.h, + cosmo.a, myrank, nr_nodes, MPI_COMM_WORLD, MPI_INFO_NULL, + nr_threads, dry_run); #else read_ic_serial(ICfileName, &us, dim, &parts, &gparts, &sparts, &bparts, - &Ngas, &Ngpart, &Nspart, &Nbpart, &flag_entropy_ICs, - with_hydro, (with_external_gravity || with_self_gravity), - with_stars, with_black_holes, cleanup_h, cleanup_sqrt_a, - cosmo.h, cosmo.a, myrank, nr_nodes, MPI_COMM_WORLD, - MPI_INFO_NULL, nr_threads, dry_run); + &Ngas, &Ngpart, &Ngpart_background, &Nspart, &Nbpart, + &flag_entropy_ICs, with_hydro, with_gravity, with_stars, + with_black_holes, cleanup_h, cleanup_sqrt_a, cosmo.h, + cosmo.a, myrank, nr_nodes, MPI_COMM_WORLD, MPI_INFO_NULL, + nr_threads, dry_run); #endif #else read_ic_single(ICfileName, &us, dim, &parts, &gparts, &sparts, &bparts, - &Ngas, &Ngpart, &Nspart, &Nbpart, &flag_entropy_ICs, - with_hydro, (with_external_gravity || with_self_gravity), - with_stars, with_black_holes, cleanup_h, cleanup_sqrt_a, - cosmo.h, cosmo.a, nr_threads, dry_run); + &Ngas, &Ngpart, &Ngpart_background, &Nspart, &Nbpart, + &flag_entropy_ICs, with_hydro, with_gravity, with_stars, + with_black_holes, cleanup_h, cleanup_sqrt_a, cosmo.h, + cosmo.a, nr_threads, dry_run); #endif #endif if (myrank == 0) { @@ -903,6 +895,12 @@ int main(int argc, char *argv[]) { fflush(stdout); } + /* Some checks that we are not doing something stupid */ + if (generate_gas_in_ics && flag_entropy_ICs) + error("Can't generate gas if the entropy flag is set in the ICs."); + if (generate_gas_in_ics && !with_cosmology) + error("Can't generate gas if the run is not cosmological."); + #ifdef SWIFT_DEBUG_CHECKS /* Check once and for all that we don't have unwanted links */ if (!with_stars && !dry_run) { @@ -925,23 +923,46 @@ int main(int argc, char *argv[]) { #endif /* Get the total number of particles across all nodes. */ - long long N_total[4] = {0, 0, 0, 0}; + long long N_total[swift_type_count + 1] = {0}; + long long Nbaryons = Ngas + Nspart + Nbpart; #if defined(WITH_MPI) - long long N_long[4] = {Ngas, Ngpart, Nspart, Nbpart}; - MPI_Allreduce(&N_long, &N_total, 4, MPI_LONG_LONG_INT, MPI_SUM, - MPI_COMM_WORLD); + long long N_long[swift_type_count + 1] = {0}; + N_long[swift_type_gas] = Ngas; + N_long[swift_type_dark_matter] = + with_gravity ? Ngpart - Ngpart_background - Nbaryons : 0; + N_long[swift_type_dark_matter_background] = Ngpart_background; + N_long[swift_type_stars] = Nspart; + N_long[swift_type_black_hole] = Nbpart; + N_long[swift_type_count] = Ngpart; + MPI_Allreduce(&N_long, &N_total, swift_type_count + 1, MPI_LONG_LONG_INT, + MPI_SUM, MPI_COMM_WORLD); #else - N_total[0] = Ngas; - N_total[1] = Ngpart; - N_total[2] = Nspart; - N_total[3] = Nbpart; + N_total[swift_type_gas] = Ngas; + N_total[swift_type_dark_matter] = + with_gravity ? Ngpart - Ngpart_background - Nbaryons : 0; + N_total[swift_type_dark_matter_background] = Ngpart_background; + N_total[swift_type_stars] = Nspart; + N_total[swift_type_black_hole] = Nbpart; + N_total[swift_type_count] = Ngpart; #endif if (myrank == 0) message( "Read %lld gas particles, %lld stars particles, %lld black hole " - "particles and %lld gparts from the ICs.", - N_total[0], N_total[2], N_total[3], N_total[1]); + "particles, %lld DM particles and %lld DM background particles from " + "the ICs.", + N_total[swift_type_gas], N_total[swift_type_stars], + N_total[swift_type_black_hole], N_total[swift_type_dark_matter], + N_total[swift_type_dark_matter_background]); + + const int with_DM_particles = N_total[swift_type_dark_matter] > 0; + const int with_baryon_particles = + (N_total[swift_type_gas] + N_total[swift_type_stars] + + N_total[swift_type_black_hole]) > 0; + + /* Do we have background DM particles? */ + const int with_DM_background_particles = + N_total[swift_type_dark_matter_background] > 0; /* Verify that the fields to dump actually exist */ if (myrank == 0) io_check_output_fields(params, N_total); @@ -950,8 +971,8 @@ int main(int argc, char *argv[]) { if (myrank == 0) clocks_gettime(&tic); space_init(&s, params, &cosmo, dim, parts, gparts, sparts, bparts, Ngas, Ngpart, Nspart, Nbpart, periodic, replicate, generate_gas_in_ics, - with_hydro, with_self_gravity, with_star_formation, talking, - dry_run); + with_hydro, with_self_gravity, with_star_formation, + with_DM_background_particles, talking, dry_run); if (myrank == 0) { clocks_gettime(&toc); @@ -960,6 +981,14 @@ int main(int argc, char *argv[]) { fflush(stdout); } + /* Initialise the gravity properties */ + bzero(&gravity_properties, sizeof(struct gravity_props)); + if (with_self_gravity) + gravity_props_init(&gravity_properties, params, &prog_const, &cosmo, + with_cosmology, with_baryon_particles, + with_DM_particles, with_DM_background_particles, + periodic); + /* Initialise the external potential properties */ bzero(&potential, sizeof(struct external_potential)); if (with_external_gravity) @@ -984,19 +1013,24 @@ int main(int argc, char *argv[]) { if (with_cosmology && with_self_gravity && !dry_run) space_check_cosmology(&s, &cosmo, myrank); -/* Also update the total counts (in case of changes due to replication) */ + /* Also update the total counts (in case of changes due to replication) */ + Nbaryons = s.nr_parts + s.nr_sparts + s.nr_bparts; #if defined(WITH_MPI) - N_long[0] = s.nr_parts; - N_long[1] = s.nr_gparts; - N_long[2] = s.nr_sparts; - N_long[3] = s.nr_bparts; - MPI_Allreduce(&N_long, &N_total, 4, MPI_LONG_LONG_INT, MPI_SUM, - MPI_COMM_WORLD); + N_long[swift_type_gas] = s.nr_parts; + N_long[swift_type_dark_matter] = + with_gravity ? s.nr_gparts - Ngpart_background - Nbaryons : 0; + N_long[swift_type_count] = s.nr_gparts; + N_long[swift_type_stars] = s.nr_sparts; + N_long[swift_type_black_hole] = s.nr_bparts; + MPI_Allreduce(&N_long, &N_total, swift_type_count + 1, MPI_LONG_LONG_INT, + MPI_SUM, MPI_COMM_WORLD); #else - N_total[0] = s.nr_parts; - N_total[1] = s.nr_gparts; - N_total[2] = s.nr_sparts; - N_total[3] = s.nr_bparts; + N_total[swift_type_gas] = s.nr_parts; + N_total[swift_type_dark_matter] = + with_gravity ? s.nr_gparts - Ngpart_background - Nbaryons : 0; + N_total[swift_type_count] = s.nr_gparts; + N_total[swift_type_stars] = s.nr_sparts; + N_total[swift_type_black_hole] = s.nr_bparts; #endif /* Say a few nice things about the space we just created. */ @@ -1020,7 +1054,7 @@ int main(int argc, char *argv[]) { "ERROR: Running with hydrodynamics but no gas particles found in the " "ICs!"); } - if ((with_self_gravity || with_external_gravity) && N_total[1] == 0) { + if (with_gravity && N_total[1] == 0) { error( "ERROR: Running with gravity but no gravity particles found in " "the ICs!"); @@ -1063,12 +1097,14 @@ int main(int argc, char *argv[]) { /* Initialize the engine with the space and policies. */ if (myrank == 0) clocks_gettime(&tic); - engine_init(&e, &s, params, N_total[0], N_total[1], N_total[2], N_total[3], - engine_policies, talking, &reparttype, &us, &prog_const, &cosmo, - &hydro_properties, &entropy_floor, &gravity_properties, - &stars_properties, &black_holes_properties, - &feedback_properties, &mesh, &potential, &cooling_func, - &starform, &chemistry, &fof_properties); + engine_init( + &e, &s, params, N_total[swift_type_gas], N_total[swift_type_count], + N_total[swift_type_stars], N_total[swift_type_black_hole], + N_total[swift_type_dark_matter_background], engine_policies, talking, + &reparttype, &us, &prog_const, &cosmo, &hydro_properties, + &entropy_floor, &gravity_properties, &stars_properties, + &black_holes_properties, &feedback_properties, &mesh, &potential, + &cooling_func, &starform, &chemistry, &fof_properties); engine_config(/*restart=*/0, /*fof=*/0, &e, params, nr_nodes, myrank, nr_threads, with_aff, talking, restart_file); @@ -1081,12 +1117,13 @@ int main(int argc, char *argv[]) { /* Get some info to the user. */ if (myrank == 0) { - long long N_DM = N_total[1] - N_total[2] - N_total[3] - N_total[0]; + const long long N_DM = N_total[swift_type_dark_matter] + + N_total[swift_type_dark_matter_background]; message( "Running on %lld gas particles, %lld stars particles %lld black " "hole particles and %lld DM particles (%lld gravity particles)", - N_total[0], N_total[2], N_total[3], N_total[1] > 0 ? N_DM : 0, - N_total[1]); + N_total[swift_type_gas], N_total[swift_type_stars], + N_total[swift_type_black_hole], N_DM, N_total[swift_type_count]); message( "from t=%.3e until t=%.3e with %d ranks, %d threads / rank and %d " "task queues / rank (dt_min=%.3e, dt_max=%.3e)...", diff --git a/examples/main_fof.c b/examples/main_fof.c index 1672cdacd5322d8c18922c1b9784f779e776c0ac..c96cb1267e8c3ab6890de121a9d7fb3fb16443df 100644 --- a/examples/main_fof.c +++ b/examples/main_fof.c @@ -409,11 +409,6 @@ int main(int argc, char *argv[]) { /* Initialise the cosmology */ cosmology_init(params, &us, &prog_const, &cosmo); - /* Initialise the gravity scheme */ - bzero(&gravity_properties, sizeof(struct gravity_props)); - gravity_props_init(&gravity_properties, params, &prog_const, &cosmo, - /*with_cosmology=*/1, periodic); - /* Initialise the FOF properties */ bzero(&fof_properties, sizeof(struct fof_props)); if (with_fof) fof_init(&fof_properties, params, &prog_const, &us); @@ -428,28 +423,32 @@ int main(int argc, char *argv[]) { /* Get ready to read particles of all kinds */ int flag_entropy_ICs = 0; - size_t Ngas = 0, Ngpart = 0, Nspart = 0, Nbpart = 0; + size_t Ngas = 0, Ngpart = 0, Ngpart_background = 0, Nspart = 0, Nbpart = 0; double dim[3] = {0., 0., 0.}; + if (myrank == 0) clocks_gettime(&tic); #if defined(HAVE_HDF5) #if defined(WITH_MPI) #if defined(HAVE_PARALLEL_HDF5) read_ic_parallel(ICfileName, &us, dim, &parts, &gparts, &sparts, &bparts, - &Ngas, &Ngpart, &Nspart, &Nbpart, &flag_entropy_ICs, - with_hydro, /*with_grav=*/1, with_stars, with_black_holes, - cleanup_h, cleanup_sqrt_a, cosmo.h, cosmo.a, myrank, - nr_nodes, MPI_COMM_WORLD, MPI_INFO_NULL, nr_threads, + &Ngas, &Ngpart, &Ngpart_background, &Nspart, &Nbpart, + &flag_entropy_ICs, with_hydro, + /*with_grav=*/1, with_stars, with_black_holes, cleanup_h, + cleanup_sqrt_a, cosmo.h, cosmo.a, myrank, nr_nodes, + MPI_COMM_WORLD, MPI_INFO_NULL, nr_threads, /*dry_run=*/0); #else read_ic_serial(ICfileName, &us, dim, &parts, &gparts, &sparts, &bparts, &Ngas, - &Ngpart, &Nspart, &Nbpart, &flag_entropy_ICs, with_hydro, + &Ngpart, &Ngpart_background, &Nspart, &Nbpart, + &flag_entropy_ICs, with_hydro, /*with_grav=*/1, with_stars, with_black_holes, cleanup_h, cleanup_sqrt_a, cosmo.h, cosmo.a, myrank, nr_nodes, MPI_COMM_WORLD, MPI_INFO_NULL, nr_threads, /*dry_run=*/0); #endif #else read_ic_single(ICfileName, &us, dim, &parts, &gparts, &sparts, &bparts, &Ngas, - &Ngpart, &Nspart, &Nbpart, &flag_entropy_ICs, with_hydro, + &Ngpart, &Ngpart_background, &Nspart, &Nbpart, + &flag_entropy_ICs, with_hydro, /*with_grav=*/1, with_stars, with_black_holes, cleanup_h, cleanup_sqrt_a, cosmo.h, cosmo.a, nr_threads, /*dry_run=*/0); #endif @@ -468,30 +467,51 @@ int main(int argc, char *argv[]) { #endif /* Get the total number of particles across all nodes. */ - long long N_total[4] = {0, 0, 0}; + long long N_total[swift_type_count + 1] = {0}; + long long Nbaryons = Ngas + Nspart + Nbpart; #if defined(WITH_MPI) - long long N_long[4] = {Ngas, Ngpart, Nspart, Nbpart}; - MPI_Allreduce(&N_long, &N_total, 4, MPI_LONG_LONG_INT, MPI_SUM, - MPI_COMM_WORLD); + long long N_long[swift_type_count + 1] = {0}; + N_long[swift_type_gas] = Ngas; + N_long[swift_type_dark_matter] = Ngpart - Ngpart_background - Nbaryons; + N_long[swift_type_dark_matter_background] = Ngpart_background; + N_long[swift_type_stars] = Nspart; + N_long[swift_type_black_hole] = Nbpart; + N_long[swift_type_count] = Ngpart; + MPI_Allreduce(&N_long, &N_total, swift_type_count + 1, MPI_LONG_LONG_INT, + MPI_SUM, MPI_COMM_WORLD); #else - N_total[0] = Ngas; - N_total[1] = Ngpart; - N_total[2] = Nspart; - N_total[3] = Nbpart; + N_total[swift_type_gas] = Ngas; + N_total[swift_type_dark_matter] = Ngpart - Ngpart_background - Nbaryons; + N_total[swift_type_dark_matter_background] = Ngpart_background; + N_total[swift_type_stars] = Nspart; + N_total[swift_type_black_hole] = Nbpart; + N_total[swift_type_count] = Ngpart; #endif if (myrank == 0) message( "Read %lld gas particles, %lld stars particles, %lld black hole " - "particles and %lld gparts from the ICs.", - N_total[0], N_total[2], N_total[3], N_total[1]); + "particles, %lld DM particles and %lld DM background particles from " + "the ICs.", + N_total[swift_type_gas], N_total[swift_type_stars], + N_total[swift_type_black_hole], N_total[swift_type_dark_matter], + N_total[swift_type_dark_matter_background]); + + const int with_DM_particles = N_total[swift_type_dark_matter] > 0; + const int with_baryon_particles = + (N_total[swift_type_gas] + N_total[swift_type_stars] + + N_total[swift_type_black_hole]) > 0; + + /* Do we have background DM particles? */ + const int with_DM_background_particles = + N_total[swift_type_dark_matter_background] > 0; /* Initialize the space with these data. */ if (myrank == 0) clocks_gettime(&tic); space_init(&s, params, &cosmo, dim, parts, gparts, sparts, bparts, Ngas, Ngpart, Nspart, Nbpart, periodic, replicate, /*generate_gas_in_ics=*/0, /*hydro=*/N_total[0] > 0, /*gravity=*/1, - /*with_star_formation=*/0, talking, + /*with_star_formation=*/0, with_DM_background_particles, talking, /*dry_run=*/0); if (myrank == 0) { @@ -501,6 +521,12 @@ int main(int argc, char *argv[]) { fflush(stdout); } + /* Initialise the gravity scheme */ + bzero(&gravity_properties, sizeof(struct gravity_props)); + gravity_props_init(&gravity_properties, params, &prog_const, &cosmo, + /*with_cosmology=*/1, with_baryon_particles, + with_DM_particles, with_DM_background_particles, periodic); + /* Initialise the long-range gravity mesh */ if (periodic) { #ifdef HAVE_FFTW @@ -513,17 +539,22 @@ int main(int argc, char *argv[]) { pm_mesh_init_no_mesh(&mesh, s.dim); } - /* Also update the total counts (in case of changes due to replication) */ + /* Also update the total counts (in case of changes due to replication) */ + Nbaryons = s.nr_parts + s.nr_sparts + s.nr_bparts; #if defined(WITH_MPI) - N_long[0] = s.nr_parts; - N_long[1] = s.nr_gparts; - N_long[2] = s.nr_sparts; - MPI_Allreduce(&N_long, &N_total, 3, MPI_LONG_LONG_INT, MPI_SUM, - MPI_COMM_WORLD); + N_long[swift_type_gas] = s.nr_parts; + N_long[swift_type_dark_matter] = s.nr_gparts - Ngpart_background - Nbaryons; + N_long[swift_type_count] = s.nr_gparts; + N_long[swift_type_stars] = s.nr_sparts; + N_long[swift_type_black_hole] = s.nr_bparts; + MPI_Allreduce(&N_long, &N_total, swift_type_count + 1, MPI_LONG_LONG_INT, + MPI_SUM, MPI_COMM_WORLD); #else - N_total[0] = s.nr_parts; - N_total[1] = s.nr_gparts; - N_total[2] = s.nr_sparts; + N_total[swift_type_gas] = s.nr_parts; + N_total[swift_type_dark_matter] = s.nr_gparts - Ngpart_background - Nbaryons; + N_total[swift_type_count] = s.nr_gparts; + N_total[swift_type_stars] = s.nr_sparts; + N_total[swift_type_black_hole] = s.nr_bparts; #endif /* Say a few nice things about the space we just created. */ @@ -548,14 +579,16 @@ int main(int argc, char *argv[]) { /* Initialize the engine with the space and policies. */ if (myrank == 0) clocks_gettime(&tic); - engine_init(&e, &s, params, N_total[0], N_total[1], N_total[2], N_total[3], - engine_policies, talking, &reparttype, &us, &prog_const, &cosmo, - /*hydro_properties=*/NULL, /*entropy_floor=*/NULL, - &gravity_properties, - /*stars_properties=*/NULL, /*black_holes_properties=*/NULL, - /*feedback_properties=*/NULL, &mesh, /*potential=*/NULL, - /*cooling_func=*/NULL, - /*starform=*/NULL, /*chemistry=*/NULL, &fof_properties); + engine_init( + &e, &s, params, N_total[swift_type_gas], N_total[swift_type_count], + N_total[swift_type_stars], N_total[swift_type_black_hole], + N_total[swift_type_dark_matter_background], engine_policies, talking, + &reparttype, &us, &prog_const, &cosmo, + /*hydro_properties=*/NULL, /*entropy_floor=*/NULL, &gravity_properties, + /*stars_properties=*/NULL, /*black_holes_properties=*/NULL, + /*feedback_properties=*/NULL, &mesh, /*potential=*/NULL, + /*cooling_func=*/NULL, + /*starform=*/NULL, /*chemistry=*/NULL, &fof_properties); engine_config(/*restart=*/0, /*fof=*/1, &e, params, nr_nodes, myrank, nr_threads, with_aff, talking, NULL); @@ -568,12 +601,13 @@ int main(int argc, char *argv[]) { /* Get some info to the user. */ if (myrank == 0) { - long long N_DM = N_total[1] - N_total[2] - N_total[3] - N_total[0]; + const long long N_DM = N_total[swift_type_dark_matter] + + N_total[swift_type_dark_matter_background]; message( - "Running on %lld gas particles, %lld stars particles %lld black " + "Running FOF on %lld gas particles, %lld stars particles %lld black " "hole particles and %lld DM particles (%lld gravity particles)", - N_total[0], N_total[2], N_total[3], N_total[1] > 0 ? N_DM : 0, - N_total[1]); + N_total[swift_type_gas], N_total[swift_type_stars], + N_total[swift_type_black_hole], N_DM, N_total[swift_type_count]); message( "from t=%.3e until t=%.3e with %d ranks, %d threads / rank and %d " "task queues / rank (dt_min=%.3e, dt_max=%.3e)...", diff --git a/examples/nIFTyCluster/Baryonic/clean.sh b/examples/nIFTyCluster/Baryonic/clean.sh old mode 100644 new mode 100755 diff --git a/examples/nIFTyCluster/Baryonic/create_ics.sh b/examples/nIFTyCluster/Baryonic/create_ics.sh old mode 100644 new mode 100755 diff --git a/examples/nIFTyCluster/Baryonic/getIC.sh b/examples/nIFTyCluster/Baryonic/getIC.sh old mode 100644 new mode 100755 diff --git a/examples/nIFTyCluster/Baryonic/nifty.yml b/examples/nIFTyCluster/Baryonic/nifty.yml index d79d6853a59722a19b740b125d21883c2c06aa2b..d520d5bfba6ca466c30a0bd234a5457d7edd8fdf 100644 --- a/examples/nIFTyCluster/Baryonic/nifty.yml +++ b/examples/nIFTyCluster/Baryonic/nifty.yml @@ -37,13 +37,14 @@ Statistics: # Parameters for the self-gravity scheme Gravity: - eta: 0.025 # Constant dimensionless multiplier for time integration. - theta: 0.7 # Opening angle (Multipole acceptance criterion) - comoving_softening: 20.0 # Comoving softening length (in internal units). - max_physical_softening: 5.0 # Physical softening length (in internal units). - mesh_side_length: 512 - softening_ratio: 0.04 # 1/25 - softening_ratio_background: 0.04 # 1/25 + eta: 0.025 # Constant dimensionless multiplier for time integration. + theta: 0.5 # Opening angle (Multipole acceptance criterion) + comoving_DM_softening: 20.0 # Comoving softening length (in internal units). + comoving_baryon_softening: 20.0 # Comoving softening length (in internal units). + max_physical_DM_softening: 5.0 # Max physical softening length (in internal units). + max_physical_baryon_softening: 5.0 # Max physical softening length (in internal units). + softening_ratio_background: 0.04 # 1/25th of mean inter-particle separation + mesh_side_length: 512 # Parameters for the hydrodynamics scheme SPH: diff --git a/examples/nIFTyCluster/Baryonic/run.sh b/examples/nIFTyCluster/Baryonic/run.sh old mode 100644 new mode 100755 diff --git a/examples/nIFTyCluster/Baryonic/setup.sh b/examples/nIFTyCluster/Baryonic/setup.sh old mode 100644 new mode 100755 diff --git a/examples/parameter_example.yml b/examples/parameter_example.yml index aabf9ac1078ad41288f1011d7bfe94626deefce3..7d8a5886ebcde64a39defa24b9f1e9fbd2232642 100644 --- a/examples/parameter_example.yml +++ b/examples/parameter_example.yml @@ -21,7 +21,7 @@ Cosmology: 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_b: 0.0482519 # 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. @@ -58,15 +58,18 @@ Stars: # Parameters for the self-gravity scheme Gravity: - mesh_side_length: 32 # Number of cells along each axis for the periodic gravity mesh. - eta: 0.025 # Constant dimensionless multiplier for time integration. - theta: 0.7 # Opening angle (Multipole acceptance criterion). - comoving_softening: 0.0026994 # Comoving softening length (in internal units). - max_physical_softening: 0.0007 # Physical softening length (in internal units). - rebuild_frequency: 0.01 # (Optional) Frequency of the gravity-tree rebuild in units of the number of g-particles (this is the default value). - 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). + mesh_side_length: 32 # Number of cells along each axis for the periodic gravity mesh. + eta: 0.025 # Constant dimensionless multiplier for time integration. + theta: 0.7 # Opening angle (Multipole acceptance criterion). + comoving_DM_softening: 0.0026994 # Comoving Plummer-equivalent softening length for DM particles (in internal units). + max_physical_DM_softening: 0.0007 # Maximal Plummer-equivalent softening length in physical coordinates for DM particles (in internal units). + comoving_baryon_softening: 0.0026994 # Comoving Plummer-equivalent softening length for baryon particles (in internal units). + max_physical_baryon_softening: 0.0007 # Maximal Plummer-equivalent softening length in physical coordinates for baryon particles (in internal units). + softening_ratio_background: 0.04 # Fraction of the mean inter-particle separation to use as Plummer-equivalent softening for the background DM particles. + rebuild_frequency: 0.01 # (Optional) Frequency of the gravity-tree rebuild in units of the number of g-particles (this is the default value). + 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). # Parameters for the Friends-Of-Friends algorithm FOF: diff --git a/src/black_holes/EAGLE/black_holes_iact.h b/src/black_holes/EAGLE/black_holes_iact.h index 7e9852dee582ab49643368c0a7b0d79ecd6b5047..3e2238dc2a05f73dc9020b66f754e26a5976572a 100644 --- a/src/black_holes/EAGLE/black_holes_iact.h +++ b/src/black_holes/EAGLE/black_holes_iact.h @@ -145,7 +145,7 @@ runner_iact_nonsym_bh_gas_swallow( const float max_dist_repos2 = kernel_gravity_softening_plummer_equivalent_inv * kernel_gravity_softening_plummer_equivalent_inv * 9.f * - grav_props->epsilon_cur2; + grav_props->epsilon_baryon_cur * grav_props->epsilon_baryon_cur; /* This gas neighbour is close enough that we can consider it's potential for repositioning */ @@ -250,7 +250,7 @@ runner_iact_nonsym_bh_bh_swallow(const float r2, const float *dx, const float max_dist_repos2 = kernel_gravity_softening_plummer_equivalent_inv * kernel_gravity_softening_plummer_equivalent_inv * 9.f * - grav_props->epsilon_cur2; + grav_props->epsilon_baryon_cur * grav_props->epsilon_baryon_cur; /* This gas neighbour is close enough that we can consider it's potential for repositioning */ @@ -285,7 +285,7 @@ runner_iact_nonsym_bh_bh_swallow(const float r2, const float *dx, const float max_dist_merge2 = kernel_gravity_softening_plummer_equivalent_inv * kernel_gravity_softening_plummer_equivalent_inv * 9.f * - grav_props->epsilon_cur2; + grav_props->epsilon_baryon_cur * grav_props->epsilon_baryon_cur; const float G_Newton = grav_props->G_Newton; diff --git a/src/black_holes/EAGLE/black_holes_part.h b/src/black_holes/EAGLE/black_holes_part.h index cbfa0fcaf560d1c771d8595ec84ad08e9ba3608e..4d8a9c8e177cc64d7e3191c046ff95c374b2d4a4 100644 --- a/src/black_holes/EAGLE/black_holes_part.h +++ b/src/black_holes/EAGLE/black_holes_part.h @@ -19,6 +19,7 @@ #ifndef SWIFT_EAGLE_BLACK_HOLE_PART_H #define SWIFT_EAGLE_BLACK_HOLE_PART_H +#include "black_holes_struct.h" #include "chemistry_struct.h" #include "timeline.h" diff --git a/src/black_holes/EAGLE/black_holes_struct.h b/src/black_holes/EAGLE/black_holes_struct.h index 98f5380e9f32ced36bcf2e4e3f02eaeb89db7218..177a54b921bec24f357756e4f777b0ecf1781c30 100644 --- a/src/black_holes/EAGLE/black_holes_struct.h +++ b/src/black_holes/EAGLE/black_holes_struct.h @@ -19,6 +19,8 @@ #ifndef SWIFT_BLACK_HOLES_STRUCT_EAGLE_H #define SWIFT_BLACK_HOLES_STRUCT_EAGLE_H +#include "inline.h" + /** * @brief Black holes-related fields carried by each *gas* particle. */ diff --git a/src/cell.c b/src/cell.c index f2b38ee1a7d084a17a8e296f18136309136564a8..4b9746e92e31f2a5ae6c4b5d01ade8d83939e412 100644 --- a/src/cell.c +++ b/src/cell.c @@ -2178,8 +2178,11 @@ void cell_reset_task_counters(struct cell *c) { * * @param c The #cell. * @param ti_current The current integer time. + * @param grav_props The properties of the gravity scheme. */ -void cell_make_multipoles(struct cell *c, integertime_t ti_current) { +void cell_make_multipoles(struct cell *c, integertime_t ti_current, + const struct gravity_props *const grav_props) { + /* Reset everything */ gravity_reset(c->grav.multipole); @@ -2187,7 +2190,7 @@ void cell_make_multipoles(struct cell *c, integertime_t ti_current) { /* Start by recursing */ for (int k = 0; k < 8; ++k) { if (c->progeny[k] != NULL) - cell_make_multipoles(c->progeny[k], ti_current); + cell_make_multipoles(c->progeny[k], ti_current, grav_props); } /* Compute CoM of all progenies */ @@ -2248,7 +2251,7 @@ void cell_make_multipoles(struct cell *c, integertime_t ti_current) { } else { if (c->grav.count > 0) { - gravity_P2M(c->grav.multipole, c->grav.parts, c->grav.count); + gravity_P2M(c->grav.multipole, c->grav.parts, c->grav.count, grav_props); const double dx = c->grav.multipole->CoM[0] > c->loc[0] + c->width[0] * 0.5 ? c->grav.multipole->CoM[0] - c->loc[0] @@ -2324,8 +2327,11 @@ void cell_check_foreign_multipole(const struct cell *c) { * recursively computed one. * * @param c Cell to act upon + * @param grav_props The properties of the gravity scheme. */ -void cell_check_multipole(struct cell *c) { +void cell_check_multipole(struct cell *c, + const struct gravity_props *const grav_props) { + #ifdef SWIFT_DEBUG_CHECKS struct gravity_tensors ma; const double tolerance = 1e-3; /* Relative */ @@ -2333,11 +2339,12 @@ void cell_check_multipole(struct cell *c) { /* First recurse */ if (c->split) for (int k = 0; k < 8; k++) - if (c->progeny[k] != NULL) cell_check_multipole(c->progeny[k]); + if (c->progeny[k] != NULL) + cell_check_multipole(c->progeny[k], grav_props); if (c->grav.count > 0) { /* Brute-force calculation */ - gravity_P2M(&ma, c->grav.parts, c->grav.count); + gravity_P2M(&ma, c->grav.parts, c->grav.count, grav_props); /* Now compare the multipole expansion */ if (!gravity_multipole_equal(&ma, c->grav.multipole, tolerance)) { @@ -5450,6 +5457,9 @@ void cell_remove_gpart(const struct engine *e, struct cell *c, if (c->nodeID != e->nodeID) error("Can't remove a particle in a foreign cell."); + if (gp->type == swift_type_dark_matter_background) + error("Can't remove a DM background particle!"); + /* Mark the particle as inhibited */ gp->time_bin = time_bin_inhibited; @@ -5900,7 +5910,11 @@ int cell_can_use_pair_mm(const struct cell *ci, const struct cell *cj, } const double r2 = dx * dx + dy * dy + dz * dz; - return gravity_M2L_accept(multi_i->r_max, multi_j->r_max, theta_crit2, r2); + const double epsilon_i = multi_i->m_pole.max_softening; + const double epsilon_j = multi_j->m_pole.max_softening; + + return gravity_M2L_accept(multi_i->r_max, multi_j->r_max, theta_crit2, r2, + epsilon_i, epsilon_j); } /** @@ -5962,6 +5976,9 @@ int cell_can_use_pair_mm_rebuild(const struct cell *ci, const struct cell *cj, } const double r2 = dx * dx + dy * dy + dz * dz; + const double epsilon_i = multi_i->m_pole.max_softening; + const double epsilon_j = multi_j->m_pole.max_softening; + return gravity_M2L_accept(multi_i->r_max_rebuild, multi_j->r_max_rebuild, - theta_crit2, r2); + theta_crit2, r2, epsilon_i, epsilon_j); } diff --git a/src/cell.h b/src/cell.h index 830b281b5a3766f4842ea8cd8276f41a8ef00b66..8067a3189818ab8738de848ea698fbf25c78ebba 100644 --- a/src/cell.h +++ b/src/cell.h @@ -854,8 +854,10 @@ int cell_link_foreign_gparts(struct cell *c, struct gpart *gparts); int cell_count_parts_for_tasks(const struct cell *c); int cell_count_gparts_for_tasks(const struct cell *c); void cell_clean_links(struct cell *c, void *data); -void cell_make_multipoles(struct cell *c, integertime_t ti_current); -void cell_check_multipole(struct cell *c); +void cell_make_multipoles(struct cell *c, integertime_t ti_current, + const struct gravity_props *const grav_props); +void cell_check_multipole(struct cell *c, + const struct gravity_props *const grav_props); void cell_check_foreign_multipole(const struct cell *c); void cell_clean(struct cell *c); void cell_check_part_drift_point(struct cell *c, void *data); diff --git a/src/common_io.c b/src/common_io.c index 945badd14cb814e5c06c5e0edf2b983669259850..6f090ee01d1c870408223f90dba0770b5f76f567 100644 --- a/src/common_io.c +++ b/src/common_io.c @@ -24,7 +24,7 @@ /* This object's header. */ #include "common_io.h" -/* First common header */ +/* Pre-inclusion as needed in other headers */ #include "engine.h" /* Local includes. */ @@ -422,6 +422,21 @@ static long long cell_count_non_inhibited_dark_matter(const struct cell* c) { return count; } +static long long cell_count_non_inhibited_background_dark_matter( + const struct cell* c) { + const int total_count = c->grav.count; + struct gpart* gparts = c->grav.parts; + long long count = 0; + for (int i = 0; i < total_count; ++i) { + if ((gparts[i].time_bin != time_bin_inhibited) && + (gparts[i].time_bin != time_bin_not_created) && + (gparts[i].type == swift_type_dark_matter_background)) { + ++count; + } + } + return count; +} + static long long cell_count_non_inhibited_stars(const struct cell* c) { const int total_count = c->stars.count; struct spart* sparts = c->stars.parts; @@ -463,30 +478,36 @@ void io_write_cell_offsets(hid_t h_grp, const int cdim[3], centres = (double*)malloc(3 * nr_cells * sizeof(double)); /* Count of particles in each cell */ - long long *count_part = NULL, *count_gpart = NULL, *count_spart = NULL, + long long *count_part = NULL, *count_gpart = NULL, + *count_background_gpart = NULL, *count_spart = NULL, *count_bpart = NULL; count_part = (long long*)malloc(nr_cells * sizeof(long long)); count_gpart = (long long*)malloc(nr_cells * sizeof(long long)); + count_background_gpart = (long long*)malloc(nr_cells * sizeof(long long)); count_spart = (long long*)malloc(nr_cells * sizeof(long long)); count_bpart = (long long*)malloc(nr_cells * sizeof(long long)); /* Global offsets of particles in each cell */ - long long *offset_part = NULL, *offset_gpart = NULL, *offset_spart = NULL, + long long *offset_part = NULL, *offset_gpart = NULL, + *offset_background_gpart = NULL, *offset_spart = NULL, *offset_bpart = NULL; offset_part = (long long*)malloc(nr_cells * sizeof(long long)); offset_gpart = (long long*)malloc(nr_cells * sizeof(long long)); + offset_background_gpart = (long long*)malloc(nr_cells * sizeof(long long)); offset_spart = (long long*)malloc(nr_cells * sizeof(long long)); offset_bpart = (long long*)malloc(nr_cells * sizeof(long long)); /* Offsets of the 0^th element */ offset_part[0] = 0; offset_gpart[0] = 0; + offset_background_gpart[0] = 0; offset_spart[0] = 0; offset_bpart[0] = 0; /* Collect the cell information of *local* cells */ long long local_offset_part = 0; long long local_offset_gpart = 0; + long long local_offset_background_gpart = 0; long long local_offset_spart = 0; long long local_offset_bpart = 0; for (int i = 0; i < nr_cells; ++i) { @@ -501,6 +522,8 @@ void io_write_cell_offsets(hid_t h_grp, const int cdim[3], /* Count real particles that will be written */ count_part[i] = cell_count_non_inhibited_gas(&cells_top[i]); count_gpart[i] = cell_count_non_inhibited_dark_matter(&cells_top[i]); + count_background_gpart[i] = + cell_count_non_inhibited_background_dark_matter(&cells_top[i]); count_spart[i] = cell_count_non_inhibited_stars(&cells_top[i]); count_bpart[i] = cell_count_non_inhibited_black_holes(&cells_top[i]); @@ -509,12 +532,16 @@ void io_write_cell_offsets(hid_t h_grp, const int cdim[3], offset_part[i] = local_offset_part + global_offsets[swift_type_gas]; offset_gpart[i] = local_offset_gpart + global_offsets[swift_type_dark_matter]; + offset_background_gpart[i] = + local_offset_background_gpart + + global_offsets[swift_type_dark_matter_background]; offset_spart[i] = local_offset_spart + global_offsets[swift_type_stars]; offset_bpart[i] = local_offset_bpart + global_offsets[swift_type_black_hole]; local_offset_part += count_part[i]; local_offset_gpart += count_gpart[i]; + local_offset_background_gpart += count_background_gpart[i]; local_offset_spart += count_spart[i]; local_offset_bpart += count_bpart[i]; @@ -528,11 +555,13 @@ void io_write_cell_offsets(hid_t h_grp, const int cdim[3], count_part[i] = 0; count_gpart[i] = 0; + count_background_gpart[i] = 0; count_spart[i] = 0; count_bpart[i] = 0; offset_part[i] = 0; offset_gpart[i] = 0; + offset_background_gpart[i] = 0; offset_spart[i] = 0; offset_bpart[i] = 0; } @@ -548,7 +577,6 @@ void io_write_cell_offsets(hid_t h_grp, const int cdim[3], MPI_Reduce(count_part, NULL, nr_cells, MPI_LONG_LONG_INT, MPI_BOR, 0, MPI_COMM_WORLD); } - if (nodeID == 0) { MPI_Reduce(MPI_IN_PLACE, count_gpart, nr_cells, MPI_LONG_LONG_INT, MPI_BOR, 0, MPI_COMM_WORLD); @@ -556,6 +584,13 @@ void io_write_cell_offsets(hid_t h_grp, const int cdim[3], MPI_Reduce(count_gpart, NULL, nr_cells, MPI_LONG_LONG_INT, MPI_BOR, 0, MPI_COMM_WORLD); } + if (nodeID == 0) { + MPI_Reduce(MPI_IN_PLACE, count_background_gpart, nr_cells, + MPI_LONG_LONG_INT, MPI_BOR, 0, MPI_COMM_WORLD); + } else { + MPI_Reduce(count_background_gpart, NULL, nr_cells, MPI_LONG_LONG_INT, + MPI_BOR, 0, MPI_COMM_WORLD); + } if (nodeID == 0) { MPI_Reduce(MPI_IN_PLACE, count_spart, nr_cells, MPI_LONG_LONG_INT, MPI_BOR, 0, MPI_COMM_WORLD); @@ -585,6 +620,13 @@ void io_write_cell_offsets(hid_t h_grp, const int cdim[3], MPI_Reduce(offset_gpart, NULL, nr_cells, MPI_LONG_LONG_INT, MPI_BOR, 0, MPI_COMM_WORLD); } + if (nodeID == 0) { + MPI_Reduce(MPI_IN_PLACE, offset_background_gpart, nr_cells, + MPI_LONG_LONG_INT, MPI_BOR, 0, MPI_COMM_WORLD); + } else { + MPI_Reduce(offset_background_gpart, NULL, nr_cells, MPI_LONG_LONG_INT, + MPI_BOR, 0, MPI_COMM_WORLD); + } if (nodeID == 0) { MPI_Reduce(MPI_IN_PLACE, offset_spart, nr_cells, MPI_LONG_LONG_INT, MPI_BOR, 0, MPI_COMM_WORLD); @@ -700,6 +742,28 @@ void io_write_cell_offsets(hid_t h_grp, const int cdim[3], H5Sclose(h_space); } + if (global_counts[swift_type_dark_matter_background] > 0) { + + shape[0] = nr_cells; + shape[1] = 1; + h_space = H5Screate(H5S_SIMPLE); + if (h_space < 0) + error("Error while creating data space for background DM offsets"); + h_err = H5Sset_extent_simple(h_space, 1, shape, shape); + if (h_err < 0) + error( + "Error while changing shape of background DM offsets data space."); + h_data = H5Dcreate(h_subgrp, "PartType2", io_hdf5_type(LONGLONG), h_space, + H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + if (h_data < 0) + error("Error while creating dataspace for background DM offsets."); + h_err = H5Dwrite(h_data, io_hdf5_type(LONGLONG), h_space, H5S_ALL, + H5P_DEFAULT, offset_background_gpart); + if (h_err < 0) error("Error while writing background DM offsets."); + H5Dclose(h_data); + H5Sclose(h_space); + } + if (global_counts[swift_type_stars] > 0) { shape[0] = nr_cells; @@ -786,6 +850,27 @@ void io_write_cell_offsets(hid_t h_grp, const int cdim[3], H5Sclose(h_space); } + if (global_counts[swift_type_dark_matter_background] > 0) { + + shape[0] = nr_cells; + shape[1] = 1; + h_space = H5Screate(H5S_SIMPLE); + if (h_space < 0) + error("Error while creating data space for background DM counts"); + h_err = H5Sset_extent_simple(h_space, 1, shape, shape); + if (h_err < 0) + error("Error while changing shape of background DM counts data space."); + h_data = H5Dcreate(h_subgrp, "PartType2", io_hdf5_type(LONGLONG), h_space, + H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + if (h_data < 0) + error("Error while creating dataspace for background DM counts."); + h_err = H5Dwrite(h_data, io_hdf5_type(LONGLONG), h_space, H5S_ALL, + H5P_DEFAULT, count_background_gpart); + if (h_err < 0) error("Error while writing background DM counts."); + H5Dclose(h_data); + H5Sclose(h_space); + } + if (global_counts[swift_type_stars] > 0) { shape[0] = nr_cells; @@ -834,10 +919,12 @@ void io_write_cell_offsets(hid_t h_grp, const int cdim[3], free(centres); free(count_part); free(count_gpart); + free(count_background_gpart); free(count_spart); free(count_bpart); free(offset_part); free(offset_gpart); + free(offset_background_gpart); free(offset_spart); free(offset_bpart); } @@ -1313,29 +1400,6 @@ void io_copy_temp_buffer(void* temp, const struct engine* e, threadpool_map((struct threadpool*)&e->threadpool, io_convert_gpart_f_mapper, temp_f, N, copySize, 0, (void*)&props); - } else if (props.convert_gpart_i != NULL) { - - /* Prepare some parameters */ - int* temp_i = (int*)temp; - props.start_temp_i = (int*)temp; - props.e = e; - - /* Copy the whole thing into a buffer */ - threadpool_map((struct threadpool*)&e->threadpool, - io_convert_gpart_i_mapper, temp_i, N, copySize, 0, - (void*)&props); - - } else if (props.convert_gpart_i != NULL) { - - /* Prepare some parameters */ - int* temp_i = (int*)temp; - props.start_temp_i = (int*)temp; - props.e = e; - - /* Copy the whole thing into a buffer */ - threadpool_map((struct threadpool*)&e->threadpool, - io_convert_gpart_i_mapper, temp_i, N, copySize, 0, - (void*)&props); } else if (props.convert_gpart_i != NULL) { @@ -1384,29 +1448,6 @@ void io_copy_temp_buffer(void* temp, const struct engine* e, threadpool_map((struct threadpool*)&e->threadpool, io_convert_spart_f_mapper, temp_f, N, copySize, 0, (void*)&props); - } else if (props.convert_spart_i != NULL) { - - /* Prepare some parameters */ - int* temp_i = (int*)temp; - props.start_temp_i = (int*)temp; - props.e = e; - - /* Copy the whole thing into a buffer */ - threadpool_map((struct threadpool*)&e->threadpool, - io_convert_spart_i_mapper, temp_i, N, copySize, 0, - (void*)&props); - - } else if (props.convert_spart_i != NULL) { - - /* Prepare some parameters */ - int* temp_i = (int*)temp; - props.start_temp_i = (int*)temp; - props.e = e; - - /* Copy the whole thing into a buffer */ - threadpool_map((struct threadpool*)&e->threadpool, - io_convert_spart_i_mapper, temp_i, N, copySize, 0, - (void*)&props); } else if (props.convert_spart_i != NULL) { @@ -1551,6 +1592,56 @@ void io_prepare_dm_gparts(struct threadpool* tp, struct gpart* const gparts, sizeof(struct gpart), 0, NULL); } +void io_prepare_dm_background_gparts_mapper(void* restrict data, int Ndm, + void* dummy) { + + struct gpart* restrict gparts = (struct gpart*)data; + + /* Let's give all these gparts a negative id */ + for (int i = 0; i < Ndm; ++i) { + + /* Negative ids are not allowed */ + if (gparts[i].id_or_neg_offset < 0) + error("Negative ID for DM particle %i: ID=%lld", i, + gparts[i].id_or_neg_offset); + + /* Set gpart type */ + gparts[i].type = swift_type_dark_matter_background; + } +} + +/** + * @brief Prepare the DM backgorund particles (in gparts) read in + * for the addition of the other particle types + * + * This function assumes that the DM particles are all at the start of the + * gparts array and that the background particles directly follow them. + * + * @param tp The current #threadpool. + * @param gparts The array of #gpart freshly read in. + * @param Ndm The number of DM particles read in. + */ +void io_prepare_dm_background_gparts(struct threadpool* tp, + struct gpart* const gparts, size_t Ndm) { + + threadpool_map(tp, io_prepare_dm_background_gparts_mapper, gparts, Ndm, + sizeof(struct gpart), 0, NULL); +} + +size_t io_count_dm_background_gparts(const struct gpart* const gparts, + const size_t Ndm) { + + swift_declare_aligned_ptr(const struct gpart, gparts_array, gparts, + gpart_align); + + size_t count = 0; + for (size_t i = 0; i < Ndm; ++i) { + if (gparts[i].type == swift_type_dark_matter_background) ++count; + } + + return count; +} + struct duplication_data { struct part* parts; @@ -1846,7 +1937,8 @@ void io_collect_bparts_to_write(const struct bpart* restrict bparts, } /** - * @brief Copy every non-inhibited DM #gpart into the gparts_written array. + * @brief Copy every non-inhibited regulat DM #gpart into the gparts_written + * array. * * @param gparts The array of #gpart containing all particles. * @param vr_data The array of gpart-related VELOCIraptor output. @@ -1888,6 +1980,50 @@ void io_collect_gparts_to_write( count, Ngparts_written); } +/** + * @brief Copy every non-inhibited background DM #gpart into the gparts_written + * array. + * + * @param gparts The array of #gpart containing all particles. + * @param vr_data The array of gpart-related VELOCIraptor output. + * @param gparts_written The array of #gpart to fill with particles we want to + * write. + * @param vr_data_written The array of gpart-related VELOCIraptor with particles + * we want to write. + * @param Ngparts The total number of #part. + * @param Ngparts_written The total number of #part to write. + * @param with_stf Are we running with STF? i.e. do we want to collect vr data? + */ +void io_collect_gparts_background_to_write( + const struct gpart* restrict gparts, + const struct velociraptor_gpart_data* restrict vr_data, + struct gpart* restrict gparts_written, + struct velociraptor_gpart_data* restrict vr_data_written, + const size_t Ngparts, const size_t Ngparts_written, const int with_stf) { + + size_t count = 0; + + /* Loop over all parts */ + for (size_t i = 0; i < Ngparts; ++i) { + + /* And collect the ones that have not been removed */ + if ((gparts[i].time_bin != time_bin_inhibited) && + (gparts[i].time_bin != time_bin_not_created) && + (gparts[i].type == swift_type_dark_matter_background)) { + + if (with_stf) vr_data_written[count] = vr_data[i]; + + gparts_written[count] = gparts[i]; + count++; + } + } + + /* Check that everything is fine */ + if (count != Ngparts_written) + error("Collected the wrong number of g-particles (%zu vs. %zu expected)", + count, Ngparts_written); +} + /** * @brief Verify the io parameter file * @@ -1895,11 +2031,7 @@ void io_collect_gparts_to_write( * @param N_total The total number of each particle type. */ void io_check_output_fields(const struct swift_params* params, - const long long N_total[3]) { - - /* Copy N_total to array with length == 6 */ - const long long nr_total[swift_type_count] = {N_total[0], N_total[1], 0, - 0, N_total[2], 0}; + const long long N_total[swift_type_count]) { /* Loop over all particle types to check the fields */ for (int ptype = 0; ptype < swift_type_count; ptype++) { @@ -1908,7 +2040,7 @@ void io_check_output_fields(const struct swift_params* params, struct io_props list[100]; /* Don't do anything if no particle of this kind */ - if (nr_total[ptype] == 0) continue; + if (N_total[ptype] == 0) continue; /* Gather particle fields from the particle structures */ switch (ptype) { @@ -1932,6 +2064,12 @@ void io_check_output_fields(const struct swift_params* params, num_fields += velociraptor_write_gparts(NULL, list + num_fields); break; + case swift_type_dark_matter_background: + darkmatter_write_particles(NULL, list, &num_fields); + num_fields += fof_write_gparts(NULL, list + num_fields); + num_fields += velociraptor_write_gparts(NULL, list + num_fields); + break; + case swift_type_stars: stars_write_particles(NULL, list, &num_fields, /*with_cosmology=*/1); num_fields += chemistry_write_sparticles(NULL, list + num_fields); @@ -2045,6 +2183,12 @@ void io_write_output_field_parameter(const char* filename) { num_fields += velociraptor_write_gparts(NULL, list + num_fields); break; + case swift_type_dark_matter_background: + darkmatter_write_particles(NULL, list, &num_fields); + num_fields += fof_write_gparts(NULL, list + num_fields); + num_fields += velociraptor_write_gparts(NULL, list + num_fields); + break; + case swift_type_stars: stars_write_particles(NULL, list, &num_fields, /*with_cosmology=*/1); num_fields += chemistry_write_sparticles(NULL, list + num_fields); diff --git a/src/common_io.h b/src/common_io.h index 03437d1a38a09e59e6abd4b9ca762f181ffc3731..aa4b0c552f8a416a4aa42ecce5e9ae0b74dbc731 100644 --- a/src/common_io.h +++ b/src/common_io.h @@ -125,8 +125,18 @@ void io_collect_gparts_to_write(const struct gpart* restrict gparts, struct velociraptor_gpart_data* vr_data_written, const size_t Ngparts, const size_t Ngparts_written, int with_stf); +void io_collect_gparts_background_to_write( + const struct gpart* restrict gparts, + const struct velociraptor_gpart_data* vr_data, + struct gpart* restrict gparts_written, + struct velociraptor_gpart_data* vr_data_written, const size_t Ngparts, + const size_t Ngparts_written, int with_stf); void io_prepare_dm_gparts(struct threadpool* tp, struct gpart* const gparts, size_t Ndm); +void io_prepare_dm_background_gparts(struct threadpool* tp, + struct gpart* const gparts, size_t Ndm); +size_t io_count_dm_background_gparts(const struct gpart* const gparts, + size_t Ndm); void io_duplicate_hydro_gparts(struct threadpool* tp, struct part* const parts, struct gpart* const gparts, size_t Ngas, size_t Ndm); diff --git a/src/debug.c b/src/debug.c index f8509af805fed90cbdbdfd58849cb7b6352062e9..8e3c581163bb404b8013790ef32549503c93fa38 100644 --- a/src/debug.c +++ b/src/debug.c @@ -73,6 +73,8 @@ #include "./gravity/Default/gravity_debug.h" #elif defined(POTENTIAL_GRAVITY) #include "./gravity/Potential/gravity_debug.h" +#elif defined(MULTI_SOFTENING_GRAVITY) +#include "./gravity/MultiSoftening/gravity_debug.h" #else #error "Invalid choice of gravity variant" #endif diff --git a/src/engine.c b/src/engine.c index c3ace9f9f7d237708f57f5ddfd575b11d3c62ed1..462f38ba4b95b7b6322964d91e19285eb618d48f 100644 --- a/src/engine.c +++ b/src/engine.c @@ -4201,7 +4201,7 @@ void engine_do_reconstruct_multipoles_mapper(void *map_data, int num_elements, if (c != NULL && c->nodeID == e->nodeID) { /* Construct the multipoles in this cell hierarchy */ - cell_make_multipoles(c, e->ti_current); + cell_make_multipoles(c, e->ti_current, e->gravity_properties); } } } @@ -4408,19 +4408,26 @@ void engine_makeproxies(struct engine *e) { sqrt(min_dist_centres2) - 2. * delta_CoM; const double min_dist_CoM2 = min_dist_CoM * min_dist_CoM; + /* We also assume that the softening is negligible compared + to the cell size */ + const double epsilon_i = 0.; + const double epsilon_j = 0.; + /* Are we beyond the distance where the truncated forces are 0 * but not too far such that M2L can be used? */ if (periodic) { if ((min_dist_CoM2 < max_mesh_dist2) && (!gravity_M2L_accept(r_max, r_max, theta_crit2, - min_dist_CoM2))) + min_dist_CoM2, epsilon_i, + epsilon_j))) proxy_type |= (int)proxy_cell_type_gravity; } else { if (!gravity_M2L_accept(r_max, r_max, theta_crit2, - min_dist_CoM2)) + min_dist_CoM2, epsilon_i, + epsilon_j)) proxy_type |= (int)proxy_cell_type_gravity; } } @@ -4883,6 +4890,7 @@ void engine_unpin(void) { * @param Ngparts total number of gravity particles in the simulation. * @param Nstars total number of star particles in the simulation. * @param Nblackholes total number of black holes in the simulation. + * @param Nbackground_gparts Total number of background DM particles. * @param policy The queuing policy to use. * @param verbose Is this #engine talkative ? * @param reparttype What type of repartition algorithm are we using ? @@ -4904,8 +4912,8 @@ void engine_unpin(void) { */ void engine_init(struct engine *e, struct space *s, struct swift_params *params, long long Ngas, long long Ngparts, long long Nstars, - long long Nblackholes, int policy, int verbose, - struct repartition *reparttype, + long long Nblackholes, long long Nbackground_gparts, + int policy, int verbose, struct repartition *reparttype, const struct unit_system *internal_units, const struct phys_const *physical_constants, struct cosmology *cosmo, struct hydro_props *hydro, @@ -4930,6 +4938,7 @@ void engine_init(struct engine *e, struct space *s, struct swift_params *params, e->total_nr_gparts = Ngparts; e->total_nr_sparts = Nstars; e->total_nr_bparts = Nblackholes; + e->total_nr_DM_background_gparts = Nbackground_gparts; e->proxy_ind = NULL; e->nr_proxies = 0; e->reparttype = reparttype; @@ -6155,11 +6164,17 @@ void engine_recompute_displacement_constraint(struct engine *e) { #endif /* Get the counts of each particle types */ + const long long total_nr_baryons = + e->total_nr_parts + e->total_nr_sparts + e->total_nr_bparts; const long long total_nr_dm_gparts = - e->total_nr_gparts - e->total_nr_parts - e->total_nr_sparts; + e->total_nr_gparts - e->total_nr_DM_background_gparts - total_nr_baryons; float count_parts[swift_type_count] = { - (float)e->total_nr_parts, (float)total_nr_dm_gparts, 0.f, 0.f, - (float)e->total_nr_sparts, (float)e->total_nr_bparts}; + (float)e->total_nr_parts, + (float)total_nr_dm_gparts, + (float)e->total_nr_DM_background_gparts, + 0.f, + (float)e->total_nr_sparts, + (float)e->total_nr_bparts}; /* Count of particles for the two species */ const float N_dm = count_parts[1]; @@ -6559,7 +6574,8 @@ void engine_fof(struct engine *e, const int dump_results, /* Compute number of DM particles */ const long long total_nr_baryons = e->total_nr_parts + e->total_nr_sparts + e->total_nr_bparts; - const long long total_nr_dmparts = e->total_nr_gparts - total_nr_baryons; + const long long total_nr_dmparts = + e->total_nr_gparts - e->total_nr_DM_background_gparts - total_nr_baryons; /* Initialise FOF parameters and allocate FOF arrays. */ fof_allocate(e->s, total_nr_dmparts, e->fof_properties); diff --git a/src/engine.h b/src/engine.h index dc5c2c9ddd9a843d3e677e9b56c47f7451515b2f..3c74f89dfcade93bb67d21eb6607cdd4cb80155d 100644 --- a/src/engine.h +++ b/src/engine.h @@ -248,6 +248,7 @@ struct engine { long long total_nr_gparts; long long total_nr_sparts; long long total_nr_bparts; + long long total_nr_DM_background_gparts; /* Total numbers of cells (top-level and sub-cells) in the system. */ long long total_nr_cells; @@ -493,8 +494,8 @@ void engine_dump_snapshot(struct engine *e); void engine_init_output_lists(struct engine *e, struct swift_params *params); void engine_init(struct engine *e, struct space *s, struct swift_params *params, long long Ngas, long long Ngparts, long long Nstars, - long long Nblackholes, int policy, int verbose, - struct repartition *reparttype, + long long Nblackholes, long long Nbackground_gparts, + int policy, int verbose, struct repartition *reparttype, const struct unit_system *internal_units, const struct phys_const *physical_constants, struct cosmology *cosmo, struct hydro_props *hydro, diff --git a/src/fof.c b/src/fof.c index c7c9323a3ed0e5c52cf09c2644c3754e6126a24f..af530af6aadfd8a8c1ea8529330156f84278a534 100644 --- a/src/fof.c +++ b/src/fof.c @@ -1956,14 +1956,14 @@ void fof_dump_group_data(const struct fof_props *props, : -1; #ifdef WITH_MPI fprintf(file, " %8zu %12zu %12e %12e %18lld %18lld\n", - gparts[group_offset - node_offset].fof_data.group_id, + (size_t)gparts[group_offset - node_offset].fof_data.group_id, group_size[group_offset - node_offset], group_mass[i], max_part_density[i], max_part_density_index[i], part_id); #else fprintf(file, " %8zu %12zu %12e %12e %18lld %18lld\n", - gparts[group_offset].fof_data.group_id, group_size[group_offset], - group_mass[i], max_part_density[i], max_part_density_index[i], - part_id); + (size_t)gparts[group_offset].fof_data.group_id, + group_size[group_offset], group_mass[i], max_part_density[i], + max_part_density_index[i], part_id); #endif } diff --git a/src/gravity.h b/src/gravity.h index 57cad8eba5f0772f85affd031a450c3ecb4dde59..4e255d2cbaaae012ab1282c82c8f6f15410e6b4b 100644 --- a/src/gravity.h +++ b/src/gravity.h @@ -34,6 +34,9 @@ #elif defined(POTENTIAL_GRAVITY) #include "./gravity/Potential/gravity.h" #define GRAVITY_IMPLEMENTATION "With potential calculation" +#elif defined(MULTI_SOFTENING_GRAVITY) +#include "./gravity/MultiSoftening/gravity.h" +#define GRAVITY_IMPLEMENTATION "With per-particle softening" #else #error "Invalid choice of gravity variant" #endif diff --git a/src/gravity/Default/gravity.h b/src/gravity/Default/gravity.h index 6d1270c952100f3a25202fcdb22be09f9acaa8d9..a8ace72d2b2bb8cb92d2d386ae3ed5402c4f76e0 100644 --- a/src/gravity/Default/gravity.h +++ b/src/gravity/Default/gravity.h @@ -42,13 +42,16 @@ __attribute__((always_inline)) INLINE static float gravity_get_mass( /** * @brief Returns the current co-moving softening of a particle * + * Note that in this basic gravity scheme, all particles have + * the same softening length. + * * @param gp The particle of interest * @param grav_props The global gravity properties. */ __attribute__((always_inline)) INLINE static float gravity_get_softening( const struct gpart* gp, const struct gravity_props* restrict grav_props) { - return grav_props->epsilon_cur; + return grav_props->epsilon_DM_cur; } /** diff --git a/src/gravity/Default/gravity_iact.h b/src/gravity/Default/gravity_iact.h index 6fce3ddd512018e9ea4be21111c75904c77cb925..4967b53d15d0c1888c77ef51265be31f571009cc 100644 --- a/src/gravity/Default/gravity_iact.h +++ b/src/gravity/Default/gravity_iact.h @@ -166,8 +166,8 @@ __attribute__((always_inline)) INLINE static void runner_iact_grav_pm_full( /* Compute the derivatives of the potential */ struct potential_derivatives_M2P d; - potential_derivatives_compute_M2P(r_x, r_y, r_z, r2, r_inv, h, h_inv, 0, 0.f, - &d); + potential_derivatives_compute_M2P(r_x, r_y, r_z, r2, r_inv, h, + /*periodic=*/0, /*r_s_inv=*/0.f, &d); /* 0th order contributions */ *f_x = m->M_000 * d.D_100; @@ -271,7 +271,7 @@ __attribute__((always_inline)) INLINE static void runner_iact_grav_pm_truncated( /* Compute the derivatives of the potential */ struct potential_derivatives_M2P d; - potential_derivatives_compute_M2P(r_x, r_y, r_z, r2, r_inv, h, h_inv, 1, + potential_derivatives_compute_M2P(r_x, r_y, r_z, r2, r_inv, h, /*periodic=*/1, r_s_inv, &d); /* 0th order contributions */ diff --git a/src/gravity/MultiSoftening/gravity.h b/src/gravity/MultiSoftening/gravity.h new file mode 100644 index 0000000000000000000000000000000000000000..08282a038dc67c2740e3d5e6ba95a5a5b8a190ff --- /dev/null +++ b/src/gravity/MultiSoftening/gravity.h @@ -0,0 +1,246 @@ +/******************************************************************************* + * This file is part of SWIFT. + * Coypright (c) 2015 Matthieu Schaller (matthieu.schaller@durham.ac.uk) + * 2016 Tom Theuns (tom.theuns@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/>. + * + ******************************************************************************/ +#ifndef SWIFT_MULTI_SOFTENING_GRAVITY_H +#define SWIFT_MULIT_SOFTENING_GRAVITY_H + +#include <float.h> + +/* Local includes. */ +#include "cosmology.h" +#include "gravity_properties.h" +#include "kernel_gravity.h" +#include "minmax.h" + +/** + * @brief Returns the mass of a particle + * + * @param gp The particle of interest + */ +__attribute__((always_inline)) INLINE static float gravity_get_mass( + const struct gpart* restrict gp) { + + return gp->mass; +} + +/** + * @brief Returns the current co-moving softening of a particle + * + * @param gp The particle of interest + * @param grav_props The global gravity properties. + */ +__attribute__((always_inline)) INLINE static float gravity_get_softening( + const struct gpart* gp, const struct gravity_props* restrict grav_props) { + + switch (gp->type) { + case swift_type_dark_matter: + return grav_props->epsilon_DM_cur; + case swift_type_stars: + return grav_props->epsilon_baryon_cur; + case swift_type_gas: + return grav_props->epsilon_baryon_cur; + case swift_type_black_hole: + return grav_props->epsilon_baryon_cur; + case swift_type_dark_matter_background: + return grav_props->epsilon_background_fac * cbrtf(gp->mass); + default: + return 0.f; + } +} + +/** + * @brief Add a contribution to this particle's potential. + * + * @param gp The particle. + * @param pot The contribution to add. + */ +__attribute__((always_inline)) INLINE static void +gravity_add_comoving_potential(struct gpart* restrict gp, float pot) { + + gp->potential += pot; +} + +/** + * @brief Returns the comoving potential of a particle. + * + * @param gp The particle of interest + */ +__attribute__((always_inline)) INLINE static float +gravity_get_comoving_potential(const struct gpart* restrict gp) { + + return gp->potential; +} + +/** + * @brief Returns the physical potential of a particle + * + * @param gp The particle of interest. + * @param cosmo The cosmological model. + */ +__attribute__((always_inline)) INLINE static float +gravity_get_physical_potential(const struct gpart* restrict gp, + const struct cosmology* cosmo) { + + return gp->potential * cosmo->a_inv; +} + +/** + * @brief Computes the gravity time-step of a given particle due to self-gravity + * + * We use Gadget-2's type 0 time-step criterion. + * + * @param gp Pointer to the g-particle data. + * @param a_hydro The accelerations coming from the hydro scheme (can be 0). + * @param grav_props Constants used in the gravity scheme. + * @param cosmo The current cosmological model. + */ +__attribute__((always_inline)) INLINE static float +gravity_compute_timestep_self(const struct gpart* const gp, + const float a_hydro[3], + const struct gravity_props* restrict grav_props, + const struct cosmology* cosmo) { + + /* Get physical acceleration (gravity contribution) */ + float a_phys_x = gp->a_grav[0] * cosmo->a_factor_grav_accel; + float a_phys_y = gp->a_grav[1] * cosmo->a_factor_grav_accel; + float a_phys_z = gp->a_grav[2] * cosmo->a_factor_grav_accel; + + /* Get physical acceleration (hydro contribution) */ + a_phys_x += a_hydro[0] * cosmo->a_factor_hydro_accel; + a_phys_y += a_hydro[1] * cosmo->a_factor_hydro_accel; + a_phys_z += a_hydro[2] * cosmo->a_factor_hydro_accel; + + const float ac2 = + a_phys_x * a_phys_x + a_phys_y * a_phys_y + a_phys_z * a_phys_z; + + const float ac_inv = (ac2 > 0.f) ? 1.f / sqrtf(ac2) : FLT_MAX; + + const float epsilon = gravity_get_softening(gp, grav_props); + + const float dt = sqrtf(2. * kernel_gravity_softening_plummer_equivalent_inv * + cosmo->a * grav_props->eta * epsilon * ac_inv); + + return dt; +} + +/** + * @brief Prepares a g-particle for the gravity calculation + * + * Zeroes all the relevant arrays in preparation for the sums taking place in + * the variaous tasks + * + * @param gp The particle to act upon + */ +__attribute__((always_inline)) INLINE static void gravity_init_gpart( + struct gpart* gp) { + + /* Zero the acceleration */ + gp->a_grav[0] = 0.f; + gp->a_grav[1] = 0.f; + gp->a_grav[2] = 0.f; + gp->potential = 0.f; + +#ifdef SWIFT_GRAVITY_FORCE_CHECKS + gp->potential_PM = 0.f; + gp->a_grav_PM[0] = 0.f; + gp->a_grav_PM[1] = 0.f; + gp->a_grav_PM[2] = 0.f; +#endif + +#ifdef SWIFT_DEBUG_CHECKS + gp->num_interacted = 0; + gp->initialised = 1; +#endif +} + +/** + * @brief Finishes the gravity calculation. + * + * Multiplies the forces and accelerations by the appropiate constants. + * Applies cosmological correction for periodic BCs. + * + * No need to apply the potential normalisation correction for periodic + * BCs here since we do not compute the potential. + * + * @param gp The particle to act upon + * @param const_G Newton's constant in internal units. + * @param potential_normalisation Term to be added to all the particles. + * @param periodic Are we using periodic BCs? + */ +__attribute__((always_inline)) INLINE static void gravity_end_force( + struct gpart* gp, float const_G, const float potential_normalisation, + const int periodic) { + + /* Apply the periodic correction to the peculiar potential */ + if (periodic) gp->potential += potential_normalisation; + + /* Let's get physical... */ + gp->a_grav[0] *= const_G; + gp->a_grav[1] *= const_G; + gp->a_grav[2] *= const_G; + gp->potential *= const_G; + +#ifdef SWIFT_GRAVITY_FORCE_CHECKS + gp->potential_PM *= const_G; + gp->a_grav_PM[0] *= const_G; + gp->a_grav_PM[1] *= const_G; + gp->a_grav_PM[2] *= const_G; +#endif + +#ifdef SWIFT_DEBUG_CHECKS + gp->initialised = 0; /* Ready for next step */ +#endif +} + +/** + * @brief Kick the additional variables + * + * @param gp The particle to act upon + * @param dt The time-step for this kick + */ +__attribute__((always_inline)) INLINE static void gravity_kick_extra( + struct gpart* gp, float dt) {} + +/** + * @brief Sets the values to be predicted in the drifts to their values at a + * kick time + * + * @param gp The particle. + */ +__attribute__((always_inline)) INLINE static void +gravity_reset_predicted_values(struct gpart* gp) {} + +/** + * @brief Initialises the g-particles for the first time + * + * This function is called only once just after the ICs have been + * read in to do some conversions. + * + * @param gp The particle to act upon + * @param grav_props The global properties of the gravity calculation. + */ +__attribute__((always_inline)) INLINE static void gravity_first_init_gpart( + struct gpart* gp, const struct gravity_props* grav_props) { + + gp->time_bin = 0; + + gravity_init_gpart(gp); +} + +#endif /* SWIFT_MULTI_SOFTENING_GRAVITY_H */ diff --git a/src/gravity/MultiSoftening/gravity_debug.h b/src/gravity/MultiSoftening/gravity_debug.h new file mode 100644 index 0000000000000000000000000000000000000000..7deea93f385d77871ed4bb28b881d7e93ce59436 --- /dev/null +++ b/src/gravity/MultiSoftening/gravity_debug.h @@ -0,0 +1,37 @@ +/******************************************************************************* + * This file is part of SWIFT. + * Coypright (c) 2016 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/>. + * + ******************************************************************************/ +#ifndef SWIFT_MULTI_SOFTENING_GRAVITY_DEBUG_H +#define SWIFT_MULTI_SOFTENING_GRAVITY_DEBUG_H + +__attribute__((always_inline)) INLINE static void gravity_debug_particle( + const struct gpart* p) { + printf( + "mass=%.3e time_bin=%d\n" + "x=[%.5e,%.5e,%.5e], v_full=[%.5e,%.5e,%.5e], type=%d, " + "a=[%.5e,%.5e,%.5e], pot=%.5e\n", + p->mass, p->time_bin, p->x[0], p->x[1], p->x[2], p->v_full[0], + p->v_full[1], p->v_full[2], (int)p->type, p->a_grav[0], p->a_grav[1], + p->a_grav[2], p->potential); +#ifdef SWIFT_DEBUG_CHECKS + printf("num_interacted=%lld ti_drift=%lld ti_kick=%lld\n", p->num_interacted, + p->ti_drift, p->ti_kick); +#endif +} + +#endif /* SWIFT_MULTI_SOFTENING_GRAVITY_DEBUG_H */ diff --git a/src/gravity/MultiSoftening/gravity_iact.h b/src/gravity/MultiSoftening/gravity_iact.h new file mode 100644 index 0000000000000000000000000000000000000000..8ab3a390010d2a2f72d0a056e399f7720e5dc464 --- /dev/null +++ b/src/gravity/MultiSoftening/gravity_iact.h @@ -0,0 +1,350 @@ +/******************************************************************************* + * This file is part of SWIFT. + * Copyright (c) 2013 Pedro Gonnet (pedro.gonnet@durham.ac.uk) + * 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/>. + * + ******************************************************************************/ +#ifndef SWIFT_MULTI_SOFTENING_GRAVITY_IACT_H +#define SWIFT_MULTI_SOFTENING_GRAVITY_IACT_H + +/* Includes. */ +#include "kernel_gravity.h" +#include "kernel_long_gravity.h" +#include "multipole.h" + +/* Standard headers */ +#include <float.h> + +/** + * @brief Computes the intensity of the force at a point generated by a + * point-mass. + * + * The returned quantity needs to be multiplied by the distance vector to obtain + * the force vector. + * + * @param r2 Square of the distance to the point-mass. + * @param h2 Square of the softening length. + * @param h_inv Inverse of the softening length. + * @param h_inv3 Cube of the inverse of the softening length. + * @param mass Mass of the point-mass. + * @param f_ij (return) The force intensity. + * @param pot_ij (return) The potential. + */ +__attribute__((always_inline)) INLINE static void runner_iact_grav_pp_full( + const float r2, const float h2, const float h_inv, const float h_inv3, + const float mass, float *f_ij, float *pot_ij) { + + /* Get the inverse distance */ + const float r_inv = 1.f / sqrtf(r2 + FLT_MIN); + + /* Should we soften ? */ + if (r2 >= h2) { + + /* Get Newtonian gravity */ + *f_ij = mass * r_inv * r_inv * r_inv; + *pot_ij = -mass * r_inv; + + } else { + + const float r = r2 * r_inv; + const float ui = r * h_inv; + + float W_f_ij, W_pot_ij; + kernel_grav_force_eval(ui, &W_f_ij); + kernel_grav_pot_eval(ui, &W_pot_ij); + + /* Get softened gravity */ + *f_ij = mass * h_inv3 * W_f_ij; + *pot_ij = mass * h_inv * W_pot_ij; + } +} + +/** + * @brief Computes the intensity of the force at a point generated by a + * point-mass truncated for long-distance periodicity. + * + * The returned quantity needs to be multiplied by the distance vector to obtain + * the force vector. + * + * @param r2 Square of the distance to the point-mass. + * @param h2 Square of the softening length. + * @param h_inv Inverse of the softening length. + * @param h_inv3 Cube of the inverse of the softening length. + * @param mass Mass of the point-mass. + * @param r_s_inv Inverse of the mesh smoothing scale. + * @param f_ij (return) The force intensity. + * @param pot_ij (return) The potential. + */ +__attribute__((always_inline)) INLINE static void runner_iact_grav_pp_truncated( + const float r2, const float h2, const float h_inv, const float h_inv3, + const float mass, const float r_s_inv, float *f_ij, float *pot_ij) { + + /* Get the inverse distance */ + const float r_inv = 1.f / sqrtf(r2 + FLT_MIN); + const float r = r2 * r_inv; + + /* Should we soften ? */ + if (r2 >= h2) { + + /* Get Newtonian gravity */ + *f_ij = mass * r_inv * r_inv * r_inv; + *pot_ij = -mass * r_inv; + + } else { + + const float ui = r * h_inv; + float W_f_ij, W_pot_ij; + + kernel_grav_force_eval(ui, &W_f_ij); + kernel_grav_pot_eval(ui, &W_pot_ij); + + /* Get softened gravity */ + *f_ij = mass * h_inv3 * W_f_ij; + *pot_ij = mass * h_inv * W_pot_ij; + } + + /* Get long-range correction */ + const float u_lr = r * r_s_inv; + float corr_f_lr, corr_pot_lr; + kernel_long_grav_force_eval(u_lr, &corr_f_lr); + kernel_long_grav_pot_eval(u_lr, &corr_pot_lr); + *f_ij *= corr_f_lr; + *pot_ij *= corr_pot_lr; +} + +/** + * @brief Computes the forces at a point generated by a multipole. + * + * This assumes M_100 == M_010 == M_001 == 0. + * This uses the quadrupole and trace of the octupole terms only and defaults to + * the monopole if the code is compiled with low-order gravity only. + * + * @param r_x x-component of the distance vector to the multipole. + * @param r_y y-component of the distance vector to the multipole. + * @param r_z z-component of the distance vector to the multipole. + * @param r2 Square of the distance vector to the multipole. + * @param h The softening length. + * @param h_inv Inverse of the softening length. + * @param m The multipole. + * @param f_x (return) The x-component of the acceleration. + * @param f_y (return) The y-component of the acceleration. + * @param f_z (return) The z-component of the acceleration. + * @param pot (return) The potential. + */ +__attribute__((always_inline)) INLINE static void runner_iact_grav_pm_full( + const float r_x, const float r_y, const float r_z, const float r2, + const float h, const float h_inv, const struct multipole *m, float *f_x, + float *f_y, float *f_z, float *pot) { + +/* In the case where the order is < 3, then there is only a monopole term left. + * We can default to the normal P-P interaction with the mass of the multipole + * and its CoM as the "particle" property */ +#if SELF_GRAVITY_MULTIPOLE_ORDER < 3 + + float f_ij, pot_ij; + runner_iact_grav_pp_full(r2, h * h, h_inv, h_inv * h_inv * h_inv, m->M_000, + &f_ij, &pot_ij); + *f_x = f_ij * r_x; + *f_y = f_ij * r_y; + *f_z = f_ij * r_z; + *pot = pot_ij; + +#else + + /* Get the inverse distance */ + const float r_inv = 1.f / sqrtf(r2); + + /* Compute the derivatives of the potential */ + struct potential_derivatives_M2P d; + potential_derivatives_compute_M2P(r_x, r_y, r_z, r2, r_inv, h, + /*periodic=*/0, /*r_s_inv=*/0.f, &d); + + /* 0th order contributions */ + *f_x = m->M_000 * d.D_100; + *f_y = m->M_000 * d.D_010; + *f_z = m->M_000 * d.D_001; + *pot = m->M_000 * d.D_000; + +#if SELF_GRAVITY_MULTIPOLE_ORDER > 1 + + /* 1st order contributions */ + + /* 1st order contributions are all 0 since the dipole is 0 */ + + /* *f_x = m->M_001 * d.D_101 + m->M_010 * d.D_110 + m->M_100 * d.D_200 ; */ + /* *f_y = m->M_001 * d.D_011 + m->M_010 * d.D_020 + m->M_100 * d.D_110 ; */ + /* *f_z = m->M_001 * d.D_002 + m->M_010 * d.D_011 + m->M_100 * d.D_101 ; */ + /* *pot = m->M_001 * d.D_001 + m->M_010 * d.D_010 + m->M_100 * d.D_100 ; */ + +#endif + +#if SELF_GRAVITY_MULTIPOLE_ORDER > 2 + + /* 2nd order contributions */ + *f_x += m->M_002 * d.D_102 + m->M_011 * d.D_111 + m->M_020 * d.D_120 + + m->M_101 * d.D_201 + m->M_110 * d.D_210 + m->M_200 * d.D_300; + *f_y += m->M_002 * d.D_012 + m->M_011 * d.D_021 + m->M_020 * d.D_030 + + m->M_101 * d.D_111 + m->M_110 * d.D_120 + m->M_200 * d.D_210; + *f_z += m->M_002 * d.D_003 + m->M_011 * d.D_012 + m->M_020 * d.D_021 + + m->M_101 * d.D_102 + m->M_110 * d.D_111 + m->M_200 * d.D_201; + *pot += m->M_002 * d.D_002 + m->M_011 * d.D_011 + m->M_020 * d.D_020 + + m->M_101 * d.D_101 + m->M_110 * d.D_110 + m->M_200 * d.D_200; + +#endif + +#if SELF_GRAVITY_MULTIPOLE_ORDER > 3 + + /* 3rd order contributions */ + *f_x += m->M_003 * d.D_103 + m->M_012 * d.D_112 + m->M_021 * d.D_121 + + m->M_030 * d.D_130 + m->M_102 * d.D_202 + m->M_111 * d.D_211 + + m->M_120 * d.D_220 + m->M_201 * d.D_301 + m->M_210 * d.D_310 + + m->M_300 * d.D_400; + *f_y += m->M_003 * d.D_013 + m->M_012 * d.D_022 + m->M_021 * d.D_031 + + m->M_030 * d.D_040 + m->M_102 * d.D_112 + m->M_111 * d.D_121 + + m->M_120 * d.D_130 + m->M_201 * d.D_211 + m->M_210 * d.D_220 + + m->M_300 * d.D_310; + *f_z += m->M_003 * d.D_004 + m->M_012 * d.D_013 + m->M_021 * d.D_022 + + m->M_030 * d.D_031 + m->M_102 * d.D_103 + m->M_111 * d.D_112 + + m->M_120 * d.D_121 + m->M_201 * d.D_202 + m->M_210 * d.D_211 + + m->M_300 * d.D_301; + *pot += m->M_003 * d.D_003 + m->M_012 * d.D_012 + m->M_021 * d.D_021 + + m->M_030 * d.D_030 + m->M_102 * d.D_102 + m->M_111 * d.D_111 + + m->M_120 * d.D_120 + m->M_201 * d.D_201 + m->M_210 * d.D_210 + + m->M_300 * d.D_300; + +#endif + + /* Take care of the the sign convention */ + *f_x *= -1.f; + *f_y *= -1.f; + *f_z *= -1.f; + *pot *= -1.f; +#endif +} + +/** + * @brief Computes the forces at a point generated by a multipole, truncated for + * long-range periodicity. + * + * This assumes M_100 == M_010 == M_001 == 0. + * This uses the quadrupole term and trace of the octupole terms only and + * defaults to the monopole if the code is compiled with low-order gravity only. + * + * @param r_x x-component of the distance vector to the multipole. + * @param r_y y-component of the distance vector to the multipole. + * @param r_z z-component of the distance vector to the multipole. + * @param r2 Square of the distance vector to the multipole. + * @param h The softening length. + * @param h_inv Inverse of the softening length. + * @param r_s_inv The inverse of the gravity mesh-smoothing scale. + * @param m The multipole. + * @param f_x (return) The x-component of the acceleration. + * @param f_y (return) The y-component of the acceleration. + * @param f_z (return) The z-component of the acceleration. + * @param pot (return) The potential. + */ +__attribute__((always_inline)) INLINE static void runner_iact_grav_pm_truncated( + const float r_x, const float r_y, const float r_z, const float r2, + const float h, const float h_inv, const float r_s_inv, + const struct multipole *m, float *f_x, float *f_y, float *f_z, float *pot) { + +/* In the case where the order is < 3, then there is only a monopole term left. + * We can default to the normal P-P interaction with the mass of the multipole + * and its CoM as the "particle" property */ +#if SELF_GRAVITY_MULTIPOLE_ORDER < 3 + + float f_ij, pot_ij; + runner_iact_grav_pp_truncated(r2, h * h, h_inv, h_inv * h_inv * h_inv, + m->M_000, r_s_inv, &f_ij, &pot_ij); + *f_x = f_ij * r_x; + *f_y = f_ij * r_y; + *f_z = f_ij * r_z; + *pot = -pot_ij; + +#else + + /* Get the inverse distance */ + const float r_inv = 1.f / sqrtf(r2); + + /* Compute the derivatives of the potential */ + struct potential_derivatives_M2P d; + potential_derivatives_compute_M2P(r_x, r_y, r_z, r2, r_inv, h, /*periodic=*/1, + r_s_inv, &d); + + /* 0th order contributions */ + *f_x = m->M_000 * d.D_100; + *f_y = m->M_000 * d.D_010; + *f_z = m->M_000 * d.D_001; + *pot = m->M_000 * d.D_000; + +#if SELF_GRAVITY_MULTIPOLE_ORDER > 1 + + /* 1st order contributions */ + + /* 1st order contributions are all 0 since the dipole is 0 */ + + /* *f_x = m->M_001 * d.D_101 + m->M_010 * d.D_110 + m->M_100 * d.D_200 ; */ + /* *f_y = m->M_001 * d.D_011 + m->M_010 * d.D_020 + m->M_100 * d.D_110 ; */ + /* *f_z = m->M_001 * d.D_002 + m->M_010 * d.D_011 + m->M_100 * d.D_101 ; */ + /* *pot = m->M_001 * d.D_001 + m->M_010 * d.D_010 + m->M_100 * d.D_100 ; */ + +#endif + +#if SELF_GRAVITY_MULTIPOLE_ORDER > 2 + + /* 2nd order contributions */ + *f_x += m->M_002 * d.D_102 + m->M_011 * d.D_111 + m->M_020 * d.D_120 + + m->M_101 * d.D_201 + m->M_110 * d.D_210 + m->M_200 * d.D_300; + *f_y += m->M_002 * d.D_012 + m->M_011 * d.D_021 + m->M_020 * d.D_030 + + m->M_101 * d.D_111 + m->M_110 * d.D_120 + m->M_200 * d.D_210; + *f_z += m->M_002 * d.D_003 + m->M_011 * d.D_012 + m->M_020 * d.D_021 + + m->M_101 * d.D_102 + m->M_110 * d.D_111 + m->M_200 * d.D_201; + *pot += m->M_002 * d.D_002 + m->M_011 * d.D_011 + m->M_020 * d.D_020 + + m->M_101 * d.D_101 + m->M_110 * d.D_110 + m->M_200 * d.D_200; + +#endif + +#if SELF_GRAVITY_MULTIPOLE_ORDER > 3 + + /* 3rd order contributions */ + *f_x += m->M_003 * d.D_103 + m->M_012 * d.D_112 + m->M_021 * d.D_121 + + m->M_030 * d.D_130 + m->M_102 * d.D_202 + m->M_111 * d.D_211 + + m->M_120 * d.D_220 + m->M_201 * d.D_301 + m->M_210 * d.D_310 + + m->M_300 * d.D_400; + *f_y += m->M_003 * d.D_013 + m->M_012 * d.D_022 + m->M_021 * d.D_031 + + m->M_030 * d.D_040 + m->M_102 * d.D_112 + m->M_111 * d.D_121 + + m->M_120 * d.D_130 + m->M_201 * d.D_211 + m->M_210 * d.D_220 + + m->M_300 * d.D_310; + *f_z += m->M_003 * d.D_004 + m->M_012 * d.D_013 + m->M_021 * d.D_022 + + m->M_030 * d.D_031 + m->M_102 * d.D_103 + m->M_111 * d.D_112 + + m->M_120 * d.D_121 + m->M_201 * d.D_202 + m->M_210 * d.D_211 + + m->M_300 * d.D_301; + *pot += m->M_003 * d.D_003 + m->M_012 * d.D_012 + m->M_021 * d.D_021 + + m->M_030 * d.D_030 + m->M_102 * d.D_102 + m->M_111 * d.D_111 + + m->M_120 * d.D_120 + m->M_201 * d.D_201 + m->M_210 * d.D_210 + + m->M_300 * d.D_300; + +#endif + + /* Take care of the the sign convention */ + *f_x *= -1.f; + *f_y *= -1.f; + *f_z *= -1.f; + *pot *= -1.f; +#endif +} + +#endif /* SWIFT_MULTI_SOFTENING_GRAVITY_IACT_H */ diff --git a/src/gravity/MultiSoftening/gravity_io.h b/src/gravity/MultiSoftening/gravity_io.h new file mode 100644 index 0000000000000000000000000000000000000000..412a270afef5d3e7ab75530184782479aaa46b82 --- /dev/null +++ b/src/gravity/MultiSoftening/gravity_io.h @@ -0,0 +1,138 @@ +/******************************************************************************* + * This file is part of SWIFT. + * Coypright (c) 2016 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/>. + * + ******************************************************************************/ +#ifndef SWIFT_MULTI_SOFTENING_GRAVITY_IO_H +#define SWIFT_MULTI_SOFTENING_GRAVITY_IO_H + +#include "io_properties.h" + +INLINE static void convert_gpart_pos(const struct engine* e, + const struct gpart* gp, double* ret) { + + if (e->s->periodic) { + ret[0] = box_wrap(gp->x[0], 0.0, e->s->dim[0]); + ret[1] = box_wrap(gp->x[1], 0.0, e->s->dim[1]); + ret[2] = box_wrap(gp->x[2], 0.0, e->s->dim[2]); + } else { + ret[0] = gp->x[0]; + ret[1] = gp->x[1]; + ret[2] = gp->x[2]; + } +} + +INLINE static void convert_gpart_vel(const struct engine* e, + const struct gpart* gp, float* ret) { + + const int with_cosmology = (e->policy & engine_policy_cosmology); + const struct cosmology* cosmo = e->cosmology; + const integertime_t ti_current = e->ti_current; + const double time_base = e->time_base; + + const integertime_t ti_beg = get_integer_time_begin(ti_current, gp->time_bin); + const integertime_t ti_end = get_integer_time_end(ti_current, gp->time_bin); + + /* Get time-step since the last kick */ + float dt_kick_grav; + if (with_cosmology) { + dt_kick_grav = cosmology_get_grav_kick_factor(cosmo, ti_beg, ti_current); + dt_kick_grav -= + cosmology_get_grav_kick_factor(cosmo, ti_beg, (ti_beg + ti_end) / 2); + } else { + dt_kick_grav = (ti_current - ((ti_beg + ti_end) / 2)) * time_base; + } + + /* Extrapolate the velocites to the current time */ + ret[0] = gp->v_full[0] + gp->a_grav[0] * dt_kick_grav; + ret[1] = gp->v_full[1] + gp->a_grav[1] * dt_kick_grav; + ret[2] = gp->v_full[2] + gp->a_grav[2] * dt_kick_grav; + + /* Conversion from internal units to peculiar velocities */ + ret[0] *= cosmo->a_inv; + ret[1] *= cosmo->a_inv; + ret[2] *= cosmo->a_inv; +} + +INLINE static void convert_gpart_soft(const struct engine* e, + const struct gpart* gp, float* ret) { + + ret[0] = kernel_gravity_softening_plummer_equivalent_inv * + gravity_get_softening(gp, e->gravity_properties); +} + +/** + * @brief Specifies which g-particle fields to read from a dataset + * + * @param gparts The g-particle array. + * @param list The list of i/o properties to read. + * @param num_fields The number of i/o fields to read. + */ +INLINE static void darkmatter_read_particles(struct gpart* gparts, + struct io_props* list, + int* num_fields) { + + /* Say how much we want to read */ + *num_fields = 4; + + /* List what we want to read */ + list[0] = io_make_input_field("Coordinates", DOUBLE, 3, COMPULSORY, + UNIT_CONV_LENGTH, gparts, x); + list[1] = io_make_input_field("Velocities", FLOAT, 3, COMPULSORY, + UNIT_CONV_SPEED, gparts, v_full); + list[2] = io_make_input_field("Masses", FLOAT, 1, COMPULSORY, UNIT_CONV_MASS, + gparts, mass); + list[3] = io_make_input_field("ParticleIDs", ULONGLONG, 1, COMPULSORY, + UNIT_CONV_NO_UNITS, gparts, id_or_neg_offset); +} + +/** + * @brief Specifies which g-particle fields to write to a dataset + * + * @param gparts The g-particle array. + * @param list The list of i/o properties to write. + * @param num_fields The number of i/o fields to write. + */ +INLINE static void darkmatter_write_particles(const struct gpart* gparts, + struct io_props* list, + int* num_fields) { + + /* Say how much we want to write */ + *num_fields = 5; + + /* List what we want to write */ + list[0] = io_make_output_field_convert_gpart( + "Coordinates", DOUBLE, 3, UNIT_CONV_LENGTH, 1.f, gparts, + convert_gpart_pos, "Co-moving position of the particles"); + + list[1] = io_make_output_field_convert_gpart( + "Velocities", FLOAT, 3, UNIT_CONV_SPEED, 0.f, gparts, convert_gpart_vel, + "Peculiar velocities of the stars. This is a * dx/dt where x is the " + "co-moving position of the particles."); + + list[2] = io_make_output_field("Masses", FLOAT, 1, UNIT_CONV_MASS, 0.f, + gparts, mass, "Masses of the particles"); + + list[3] = io_make_output_field( + "ParticleIDs", ULONGLONG, 1, UNIT_CONV_NO_UNITS, 0.f, gparts, + id_or_neg_offset, "Unique ID of the particles"); + + list[4] = io_make_output_field_convert_gpart( + "Softenings", FLOAT, 1, UNIT_CONV_LENGTH, 1.f, gparts, convert_gpart_soft, + "Co-moving Plummer-equivalent softening lengths of the particles."); +} + +#endif /* SWIFT_MULTI_SOFTENING_GRAVITY_IO_H */ diff --git a/src/gravity/MultiSoftening/gravity_part.h b/src/gravity/MultiSoftening/gravity_part.h new file mode 100644 index 0000000000000000000000000000000000000000..de410fbbb988136af46c6f9085bdafee863b9f99 --- /dev/null +++ b/src/gravity/MultiSoftening/gravity_part.h @@ -0,0 +1,88 @@ +/******************************************************************************* + * This file is part of SWIFT. + * Copyright (c) 2012 Pedro Gonnet (pedro.gonnet@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/>. + * + ******************************************************************************/ +#ifndef SWIFT_MULTI_SOFTENING_GRAVITY_PART_H +#define SWIFT_MULTI_SOFTENING_GRAVITY_PART_H + +#include "fof_struct.h" + +/* Gravity particle. */ +struct gpart { + + /*! Particle ID. If negative, it is the negative offset of the #part with + which this gpart is linked. */ + long long id_or_neg_offset; + + /*! Particle position. */ + double x[3]; + + /*! Particle velocity. */ + float v_full[3]; + + /*! Particle acceleration. */ + float a_grav[3]; + + /*! Gravitational potential */ + float potential; + + /*! Particle mass. */ + float mass; + + /*! Particle FoF properties (group ID, group size, ...) */ + struct fof_gpart_data fof_data; + + /*! Time-step length */ + timebin_t time_bin; + + /*! Type of the #gpart (DM, gas, star, ...) */ + enum part_type type; + +#ifdef SWIFT_DEBUG_CHECKS + + /* Numer of gparts this gpart interacted with */ + long long num_interacted; + + /* Time of the last drift */ + integertime_t ti_drift; + + /* Time of the last kick */ + integertime_t ti_kick; + + /* Has this particle been initialised? */ + int initialised; + +#endif + +#ifdef SWIFT_GRAVITY_FORCE_CHECKS + + /*! Acceleration taken from the mesh only */ + float a_grav_PM[3]; + + /*! Potential taken from the mesh only */ + float potential_PM; + + /* Brute-force particle acceleration. */ + double a_grav_exact[3]; + + /* Brute-force particle potential. */ + double potential_exact; +#endif + +} SWIFT_STRUCT_ALIGN; + +#endif /* SWIFT_MULTI_SOFTENING_GRAVITY_PART_H */ diff --git a/src/gravity/Potential/gravity.h b/src/gravity/Potential/gravity.h index 7d38e9126f1a313b169092b080ebc312c4bbe1bc..3a3e9680016ef51c554691c6f43f8279cde8caf9 100644 --- a/src/gravity/Potential/gravity.h +++ b/src/gravity/Potential/gravity.h @@ -22,6 +22,7 @@ #include <float.h> +/* Local includes. */ #include "cosmology.h" #include "gravity_properties.h" #include "kernel_gravity.h" @@ -41,13 +42,16 @@ __attribute__((always_inline)) INLINE static float gravity_get_mass( /** * @brief Returns the current co-moving softening of a particle * + * Note that in this basic gravity scheme, all particles have + * the same softening length. + * * @param gp The particle of interest * @param grav_props The global gravity properties. */ __attribute__((always_inline)) INLINE static float gravity_get_softening( const struct gpart* gp, const struct gravity_props* restrict grav_props) { - return grav_props->epsilon_cur; + return grav_props->epsilon_DM_cur; } /** diff --git a/src/gravity/Potential/gravity_iact.h b/src/gravity/Potential/gravity_iact.h index f2094f6ecd5b31b94ebfe7a64f42fbd289a0c81c..abd4b0718145b131b0c1ad79dfe05d89a55cbb28 100644 --- a/src/gravity/Potential/gravity_iact.h +++ b/src/gravity/Potential/gravity_iact.h @@ -169,8 +169,8 @@ __attribute__((always_inline)) INLINE static void runner_iact_grav_pm_full( /* Compute the derivatives of the potential */ struct potential_derivatives_M2P d; - potential_derivatives_compute_M2P(r_x, r_y, r_z, r2, r_inv, h, h_inv, 0, 0.f, - &d); + potential_derivatives_compute_M2P(r_x, r_y, r_z, r2, r_inv, h, /*periodic=*/0, + /*r_s_inv=*/0.f, &d); /* 0th order contributions */ *f_x = m->M_000 * d.D_100; @@ -178,7 +178,7 @@ __attribute__((always_inline)) INLINE static void runner_iact_grav_pm_full( *f_z = m->M_000 * d.D_001; *pot = m->M_000 * d.D_000; -#if SELF_GRAVITY_MULTIPOLE_ORDER > 0 +#if SELF_GRAVITY_MULTIPOLE_ORDER > 1 /* 1st order contributions */ @@ -281,7 +281,7 @@ __attribute__((always_inline)) INLINE static void runner_iact_grav_pm_truncated( /* Compute the derivatives of the potential */ struct potential_derivatives_M2P d; - potential_derivatives_compute_M2P(r_x, r_y, r_z, r2, r_inv, h, h_inv, 1, + potential_derivatives_compute_M2P(r_x, r_y, r_z, r2, r_inv, h, /*periodic=*/1, r_s_inv, &d); /* 0th order contributions */ @@ -290,7 +290,7 @@ __attribute__((always_inline)) INLINE static void runner_iact_grav_pm_truncated( *f_z = m->M_000 * d.D_001; *pot = m->M_000 * d.D_000; -#if SELF_GRAVITY_MULTIPOLE_ORDER > 0 +#if SELF_GRAVITY_MULTIPOLE_ORDER > 1 /* 1st order contributions */ diff --git a/src/gravity_cache.h b/src/gravity_cache.h index 6d073db60171a9d30d6f397213849e4c3d5314a1..912961d2e06dc748039f54c72bd9b33fd2547df2 100644 --- a/src/gravity_cache.h +++ b/src/gravity_cache.h @@ -255,7 +255,8 @@ __attribute__((always_inline)) INLINE static void gravity_cache_populate( const float r2 = dx * dx + dy * dy + dz * dz; /* Check whether we can use the multipole instead of P-P */ - use_mpole[i] = allow_mpole && gravity_M2P_accept(r_max2, theta_crit2, r2); + use_mpole[i] = + allow_mpole && gravity_M2P_accept(r_max2, theta_crit2, r2, epsilon[i]); } #ifdef SWIFT_DEBUG_CHECKS @@ -436,7 +437,7 @@ gravity_cache_populate_all_mpole(const timebin_t max_active_bin, } const float r2 = dx * dx + dy * dy + dz * dz; - if (!gravity_M2P_accept(r_max2, theta_crit2, r2)) + if (!gravity_M2P_accept(r_max2, theta_crit2, r2, epsilon[i])) error("Using m-pole where the test fails"); #endif } diff --git a/src/gravity_derivatives.h b/src/gravity_derivatives.h index 3dcffe1cc04c5e10d3b2353b7e21c532747c1475..2ec9bd58c9c7ef8703b6191d1346c3da74416101 100644 --- a/src/gravity_derivatives.h +++ b/src/gravity_derivatives.h @@ -194,7 +194,6 @@ potential_derivatives_flip_signs(struct potential_derivatives_M2L *pot) { * @param r2 Square norm of distance vector * @param r_inv Inverse norm of distance vector * @param eps Softening length. - * @param eps_inv Inverse of softening length. * @param periodic Is the calculation periodic ? * @param r_s_inv Inverse of the long-range gravity mesh smoothing length. * @param pot (return) The structure containing all the derivatives. @@ -203,10 +202,14 @@ __attribute__((always_inline)) INLINE static void potential_derivatives_compute_M2L(const float r_x, const float r_y, const float r_z, const float r2, const float r_inv, const float eps, - const float eps_inv, const int periodic, - const float r_s_inv, + const int periodic, const float r_s_inv, struct potential_derivatives_M2L *pot) { +#ifdef SWIFT_DEBUG_CHECKS + if (r2 < 0.99f * eps * eps) + error("Computing M2L derivatives below softening length"); +#endif + float Dt_1; #if SELF_GRAVITY_MULTIPOLE_ORDER > 0 float Dt_3; @@ -224,8 +227,8 @@ potential_derivatives_compute_M2L(const float r_x, const float r_y, float Dt_11; #endif - /* Un-softened un-truncated case (Newtonian potential) */ - if (!periodic && r2 > eps * eps) { + /* Un-truncated case (Newtonian potential) */ + if (!periodic) { Dt_1 = r_inv; #if SELF_GRAVITY_MULTIPOLE_ORDER > 0 @@ -248,8 +251,8 @@ potential_derivatives_compute_M2L(const float r_x, const float r_y, #error "Missing implementation for order >5" #endif - /* Un-softened truncated case */ - } else if (periodic && r2 > eps * eps) { + /* Truncated case */ + } else { /* Get the derivatives of the truncated potential */ const float r = r2 * r_inv; @@ -291,38 +294,6 @@ potential_derivatives_compute_M2L(const float r_x, const float r_y, #endif #if SELF_GRAVITY_MULTIPOLE_ORDER > 5 #error "Missing implementation for order >5" -#endif - - /* Softened case */ - } else { - const float r = r2 * r_inv; - const float u = r * eps_inv; - const float u_inv = r_inv * eps; - - Dt_1 = eps_inv * D_soft_1(u, u_inv); -#if SELF_GRAVITY_MULTIPOLE_ORDER > 0 - const float eps_inv2 = eps_inv * eps_inv; - const float eps_inv3 = eps_inv * eps_inv2; - Dt_3 = -eps_inv3 * D_soft_3(u, u_inv); -#endif -#if SELF_GRAVITY_MULTIPOLE_ORDER > 1 - const float eps_inv5 = eps_inv3 * eps_inv2; - Dt_5 = eps_inv5 * D_soft_5(u, u_inv); -#endif -#if SELF_GRAVITY_MULTIPOLE_ORDER > 2 - const float eps_inv7 = eps_inv5 * eps_inv2; - Dt_7 = -eps_inv7 * D_soft_7(u, u_inv); -#endif -#if SELF_GRAVITY_MULTIPOLE_ORDER > 3 - const float eps_inv9 = eps_inv7 * eps_inv2; - Dt_9 = eps_inv9 * D_soft_9(u, u_inv); -#endif -#if SELF_GRAVITY_MULTIPOLE_ORDER > 4 - const float eps_inv11 = eps_inv9 * eps_inv2; - Dt_11 = -eps_inv11 * D_soft_11(u, u_inv); -#endif -#if SELF_GRAVITY_MULTIPOLE_ORDER > 5 -#error "Missing implementation for order >5" #endif } @@ -450,7 +421,6 @@ potential_derivatives_compute_M2L(const float r_x, const float r_y, * @param r2 Square norm of distance vector * @param r_inv Inverse norm of distance vector * @param eps Softening length. - * @param eps_inv Inverse of softening length. * @param periodic Is the calculation using periodic BCs? * @param r_s_inv The inverse of the gravity mesh-smoothing scale. * @param pot (return) The structure containing all the derivatives. @@ -459,10 +429,14 @@ __attribute__((always_inline)) INLINE static void potential_derivatives_compute_M2P(const float r_x, const float r_y, const float r_z, const float r2, const float r_inv, const float eps, - const float eps_inv, const int periodic, - const float r_s_inv, + const int periodic, const float r_s_inv, struct potential_derivatives_M2P *pot) { +#ifdef SWIFT_DEBUG_CHECKS + if (r2 < 0.99f * eps * eps) + error("Computing M2P derivatives below softening length"); +#endif + float Dt_1; float Dt_3; float Dt_5; @@ -471,8 +445,8 @@ potential_derivatives_compute_M2P(const float r_x, const float r_y, float Dt_9; #endif - /* Un-softened un-truncated case (Newtonian potential) */ - if (!periodic && r2 > eps * eps) { + /* Un-truncated case (Newtonian potential) */ + if (!periodic) { const float r_inv2 = r_inv * r_inv; @@ -484,8 +458,8 @@ potential_derivatives_compute_M2P(const float r_x, const float r_y, Dt_9 = -7.f * Dt_7 * r_inv2; /* -105 / r^9 */ #endif - /* Un-softened truncated case */ - } else if (periodic && r2 > eps * eps) { + /* Truncated case */ + } else if (periodic) { /* Get the derivatives of the truncated potential */ const float r = r2 * r_inv; @@ -512,30 +486,6 @@ potential_derivatives_compute_M2P(const float r_x, const float r_y, 45.f * r * r * d.chi_2 - 105.f * r * d.chi_1 + 105.f * d.chi_0) * r_inv9; #endif - - /* Softened case */ - } else { - - const float r = r2 * r_inv; - const float u = r * eps_inv; - const float u_inv = r_inv * eps; - const float eps_inv2 = eps_inv * eps_inv; - - Dt_1 = eps_inv * D_soft_1(u, u_inv); - - const float eps_inv3 = eps_inv * eps_inv2; - Dt_3 = -eps_inv3 * D_soft_3(u, u_inv); - - const float eps_inv5 = eps_inv3 * eps_inv2; - Dt_5 = eps_inv5 * D_soft_5(u, u_inv); - - const float eps_inv7 = eps_inv5 * eps_inv2; - Dt_7 = -eps_inv7 * D_soft_7(u, u_inv); - -#if SELF_GRAVITY_MULTIPOLE_ORDER > 3 - const float eps_inv9 = eps_inv7 * eps_inv2; - Dt_9 = eps_inv9 * D_soft_9(u, u_inv); -#endif } /* Compute some powers of r_x, r_y and r_z */ diff --git a/src/gravity_iact.h b/src/gravity_iact.h index 2aaf7219d0851058cba92d4686ed989572dbcaa4..4c8d707fe33d0955809f8cb394d75c3a2f580fb7 100644 --- a/src/gravity_iact.h +++ b/src/gravity_iact.h @@ -32,6 +32,8 @@ #include "./gravity/Default/gravity_iact.h" #elif defined(POTENTIAL_GRAVITY) #include "./gravity/Potential/gravity_iact.h" +#elif defined(MULTI_SOFTENING_GRAVITY) +#include "./gravity/MultiSoftening/gravity_iact.h" #else #error "Invalid choice of gravity variant" #endif diff --git a/src/gravity_io.h b/src/gravity_io.h index 752ee906081d706865e62bae7c8f505e9ca64347..44f392ee06d43228f7aa46faa5c7d9015fde790b 100644 --- a/src/gravity_io.h +++ b/src/gravity_io.h @@ -30,6 +30,8 @@ #include "./gravity/Default/gravity_io.h" #elif defined(POTENTIAL_GRAVITY) #include "./gravity/Potential/gravity_io.h" +#elif defined(MULTI_SOFTENING_GRAVITY) +#include "./gravity/MultiSoftening/gravity_io.h" #else #error "Invalid choice of gravity variant" #endif diff --git a/src/gravity_properties.c b/src/gravity_properties.c index 8d3dfe9c4683842b905959ab3c688cc1f23309e9..d1654a1e7830d31c20731f130389a04d69b148b3 100644 --- a/src/gravity_properties.c +++ b/src/gravity_properties.c @@ -40,8 +40,9 @@ void gravity_props_init(struct gravity_props *p, struct swift_params *params, const struct phys_const *phys_const, - const struct cosmology *cosmo, int with_cosmology, - int periodic) { + const struct cosmology *cosmo, const int with_cosmology, + const int has_baryons, const int has_DM, + const int is_zoom_simulation, const int periodic) { /* Tree updates */ p->rebuild_frequency = @@ -89,14 +90,58 @@ void gravity_props_init(struct gravity_props *p, struct swift_params *params, /* Softening parameters */ if (with_cosmology) { - p->epsilon_comoving = - parser_get_param_double(params, "Gravity:comoving_softening"); - p->epsilon_max_physical = - parser_get_param_double(params, "Gravity:max_physical_softening"); + + if (has_DM) { + /* Maximal physical softening taken straight from the parameter file */ + p->epsilon_DM_max_physical = + parser_get_param_double(params, "Gravity:max_physical_DM_softening"); + + /* Co-moving softenings taken straight from the parameter file */ + p->epsilon_DM_comoving = + parser_get_param_double(params, "Gravity:comoving_DM_softening"); + } + + if (has_baryons) { + /* Maximal physical softening taken straight from the parameter file */ + p->epsilon_baryon_max_physical = parser_get_param_double( + params, "Gravity:max_physical_baryon_softening"); + + /* Co-moving softenings taken straight from the parameter file */ + p->epsilon_baryon_comoving = + parser_get_param_double(params, "Gravity:comoving_baryon_softening"); + } + + if (is_zoom_simulation) { + + /* Compute the comoving softening length for background particles as + * a fraction of the mean inter-particle density of the background DM + * particles Since they have variable masses the mass factor will be + * multiplied in later on. Note that we already multiply in the conversion + * from Plummer -> real softening length */ + const double ratio_background = + parser_get_param_double(params, "Gravity:softening_ratio_background"); + + const double mean_matter_density = + cosmo->Omega_m * cosmo->critical_density_0; + + p->epsilon_background_fac = kernel_gravity_softening_plummer_equivalent * + ratio_background * + cbrt(1. / mean_matter_density); + } + } else { - p->epsilon_max_physical = - parser_get_param_double(params, "Gravity:max_physical_softening"); - p->epsilon_comoving = p->epsilon_max_physical; + + if (has_DM) { + p->epsilon_DM_max_physical = + parser_get_param_double(params, "Gravity:max_physical_DM_softening"); + } + if (has_baryons) { + p->epsilon_baryon_max_physical = parser_get_param_double( + params, "Gravity:max_physical_baryon_softening"); + } + + p->epsilon_DM_comoving = p->epsilon_DM_max_physical; + p->epsilon_baryon_comoving = p->epsilon_baryon_max_physical; } /* Copy over the gravitational constant */ @@ -109,23 +154,26 @@ void gravity_props_init(struct gravity_props *p, struct swift_params *params, void gravity_props_update(struct gravity_props *p, const struct cosmology *cosmo) { - /* Current softening lengths */ - double softening; - if (p->epsilon_comoving * cosmo->a > p->epsilon_max_physical) - softening = p->epsilon_max_physical / cosmo->a; + /* Current softening length for the high-res. DM particles. */ + double DM_softening, baryon_softening; + if (p->epsilon_DM_comoving * cosmo->a > p->epsilon_DM_max_physical) + DM_softening = p->epsilon_DM_max_physical / cosmo->a; else - softening = p->epsilon_comoving; + DM_softening = p->epsilon_DM_comoving; + + /* Current softening length for the high-res. baryon particles. */ + if (p->epsilon_baryon_comoving * cosmo->a > p->epsilon_baryon_max_physical) + baryon_softening = p->epsilon_baryon_max_physical / cosmo->a; + else + baryon_softening = p->epsilon_baryon_comoving; /* Plummer equivalent -> internal */ - softening *= kernel_gravity_softening_plummer_equivalent; + DM_softening *= kernel_gravity_softening_plummer_equivalent; + baryon_softening *= kernel_gravity_softening_plummer_equivalent; /* Store things */ - p->epsilon_cur = softening; - - /* Other factors */ - p->epsilon_cur2 = softening * softening; - p->epsilon_cur_inv = 1. / softening; - p->epsilon_cur_inv3 = 1. / (softening * softening * softening); + p->epsilon_DM_cur = DM_softening; + p->epsilon_baryon_cur = baryon_softening; } void gravity_props_print(const struct gravity_props *p) { @@ -143,16 +191,31 @@ void gravity_props_print(const struct gravity_props *p) { kernel_gravity_softening_name); message( - "Self-gravity comoving softening: epsilon=%.4f (Plummer equivalent: " - "%.4f)", - p->epsilon_comoving * kernel_gravity_softening_plummer_equivalent, - p->epsilon_comoving); + "Self-gravity DM comoving softening: epsilon=%.6f (Plummer equivalent: " + "%.6f)", + p->epsilon_DM_comoving * kernel_gravity_softening_plummer_equivalent, + p->epsilon_DM_comoving); message( - "Self-gravity maximal physical softening: epsilon=%.4f (Plummer " - "equivalent: %.4f)", - p->epsilon_max_physical * kernel_gravity_softening_plummer_equivalent, - p->epsilon_max_physical); + "Self-gravity DM maximal physical softening: epsilon=%.6f (Plummer " + "equivalent: %.6f)", + p->epsilon_DM_max_physical * kernel_gravity_softening_plummer_equivalent, + p->epsilon_DM_max_physical); + + message( + "Self-gravity baryon comoving softening: epsilon=%.6f (Plummer " + "equivalent: " + "%.6f)", + p->epsilon_baryon_comoving * kernel_gravity_softening_plummer_equivalent, + p->epsilon_baryon_comoving); + + message( + "Self-gravity baryon maximal physical softening: epsilon=%.6f " + "(Plummer " + "equivalent: %.6f)", + p->epsilon_baryon_max_physical * + kernel_gravity_softening_plummer_equivalent, + p->epsilon_baryon_max_physical); message("Self-gravity mesh side-length: N=%d", p->mesh_size); message("Self-gravity mesh smoothing-scale: a_smooth=%f", p->a_smooth); @@ -174,20 +237,40 @@ void gravity_props_print_snapshot(hid_t h_grpgrav, io_write_attribute_f(h_grpgrav, "Time integration eta", p->eta); io_write_attribute_s(h_grpgrav, "Softening style", kernel_gravity_softening_name); + io_write_attribute_f( - h_grpgrav, "Comoving softening length [internal units]", - p->epsilon_comoving * kernel_gravity_softening_plummer_equivalent); + h_grpgrav, "Comoving DM softening length [internal units]", + p->epsilon_DM_comoving * kernel_gravity_softening_plummer_equivalent); io_write_attribute_f( h_grpgrav, - "Comoving Softening length (Plummer equivalent) [internal units]", - p->epsilon_comoving); + "Comoving DM softening length (Plummer equivalent) [internal units]", + p->epsilon_DM_comoving); + io_write_attribute_f( - h_grpgrav, "Maximal physical softening length [internal units]", - p->epsilon_max_physical * kernel_gravity_softening_plummer_equivalent); + h_grpgrav, "Maximal physical DM softening length [internal units]", + p->epsilon_DM_max_physical * kernel_gravity_softening_plummer_equivalent); io_write_attribute_f(h_grpgrav, - "Maximal physical softening length (Plummer equivalent) " - " [internal units]", - p->epsilon_max_physical); + "Maximal physical DM softening length (Plummer " + "equivalent) [internal units]", + p->epsilon_DM_max_physical); + + io_write_attribute_f( + h_grpgrav, "Comoving baryon softening length [internal units]", + p->epsilon_baryon_comoving * kernel_gravity_softening_plummer_equivalent); + io_write_attribute_f( + h_grpgrav, + "Comoving baryon softening length (Plummer equivalent) [internal units]", + p->epsilon_baryon_comoving); + + io_write_attribute_f( + h_grpgrav, "Maximal physical baryon softening length [internal units]", + p->epsilon_baryon_max_physical * + kernel_gravity_softening_plummer_equivalent); + io_write_attribute_f(h_grpgrav, + "Maximal physical baryon softening length (Plummer " + "equivalent) [internal units]", + p->epsilon_baryon_max_physical); + io_write_attribute_f(h_grpgrav, "Opening angle", p->theta_crit); io_write_attribute_s(h_grpgrav, "Scheme", GRAVITY_IMPLEMENTATION); io_write_attribute_i(h_grpgrav, "MM order", SELF_GRAVITY_MULTIPOLE_ORDER); diff --git a/src/gravity_properties.h b/src/gravity_properties.h index 79d72765e767351e29ffa30b615c1f7f4f98022c..d0a68ceb14d13f618dc628fb7e0a0dbf37d67cfb 100644 --- a/src/gravity_properties.h +++ b/src/gravity_properties.h @@ -40,25 +40,23 @@ struct swift_params; */ struct gravity_props { - /*! Frequency of tree-rebuild in units of #gpart updates. */ - float rebuild_frequency; + /* -------------- Softening for the regular particles ---------------- */ - /*! Periodic long-range mesh side-length */ - int mesh_size; + /*! Co-moving softening length for high-res. DM particles at the current + * redshift. */ + float epsilon_DM_cur; - /*! Mesh smoothing scale in units of top-level cell size */ - float a_smooth; + /*! Co-moving softening length for high-res. baryon particles at the current + * redshift. */ + float epsilon_baryon_cur; - /*! Distance below which the truncated mesh force is Newtonian in units of - * a_smooth */ - float r_cut_min_ratio; + /* -------------- Softening for the background DM -------------------- */ - /*! Distance above which the truncated mesh force is negligible in units of - * a_smooth */ - float r_cut_max_ratio; + /*! Conversion factor from cbrt of particle mass to softening assuming + * a constant fraction of the mean inter-particle separation at that mass. */ + float epsilon_background_fac; - /*! Time integration dimensionless multiplier */ - float eta; + /* -------------- Properties of the FFM gravity ---------------------- */ /*! Tree opening angle (Multipole acceptance criterion) */ double theta_crit; @@ -69,23 +67,49 @@ struct gravity_props { /*! Inverse of opening angle */ double theta_crit_inv; - /*! Comoving softening */ - double epsilon_comoving; + /* ------------- Properties of the softened gravity ------------------ */ + + /*! Co-moving softening length for for high-res. DM particles */ + float epsilon_DM_comoving; + + /*! Maximal softening length in physical coordinates for the high-res. + * DM particles */ + float epsilon_DM_max_physical; + + /*! Co-moving softening length for for high-res. baryon particles */ + float epsilon_baryon_comoving; + + /*! Maximal softening length in physical coordinates for the high-res. + * baryon particles */ + float epsilon_baryon_max_physical; - /*! Maxium physical softening */ - double epsilon_max_physical; + /*! Fraction of the mean inter particle separation corresponding to the + * co-moving softening length of the low-res. particles (DM + baryons) */ + float mean_inter_particle_fraction_high_res; - /*! Current softening length */ - float epsilon_cur; + /* ------------- Properties of the time integration ----------------- */ - /*! Square of current softening length */ - float epsilon_cur2; + /*! Frequency of tree-rebuild in units of #gpart updates. */ + float rebuild_frequency; + + /*! Time integration dimensionless multiplier */ + float eta; + + /* ------------- Properties of the mesh-based gravity ---------------- */ + + /*! Periodic long-range mesh side-length */ + int mesh_size; - /*! Inverse of current softening length */ - float epsilon_cur_inv; + /*! Mesh smoothing scale in units of top-level cell size */ + float a_smooth; - /*! Cube of the inverse of current oftening length */ - float epsilon_cur_inv3; + /*! Distance below which the truncated mesh force is Newtonian in units of + * a_smooth */ + float r_cut_min_ratio; + + /*! Distance above which the truncated mesh force is negligible in units of + * a_smooth */ + float r_cut_max_ratio; /*! Gravitational constant (in internal units, copied from the physical * constants) */ @@ -95,8 +119,9 @@ struct gravity_props { void gravity_props_print(const struct gravity_props *p); void gravity_props_init(struct gravity_props *p, struct swift_params *params, const struct phys_const *phys_const, - const struct cosmology *cosmo, int with_cosmology, - int periodic); + const struct cosmology *cosmo, const int with_cosmology, + const int has_baryons, const int has_DM, + const int is_zoom_simulation, const int periodic); void gravity_props_update(struct gravity_props *p, const struct cosmology *cosmo); diff --git a/src/hydro_properties.c b/src/hydro_properties.c index d272fb7381664d91f763119ae68043ce59a77e1f..d28cc1dff363517e72ebb3607ec5aa8121f828b2 100644 --- a/src/hydro_properties.c +++ b/src/hydro_properties.c @@ -343,7 +343,7 @@ void hydro_props_update(struct hydro_props *p, const struct gravity_props *gp, * is a fixed fraction of the radius at which the softened forces * recover a Newtonian behaviour (i.e. 2.8 * Plummer equivalent softening * in the case of a cubic spline kernel). */ - p->h_min = p->h_min_ratio * gp->epsilon_cur / kernel_gamma; + p->h_min = p->h_min_ratio * gp->epsilon_baryon_cur / kernel_gamma; } /** diff --git a/src/multipole.h b/src/multipole.h index e867dfd4e2cc5c9fcd06d7d95dcf76a97689c2b3..bbe8c49db544425f4f35d57884c6036d3f83c905 100644 --- a/src/multipole.h +++ b/src/multipole.h @@ -117,6 +117,9 @@ struct multipole { /*! Minimal velocity along each axis of all #gpart */ float min_delta_vel[3]; + /*! Maximal co-moving softening of all the #gpart in the mulipole */ + float max_softening; + /* 0th order term */ float M_000; @@ -459,6 +462,7 @@ INLINE static void gravity_multipole_init(struct multipole *m) { */ INLINE static void gravity_multipole_print(const struct multipole *m) { + printf("eps_max = %12.5e\n", m->max_softening); printf("Vel= [%12.5e %12.5e %12.5e]\n", m->vel[0], m->vel[1], m->vel[2]); printf("-------------------------\n"); printf("M_000= %12.5e\n", m->M_000); @@ -512,6 +516,9 @@ INLINE static void gravity_multipole_print(const struct multipole *m) { INLINE static void gravity_multipole_add(struct multipole *restrict ma, const struct multipole *restrict mb) { + /* Maximum of both softenings */ + ma->max_softening = max(ma->max_softening, mb->max_softening); + /* Add 0th order term */ ma->M_000 += mb->M_000; @@ -630,6 +637,14 @@ INLINE static int gravity_multipole_equal(const struct gravity_tensors *ga, const double v2 = ma->vel[0] * ma->vel[0] + ma->vel[1] * ma->vel[1] + ma->vel[2] * ma->vel[2]; + /* Check maximal softening */ + if (fabsf(ma->max_softening - mb->max_softening) / + fabsf(ma->max_softening + mb->max_softening) > + tolerance) { + message("max softening different!"); + return 0; + } + /* Check bulk velocity (if non-zero and component > 1% of norm)*/ if (fabsf(ma->vel[0] + mb->vel[0]) > 1e-10 && (ma->vel[0] * ma->vel[0]) > 0.0001 * v2 && @@ -1022,11 +1037,14 @@ INLINE static int gravity_multipole_equal(const struct gravity_tensors *ga, * @param multi The #multipole (content will be overwritten). * @param gparts The #gpart. * @param gcount The number of particles. + * @param grav_props The properties of the gravity scheme. */ INLINE static void gravity_P2M(struct gravity_tensors *multi, - const struct gpart *gparts, int gcount) { + const struct gpart *gparts, const int gcount, + const struct gravity_props *const grav_props) { /* Temporary variables */ + float epsilon_max = 0.f; double mass = 0.0; double com[3] = {0.0, 0.0, 0.0}; double vel[3] = {0.f, 0.f, 0.f}; @@ -1034,12 +1052,14 @@ INLINE static void gravity_P2M(struct gravity_tensors *multi, /* Collect the particle data for CoM. */ for (int k = 0; k < gcount; k++) { const double m = gparts[k].mass; + const float epsilon = gravity_get_softening(&gparts[k], grav_props); #ifdef SWIFT_DEBUG_CHECKS if (gparts[k].time_bin == time_bin_inhibited) error("Inhibited particle in P2M. Should have been removed earlier."); #endif + epsilon_max = max(epsilon_max, epsilon); mass += m; com[0] += gparts[k].x[0] * m; com[1] += gparts[k].x[1] * m; @@ -1203,6 +1223,7 @@ INLINE static void gravity_P2M(struct gravity_tensors *multi, #endif /* Store the data on the multipole. */ + multi->m_pole.max_softening = epsilon_max; multi->m_pole.M_000 = mass; multi->r_max = sqrt(r_max2); multi->CoM[0] = com[0]; @@ -1316,6 +1337,9 @@ INLINE static void gravity_M2M(struct multipole *restrict m_a, const struct multipole *restrict m_b, const double pos_a[3], const double pos_b[3]) { + /* "shift" the softening */ + m_a->max_softening = m_b->max_softening; + /* Shift 0th order term */ m_a->M_000 = m_b->M_000; @@ -1964,8 +1988,7 @@ INLINE static void gravity_M2L_nonsym( const int periodic, const double dim[3], const float rs_inv) { /* Recover some constants */ - const float eps = props->epsilon_cur; - const float eps_inv = props->epsilon_cur_inv; + const float eps = m_a->max_softening; /* Compute distance vector */ float dx = (float)(pos_b[0] - pos_a[0]); @@ -1985,8 +2008,8 @@ INLINE static void gravity_M2L_nonsym( /* Compute all derivatives */ struct potential_derivatives_M2L pot; - potential_derivatives_compute_M2L(dx, dy, dz, r2, r_inv, eps, eps_inv, - periodic, rs_inv, &pot); + potential_derivatives_compute_M2L(dx, dy, dz, r2, r_inv, eps, periodic, + rs_inv, &pot); /* Do the M2L tensor multiplication */ gravity_M2L_apply(l_b, m_a, &pot); @@ -2015,8 +2038,7 @@ INLINE static void gravity_M2L_symmetric( const float rs_inv) { /* Recover some constants */ - const float eps = props->epsilon_cur; - const float eps_inv = props->epsilon_cur_inv; + const float eps = max(m_a->max_softening, m_b->max_softening); /* Compute distance vector */ float dx = (float)(pos_b[0] - pos_a[0]); @@ -2036,8 +2058,8 @@ INLINE static void gravity_M2L_symmetric( /* Compute all derivatives */ struct potential_derivatives_M2L pot; - potential_derivatives_compute_M2L(dx, dy, dz, r2, r_inv, eps, eps_inv, - periodic, rs_inv, &pot); + potential_derivatives_compute_M2L(dx, dy, dz, r2, r_inv, eps, periodic, + rs_inv, &pot); /* Do the first M2L tensor multiplication */ gravity_M2L_apply(l_b, m_a, &pot); @@ -2551,23 +2573,31 @@ INLINE static void gravity_L2P(const struct grav_tensor *lb, * We use the multipole acceptance criterion of Dehnen, 2002, JCoPh, Volume 179, * Issue 1, pp.27-42, equation 10. * + * We also additionally check that the distance between the multipoles + * is larger than the softening lengths (here the distance at which + * the gravity becomes Newtonian again, not the Plummer-equivalent quantity). + * * @param r_crit_a The size of the multipole A. * @param r_crit_b The size of the multipole B. * @param theta_crit2 The square of the critical opening angle. * @param r2 Square of the distance (periodically wrapped) between the * multipoles. + * @param epsilon_a The maximal softening length of any particle in A. + * @param epsilon_b The maximal softening length of any particle in B. */ __attribute__((always_inline, const)) INLINE static int gravity_M2L_accept( const double r_crit_a, const double r_crit_b, const double theta_crit2, - const double r2) { + const double r2, const double epsilon_a, const double epsilon_b) { const double size = r_crit_a + r_crit_b; const double size2 = size * size; + const double epsilon_a2 = epsilon_a * epsilon_a; + const double epsilon_b2 = epsilon_b * epsilon_b; // MATTHIEU: Make this mass-dependent ? /* Multipole acceptance criterion (Dehnen 2002, eq.10) */ - return (r2 * theta_crit2 > size2); + return (r2 * theta_crit2 > size2) && (r2 > epsilon_a2) && (r2 > epsilon_b2); } /** @@ -2577,18 +2607,24 @@ __attribute__((always_inline, const)) INLINE static int gravity_M2L_accept( * We use the multipole acceptance criterion of Dehnen, 2002, JCoPh, Volume 179, * Issue 1, pp.27-42, equation 10. * + * We also additionally check that the distance between the particle and the + * multipole is larger than the softening length (here the distance at which + * the gravity becomes Newtonian again, not the Plummer-equivalent quantity). + * * @param r_max2 The square of the size of the multipole. * @param theta_crit2 The square of the critical opening angle. * @param r2 Square of the distance (periodically wrapped) between the * particle and the multipole. + * @param epsilon The softening length of the particle. */ __attribute__((always_inline, const)) INLINE static int gravity_M2P_accept( - const float r_max2, const float theta_crit2, const float r2) { + const float r_max2, const float theta_crit2, const float r2, + const float epsilon) { // MATTHIEU: Make this mass-dependent ? /* Multipole acceptance criterion (Dehnen 2002, eq.10) */ - return (r2 * theta_crit2 > r_max2); + return (r2 * theta_crit2 > r_max2) && (r2 > epsilon * epsilon); } #endif /* SWIFT_MULTIPOLE_H */ diff --git a/src/parallel_io.c b/src/parallel_io.c index 929e0bb43ac15526bffe66a9563e38e5ea7af9a4..8ce21085e0dc0d1d126ed510262e14842ddf4019 100644 --- a/src/parallel_io.c +++ b/src/parallel_io.c @@ -704,12 +704,13 @@ void writeArray(struct engine* e, hid_t grp, char* fileName, void read_ic_parallel(char* fileName, const struct unit_system* internal_units, double dim[3], struct part** parts, struct gpart** gparts, struct spart** sparts, struct bpart** bparts, - size_t* Ngas, size_t* Ngparts, size_t* Nstars, - size_t* Nblackholes, int* flag_entropy, int with_hydro, - int with_gravity, int with_stars, int with_black_holes, - int cleanup_h, int cleanup_sqrt_a, double h, double a, - int mpi_rank, int mpi_size, MPI_Comm comm, MPI_Info info, - int n_threads, int dry_run) { + size_t* Ngas, size_t* Ngparts, size_t* Ngparts_background, + size_t* Nstars, size_t* Nblackholes, int* flag_entropy, + int with_hydro, int with_gravity, int with_stars, + int with_black_holes, int cleanup_h, int cleanup_sqrt_a, + double h, double a, int mpi_rank, int mpi_size, + MPI_Comm comm, MPI_Info info, int n_threads, + int dry_run) { hid_t h_file = 0, h_grp = 0; /* GADGET has only cubic boxes (in cosmological mode) */ @@ -721,9 +722,11 @@ void read_ic_parallel(char* fileName, const struct unit_system* internal_units, long long offset[swift_type_count] = {0}; int dimension = 3; /* Assume 3D if nothing is specified */ size_t Ndm = 0; + size_t Ndm_background = 0; /* Initialise counters */ - *Ngas = 0, *Ngparts = 0, *Nstars = 0, *Nblackholes = 0; + *Ngas = 0, *Ngparts = 0, *Ngparts_background = 0, *Nstars = 0, + *Nblackholes = 0; /* Open file */ /* message("Opening file '%s' as IC.", fileName); */ @@ -875,11 +878,14 @@ void read_ic_parallel(char* fileName, const struct unit_system* internal_units, /* Allocate memory to store gravity particles */ if (with_gravity) { - Ndm = N[1]; + Ndm = N[swift_type_dark_matter]; + Ndm_background = N[swift_type_dark_matter_background]; *Ngparts = (with_hydro ? N[swift_type_gas] : 0) + N[swift_type_dark_matter] + + N[swift_type_dark_matter_background] + (with_stars ? N[swift_type_stars] : 0) + (with_black_holes ? N[swift_type_black_hole] : 0); + *Ngparts_background = Ndm_background; if (swift_memalign("gparts", (void**)gparts, gpart_align, *Ngparts * sizeof(struct gpart)) != 0) error("Error while allocating memory for gravity particles"); @@ -928,6 +934,13 @@ void read_ic_parallel(char* fileName, const struct unit_system* internal_units, } break; + case swift_type_dark_matter_background: + if (with_gravity) { + Nparticles = Ndm_background; + darkmatter_read_particles(*gparts + Ndm, list, &num_fields); + } + break; + case swift_type_stars: if (with_stars) { Nparticles = *Nstars; @@ -968,17 +981,23 @@ void read_ic_parallel(char* fileName, const struct unit_system* internal_units, /* Prepare the DM particles */ io_prepare_dm_gparts(&tp, *gparts, Ndm); + /* Prepare the DM background particles */ + io_prepare_dm_background_gparts(&tp, *gparts + Ndm, Ndm_background); + /* Duplicate the hydro particles into gparts */ - if (with_hydro) io_duplicate_hydro_gparts(&tp, *parts, *gparts, *Ngas, Ndm); + if (with_hydro) + io_duplicate_hydro_gparts(&tp, *parts, *gparts, *Ngas, + Ndm + Ndm_background); /* Duplicate the stars particles into gparts */ if (with_stars) - io_duplicate_stars_gparts(&tp, *sparts, *gparts, *Nstars, Ndm + *Ngas); + io_duplicate_stars_gparts(&tp, *sparts, *gparts, *Nstars, + Ndm + Ndm_background + *Ngas); /* Duplicate the stars particles into gparts */ if (with_black_holes) io_duplicate_black_holes_gparts(&tp, *bparts, *gparts, *Nblackholes, - Ndm + *Ngas + *Nstars); + Ndm + Ndm_background + *Ngas + *Nstars); threadpool_clean(&tp); } @@ -1236,6 +1255,17 @@ void prepare_file(struct engine* e, const char* baseName, long long N_total[6], } break; + case swift_type_dark_matter_background: + darkmatter_write_particles(gparts, list, &num_fields); + if (with_fof) { + num_fields += fof_write_gparts(gparts, list + num_fields); + } + if (with_stf) { + num_fields += velociraptor_write_gparts(e->s->gpart_group_data, + list + num_fields); + } + break; + case swift_type_stars: stars_write_particles(sparts, list, &num_fields, with_cosmology); num_fields += chemistry_write_sparticles(sparts, list + num_fields); @@ -1329,6 +1359,7 @@ void write_output_parallel(struct engine* e, const char* baseName, const int with_cooling = e->policy & engine_policy_cooling; const int with_temperature = e->policy & engine_policy_temperature; const int with_fof = e->policy & engine_policy_fof; + const int with_DM_background = e->s->with_DM_background; #ifdef HAVE_VELOCIRAPTOR const int with_stf = (e->policy & engine_policy_structure_finding) && (e->s->gpart_group_data != NULL); @@ -1344,6 +1375,11 @@ void write_output_parallel(struct engine* e, const char* baseName, // const size_t Nbaryons = Ngas + Nstars; // const size_t Ndm = Ntot > 0 ? Ntot - Nbaryons : 0; + size_t Ndm_background = 0; + if (with_DM_background) { + Ndm_background = io_count_dm_background_gparts(gparts, Ntot); + } + /* Number of particles that we will write */ const size_t Ntot_written = e->s->nr_gparts - e->s->nr_inhibited_gparts - e->s->nr_extra_gparts; @@ -1356,10 +1392,11 @@ void write_output_parallel(struct engine* e, const char* baseName, const size_t Nbaryons_written = Ngas_written + Nstars_written + Nblackholes_written; const size_t Ndm_written = - Ntot_written > 0 ? Ntot_written - Nbaryons_written : 0; + Ntot_written > 0 ? Ntot_written - Nbaryons_written - Ndm_background : 0; /* Compute offset in the file and total number of particles */ - size_t N[swift_type_count] = {Ngas_written, Ndm_written, 0, 0, + size_t N[swift_type_count] = {Ngas_written, Ndm_written, + Ndm_background, 0, Nstars_written, Nblackholes_written}; long long N_total[swift_type_count] = {0}; long long offset[swift_type_count] = {0}; @@ -1665,6 +1702,43 @@ void write_output_parallel(struct engine* e, const char* baseName, } } break; + case swift_type_dark_matter_background: { + + /* Ok, we need to fish out the particles we want */ + Nparticles = Ndm_background; + + /* Allocate temporary array */ + if (swift_memalign("gparts_written", (void**)&gparts_written, + gpart_align, + Ndm_background * sizeof(struct gpart)) != 0) + error("Error while allocating temporart memory for gparts"); + + if (with_stf) { + if (swift_memalign( + "gpart_group_written", (void**)&gpart_group_data_written, + gpart_align, + Ndm_background * sizeof(struct velociraptor_gpart_data)) != 0) + error( + "Error while allocating temporart memory for gparts STF " + "data"); + } + + /* Collect the non-inhibited DM particles from gpart */ + io_collect_gparts_background_to_write( + gparts, e->s->gpart_group_data, gparts_written, + gpart_group_data_written, Ntot, Ndm_background, with_stf); + + /* Select the fields to write */ + darkmatter_write_particles(gparts_written, list, &num_fields); + if (with_stf) { +#ifdef HAVE_VELOCIRAPTOR + num_fields += velociraptor_write_gparts(gpart_group_data_written, + list + num_fields); +#endif + } + + } break; + case swift_type_stars: { if (Nstars == Nstars_written) { diff --git a/src/parallel_io.h b/src/parallel_io.h index 6e6b52b74ebf166068f8dff110ea0ca0fd8464a2..465835013847347a907b3f81fd3611992070d0d7 100644 --- a/src/parallel_io.h +++ b/src/parallel_io.h @@ -36,12 +36,13 @@ void read_ic_parallel(char* fileName, const struct unit_system* internal_units, double dim[3], struct part** parts, struct gpart** gparts, struct spart** sparts, struct bpart** bparts, - size_t* Ngas, size_t* Ngparts, size_t* Nsparts, - size_t* Nbparts, int* flag_entropy, int with_hydro, - int with_gravity, int with_stars, int with_black_holes, - int cleanup_h, int cleanup_sqrt_a, double h, double a, - int mpi_rank, int mpi_size, MPI_Comm comm, MPI_Info info, - int nr_threads, int dry_run); + size_t* Ngas, size_t* Ngparts, size_t* Ngparts_background, + size_t* Nsparts, size_t* Nbparts, int* flag_entropy, + int with_hydro, int with_gravity, int with_stars, + int with_black_holes, int cleanup_h, int cleanup_sqrt_a, + double h, double a, int mpi_rank, int mpi_size, + MPI_Comm comm, MPI_Info info, int nr_threads, + int dry_run); void write_output_parallel(struct engine* e, const char* baseName, const struct unit_system* internal_units, diff --git a/src/part.c b/src/part.c index 7d967caad18caf0c45d2a422fb4766d34f559d00..d8f57a8b3db3d5f29667dff162fb03d8b117d3a3 100644 --- a/src/part.c +++ b/src/part.c @@ -188,6 +188,15 @@ void part_verify_links(struct part *parts, struct gpart *gparts, error("DM gpart particle linked to something !"); } + /* We have a background DM particle */ + if (gparts[k].type == swift_type_dark_matter_background && + gparts[k].time_bin != time_bin_not_created) { + + /* Check that it's not linked */ + if (gparts[k].id_or_neg_offset <= 0) + error("Background DM gpart particle linked to something !"); + } + /* We have a gas particle */ else if (gparts[k].type == swift_type_gas) { diff --git a/src/part.h b/src/part.h index 820834d652cf53b3dce06192d7c552ec7681f2c7..440e5e1eb3415e65d7d9cc8b611bb98de107a1b2 100644 --- a/src/part.h +++ b/src/part.h @@ -95,6 +95,8 @@ #include "./gravity/Default/gravity_part.h" #elif defined(POTENTIAL_GRAVITY) #include "./gravity/Potential/gravity_part.h" +#elif defined(MULTI_SOFTENING_GRAVITY) +#include "./gravity/MultiSoftening/gravity_part.h" #else #error "Invalid choice of gravity variant" #endif diff --git a/src/part_type.c b/src/part_type.c index 1f96d4ef1db4b35a92d133e91498ea10ce472c70..5a2eee2ee2e4296f4abdd1dd3ae4927748484b15 100644 --- a/src/part_type.c +++ b/src/part_type.c @@ -20,5 +20,5 @@ /* This object's header. */ #include "part_type.h" -const char* part_type_names[swift_type_count] = {"Gas", "DM", "Dummy", - "Dummy", "Stars", "BH"}; +const char* part_type_names[swift_type_count] = { + "Gas", "DM", "DM_background", "Dummy", "Stars", "BH"}; diff --git a/src/part_type.h b/src/part_type.h index 901f47193fa0e72b362c8dce5199a1d0a20526c9..8311f5d17a7b838b9577a029387a5f01fb1a0801 100644 --- a/src/part_type.h +++ b/src/part_type.h @@ -27,6 +27,7 @@ enum part_type { swift_type_gas = 0, swift_type_dark_matter = 1, + swift_type_dark_matter_background = 2, swift_type_stars = 4, swift_type_black_hole = 5, swift_type_count diff --git a/src/runner.c b/src/runner.c index 22fdfaee1d422a935be5d6a5329f67d8b9c41efb..db7e512873b51a7329e19e75a763b69521efb0eb 100644 --- a/src/runner.c +++ b/src/runner.c @@ -2776,7 +2776,9 @@ void runner_do_kick1(struct runner *r, struct cell *c, int timer) { struct gpart *restrict gp = &gparts[k]; /* If the g-particle has no counterpart and needs to be kicked */ - if (gp->type == swift_type_dark_matter && gpart_is_starting(gp, e)) { + if ((gp->type == swift_type_dark_matter || + gp->type == swift_type_dark_matter_background) && + gpart_is_starting(gp, e)) { const integertime_t ti_step = get_integer_timestep(gp->time_bin); const integertime_t ti_begin = @@ -2970,7 +2972,9 @@ void runner_do_kick2(struct runner *r, struct cell *c, int timer) { struct gpart *restrict gp = &gparts[k]; /* If the g-particle has no counterpart and needs to be kicked */ - if (gp->type == swift_type_dark_matter && gpart_is_active(gp, e)) { + if ((gp->type == swift_type_dark_matter || + gp->type == swift_type_dark_matter_background) && + gpart_is_active(gp, e)) { const integertime_t ti_step = get_integer_timestep(gp->time_bin); const integertime_t ti_begin = @@ -3190,7 +3194,8 @@ void runner_do_timestep(struct runner *r, struct cell *c, int timer) { struct gpart *restrict gp = &gparts[k]; /* If the g-particle has no counterpart */ - if (gp->type == swift_type_dark_matter) { + if (gp->type == swift_type_dark_matter || + gp->type == swift_type_dark_matter_background) { /* need to be updated ? */ if (gpart_is_active(gp, e)) { diff --git a/src/runner_doiact_grav.h b/src/runner_doiact_grav.h index c6885746a29fd7b6bd828496316f8dad01c1b7da..b4ee8225a7aada8cf595ae7bca251d61b5226f64 100644 --- a/src/runner_doiact_grav.h +++ b/src/runner_doiact_grav.h @@ -182,12 +182,7 @@ static INLINE void runner_dopair_grav_pp_full( const float x_i = ci_cache->x[pid]; const float y_i = ci_cache->y[pid]; const float z_i = ci_cache->z[pid]; - - /* Some powers of the softening length */ const float h_i = ci_cache->epsilon[pid]; - const float h2_i = h_i * h_i; - const float h_inv_i = 1.f / h_i; - const float h_inv3_i = h_inv_i * h_inv_i * h_inv_i; /* Local accumulators for the acceleration and potential */ float a_x = 0.f, a_y = 0.f, a_z = 0.f, pot = 0.f; @@ -197,6 +192,7 @@ static INLINE void runner_dopair_grav_pp_full( swift_align_information(float, cj_cache->y, SWIFT_CACHE_ALIGNMENT); swift_align_information(float, cj_cache->z, SWIFT_CACHE_ALIGNMENT); swift_align_information(float, cj_cache->m, SWIFT_CACHE_ALIGNMENT); + swift_align_information(float, cj_cache->epsilon, SWIFT_CACHE_ALIGNMENT); swift_assume_size(gcount_padded_j, VEC_SIZE); /* Loop over every particle in the other cell. */ @@ -207,6 +203,7 @@ static INLINE void runner_dopair_grav_pp_full( const float y_j = cj_cache->y[pjd]; const float z_j = cj_cache->z[pjd]; const float mass_j = cj_cache->m[pjd]; + const float h_j = cj_cache->epsilon[pjd]; /* Compute the pairwise distance. */ float dx = x_j - x_i; @@ -222,8 +219,14 @@ static INLINE void runner_dopair_grav_pp_full( const float r2 = dx * dx + dy * dy + dz * dz; + /* Pick the maximal softening length of i and j */ + const float h = max(h_i, h_j); + const float h2 = h * h; + const float h_inv = 1.f / h; + const float h_inv_3 = h_inv * h_inv * h_inv; + #ifdef SWIFT_DEBUG_CHECKS - if (r2 == 0.f && h2_i == 0.) + if (r2 == 0.f && h2 == 0.) error("Interacting particles with 0 distance and 0 softening."); /* Check that particles have been drifted to the current time */ @@ -249,8 +252,7 @@ static INLINE void runner_dopair_grav_pp_full( /* Interact! */ float f_ij, pot_ij; - runner_iact_grav_pp_full(r2, h2_i, h_inv_i, h_inv3_i, mass_j, &f_ij, - &pot_ij); + runner_iact_grav_pp_full(r2, h2, h_inv, h_inv_3, mass_j, &f_ij, &pot_ij); /* Store it back */ a_x += f_ij * dx; @@ -325,12 +327,7 @@ static INLINE void runner_dopair_grav_pp_truncated( const float x_i = ci_cache->x[pid]; const float y_i = ci_cache->y[pid]; const float z_i = ci_cache->z[pid]; - - /* Some powers of the softening length */ const float h_i = ci_cache->epsilon[pid]; - const float h2_i = h_i * h_i; - const float h_inv_i = 1.f / h_i; - const float h_inv3_i = h_inv_i * h_inv_i * h_inv_i; /* Local accumulators for the acceleration and potential */ float a_x = 0.f, a_y = 0.f, a_z = 0.f, pot = 0.f; @@ -340,6 +337,7 @@ static INLINE void runner_dopair_grav_pp_truncated( swift_align_information(float, cj_cache->y, SWIFT_CACHE_ALIGNMENT); swift_align_information(float, cj_cache->z, SWIFT_CACHE_ALIGNMENT); swift_align_information(float, cj_cache->m, SWIFT_CACHE_ALIGNMENT); + swift_align_information(float, cj_cache->epsilon, SWIFT_CACHE_ALIGNMENT); swift_assume_size(gcount_padded_j, VEC_SIZE); /* Loop over every particle in the other cell. */ @@ -350,6 +348,7 @@ static INLINE void runner_dopair_grav_pp_truncated( const float y_j = cj_cache->y[pjd]; const float z_j = cj_cache->z[pjd]; const float mass_j = cj_cache->m[pjd]; + const float h_j = cj_cache->epsilon[pjd]; /* Compute the pairwise distance. */ float dx = x_j - x_i; @@ -363,8 +362,14 @@ static INLINE void runner_dopair_grav_pp_truncated( const float r2 = dx * dx + dy * dy + dz * dz; + /* Pick the maximal softening length of i and j */ + const float h = max(h_i, h_j); + const float h2 = h * h; + const float h_inv = 1.f / h; + const float h_inv_3 = h_inv * h_inv * h_inv; + #ifdef SWIFT_DEBUG_CHECKS - if (r2 == 0.f && h2_i == 0.) + if (r2 == 0.f && h2 == 0.) error("Interacting particles with 0 distance and 0 softening."); /* Check that particles have been drifted to the current time */ @@ -390,8 +395,8 @@ static INLINE void runner_dopair_grav_pp_truncated( /* Interact! */ float f_ij, pot_ij; - runner_iact_grav_pp_truncated(r2, h2_i, h_inv_i, h_inv3_i, mass_j, - r_s_inv, &f_ij, &pot_ij); + runner_iact_grav_pp_truncated(r2, h2, h_inv, h_inv_3, mass_j, r_s_inv, + &f_ij, &pot_ij); /* Store it back */ a_x += f_ij * dx; @@ -513,12 +518,12 @@ static INLINE void runner_dopair_grav_pm_full( const float r_max2 = r_max_j * r_max_j; const float theta_crit2 = e->gravity_properties->theta_crit2; - /* Note: 1.1 to avoid FP rounding false-positives */ - if (!gravity_M2P_accept(r_max2, theta_crit2 * 1.1, r2)) + /* Note: 0.99 and 1.1 to avoid FP rounding false-positives */ + if (!gravity_M2P_accept(r_max2, theta_crit2 * 1.1, r2, 0.99 * h_i)) error( "use_mpole[i] set when M2P accept fails CoM=[%e %e %e] pos=[%e %e " - "%e], rmax=%e", - CoM_j[0], CoM_j[1], CoM_j[2], x_i, y_i, z_i, r_max_j); + "%e], rmax=%e r=%e epsilon=%e", + CoM_j[0], CoM_j[1], CoM_j[2], x_i, y_i, z_i, r_max_j, sqrtf(r2), h_i); #endif /* Interact! */ @@ -644,8 +649,8 @@ static INLINE void runner_dopair_grav_pm_truncated( const float r_max2 = r_max_j * r_max_j; const float theta_crit2 = e->gravity_properties->theta_crit2; - /* 1.1 to avoid FP rounding false-positives */ - if (!gravity_M2P_accept(r_max2, theta_crit2 * 1.1, r2)) + /* 0.99 and 1.1 to avoid FP rounding false-positives */ + if (!gravity_M2P_accept(r_max2, theta_crit2 * 1.1, r2, 0.99 * h_i)) error( "use_mpole[i] set when M2P accept fails CoM=[%e %e %e] pos=[%e %e " "%e], rmax=%e", @@ -916,12 +921,7 @@ static INLINE void runner_doself_grav_pp_full( const float x_i = ci_cache->x[pid]; const float y_i = ci_cache->y[pid]; const float z_i = ci_cache->z[pid]; - - /* Some powers of the softening length */ const float h_i = ci_cache->epsilon[pid]; - const float h2_i = h_i * h_i; - const float h_inv_i = 1.f / h_i; - const float h_inv3_i = h_inv_i * h_inv_i * h_inv_i; /* Local accumulators for the acceleration */ float a_x = 0.f, a_y = 0.f, a_z = 0.f, pot = 0.f; @@ -931,6 +931,7 @@ static INLINE void runner_doself_grav_pp_full( swift_align_information(float, ci_cache->y, SWIFT_CACHE_ALIGNMENT); swift_align_information(float, ci_cache->z, SWIFT_CACHE_ALIGNMENT); swift_align_information(float, ci_cache->m, SWIFT_CACHE_ALIGNMENT); + swift_align_information(float, ci_cache->epsilon, SWIFT_CACHE_ALIGNMENT); swift_assume_size(gcount_padded, VEC_SIZE); /* Loop over every other particle in the cell. */ @@ -944,6 +945,7 @@ static INLINE void runner_doself_grav_pp_full( const float y_j = ci_cache->y[pjd]; const float z_j = ci_cache->z[pjd]; const float mass_j = ci_cache->m[pjd]; + const float h_j = ci_cache->epsilon[pjd]; /* Compute the pairwise (square) distance. */ /* Note: no need for periodic wrapping inside a cell */ @@ -952,8 +954,14 @@ static INLINE void runner_doself_grav_pp_full( const float dz = z_j - z_i; const float r2 = dx * dx + dy * dy + dz * dz; + /* Pick the maximal softening length of i and j */ + const float h = max(h_i, h_j); + const float h2 = h * h; + const float h_inv = 1.f / h; + const float h_inv_3 = h_inv * h_inv * h_inv; + #ifdef SWIFT_DEBUG_CHECKS - if (r2 == 0.f && h2_i == 0.) + if (r2 == 0.f && h2 == 0.) error("Interacting particles with 0 distance and 0 softening."); /* Check that particles have been drifted to the current time */ @@ -978,8 +986,7 @@ static INLINE void runner_doself_grav_pp_full( /* Interact! */ float f_ij, pot_ij; - runner_iact_grav_pp_full(r2, h2_i, h_inv_i, h_inv3_i, mass_j, &f_ij, - &pot_ij); + runner_iact_grav_pp_full(r2, h2, h_inv, h_inv_3, mass_j, &f_ij, &pot_ij); /* Store it back */ a_x += f_ij * dx; @@ -1039,12 +1046,7 @@ static INLINE void runner_doself_grav_pp_truncated( const float x_i = ci_cache->x[pid]; const float y_i = ci_cache->y[pid]; const float z_i = ci_cache->z[pid]; - - /* Some powers of the softening length */ const float h_i = ci_cache->epsilon[pid]; - const float h2_i = h_i * h_i; - const float h_inv_i = 1.f / h_i; - const float h_inv3_i = h_inv_i * h_inv_i * h_inv_i; /* Local accumulators for the acceleration and potential */ float a_x = 0.f, a_y = 0.f, a_z = 0.f, pot = 0.f; @@ -1054,6 +1056,7 @@ static INLINE void runner_doself_grav_pp_truncated( swift_align_information(float, ci_cache->y, SWIFT_CACHE_ALIGNMENT); swift_align_information(float, ci_cache->z, SWIFT_CACHE_ALIGNMENT); swift_align_information(float, ci_cache->m, SWIFT_CACHE_ALIGNMENT); + swift_align_information(float, ci_cache->epsilon, SWIFT_CACHE_ALIGNMENT); swift_assume_size(gcount_padded, VEC_SIZE); /* Loop over every other particle in the cell. */ @@ -1067,6 +1070,7 @@ static INLINE void runner_doself_grav_pp_truncated( const float y_j = ci_cache->y[pjd]; const float z_j = ci_cache->z[pjd]; const float mass_j = ci_cache->m[pjd]; + const float h_j = ci_cache->epsilon[pjd]; /* Compute the pairwise (square) distance. */ /* Note: no need for periodic wrapping inside a cell */ @@ -1076,8 +1080,14 @@ static INLINE void runner_doself_grav_pp_truncated( const float r2 = dx * dx + dy * dy + dz * dz; + /* Pick the maximal softening length of i and j */ + const float h = max(h_i, h_j); + const float h2 = h * h; + const float h_inv = 1.f / h; + const float h_inv_3 = h_inv * h_inv * h_inv; + #ifdef SWIFT_DEBUG_CHECKS - if (r2 == 0.f && h2_i == 0.) + if (r2 == 0.f && h2 == 0.) error("Interacting particles with 0 distance and 0 softening."); /* Check that particles have been drifted to the current time */ @@ -1102,8 +1112,8 @@ static INLINE void runner_doself_grav_pp_truncated( /* Interact! */ float f_ij, pot_ij; - runner_iact_grav_pp_truncated(r2, h2_i, h_inv_i, h_inv3_i, mass_j, - r_s_inv, &f_ij, &pot_ij); + runner_iact_grav_pp_truncated(r2, h2, h_inv, h_inv_3, mass_j, r_s_inv, + &f_ij, &pot_ij); /* Store it back */ a_x += f_ij * dx; @@ -1575,7 +1585,9 @@ static INLINE void runner_dopair_recursive_grav(struct runner *r, * option... */ /* Can we use M-M interactions ? */ - if (gravity_M2L_accept(multi_i->r_max, multi_j->r_max, theta_crit2, r2)) { + if (gravity_M2L_accept(multi_i->r_max, multi_j->r_max, theta_crit2, r2, + multi_i->m_pole.max_softening, + multi_j->m_pole.max_softening)) { /* Go M-M */ runner_dopair_grav_mm(r, ci, cj); @@ -1797,7 +1809,9 @@ static INLINE void runner_do_grav_long_range(struct runner *r, struct cell *ci, /* Are we in charge of this cell pair? */ if (gravity_M2L_accept(multi_top->r_max_rebuild, multi_j->r_max_rebuild, - theta_crit2, r2_rebuild)) { + theta_crit2, r2_rebuild, + multi_top->m_pole.max_softening, + multi_j->m_pole.max_softening)) { /* Call the PM interaction fucntion on the active sub-cells of ci */ runner_dopair_grav_mm_nonsym(r, ci, cj); diff --git a/src/serial_io.c b/src/serial_io.c index 0d367b1cf423d0471a0f6235fa3a1c6877e9f279..ca832a4beb16f8f39760c3c0a2950ecd003cc02b 100644 --- a/src/serial_io.c +++ b/src/serial_io.c @@ -460,6 +460,8 @@ void writeArray(const struct engine* e, hid_t grp, char* fileName, * @param bparts (output) Array of #bpart particles. * @param Ngas (output) The number of #part read from the file on that node. * @param Ngparts (output) The number of #gpart read from the file on that node. + * @param Ngparts_background (output) The number of background #gpart (type 2) + * read from the file on that node. * @param Nstars (output) The number of #spart read from the file on that node. * @param Nblackholes (output) The number of #bpart read from the file on that * node. @@ -492,12 +494,12 @@ void writeArray(const struct engine* e, hid_t grp, char* fileName, void read_ic_serial(char* fileName, const struct unit_system* internal_units, double dim[3], struct part** parts, struct gpart** gparts, struct spart** sparts, struct bpart** bparts, size_t* Ngas, - size_t* Ngparts, size_t* Nstars, size_t* Nblackholes, - int* flag_entropy, int with_hydro, int with_gravity, - int with_stars, int with_black_holes, int cleanup_h, - int cleanup_sqrt_a, double h, double a, int mpi_rank, - int mpi_size, MPI_Comm comm, MPI_Info info, int n_threads, - int dry_run) { + size_t* Ngparts, size_t* Ngparts_background, size_t* Nstars, + size_t* Nblackholes, int* flag_entropy, int with_hydro, + int with_gravity, int with_stars, int with_black_holes, + int cleanup_h, int cleanup_sqrt_a, double h, double a, + int mpi_rank, int mpi_size, MPI_Comm comm, MPI_Info info, + int n_threads, int dry_run) { hid_t h_file = 0, h_grp = 0; /* GADGET has only cubic boxes (in cosmological mode) */ @@ -510,11 +512,13 @@ void read_ic_serial(char* fileName, const struct unit_system* internal_units, long long offset[swift_type_count] = {0}; int dimension = 3; /* Assume 3D if nothing is specified */ size_t Ndm = 0; + size_t Ndm_background = 0; struct unit_system* ic_units = (struct unit_system*)malloc(sizeof(struct unit_system)); /* Initialise counters */ - *Ngas = 0, *Ngparts = 0, *Nstars = 0, *Nblackholes = 0; + *Ngas = 0, *Ngparts = 0, *Ngparts_background = 0, *Nstars = 0, + *Nblackholes = 0; /* First read some information about the content */ if (mpi_rank == 0) { @@ -675,11 +679,14 @@ void read_ic_serial(char* fileName, const struct unit_system* internal_units, /* Allocate memory to store all gravity particles */ if (with_gravity) { - Ndm = N[1]; + Ndm = N[swift_type_dark_matter]; + Ndm_background = N[swift_type_dark_matter_background]; *Ngparts = (with_hydro ? N[swift_type_gas] : 0) + N[swift_type_dark_matter] + + N[swift_type_dark_matter_background] + (with_stars ? N[swift_type_stars] : 0) + (with_black_holes ? N[swift_type_black_hole] : 0); + *Ngparts_background = Ndm_background; if (swift_memalign("gparts", (void**)gparts, gpart_align, *Ngparts * sizeof(struct gpart)) != 0) error("Error while allocating memory for gravity particles"); @@ -740,6 +747,13 @@ void read_ic_serial(char* fileName, const struct unit_system* internal_units, } break; + case swift_type_dark_matter_background: + if (with_gravity) { + Nparticles = Ndm_background; + darkmatter_read_particles(*gparts + Ndm, list, &num_fields); + } + break; + case swift_type_stars: if (with_stars) { Nparticles = *Nstars; @@ -789,17 +803,23 @@ void read_ic_serial(char* fileName, const struct unit_system* internal_units, /* Prepare the DM particles */ io_prepare_dm_gparts(&tp, *gparts, Ndm); + /* Prepare the DM background particles */ + io_prepare_dm_background_gparts(&tp, *gparts + Ndm, Ndm_background); + /* Duplicate the hydro particles into gparts */ - if (with_hydro) io_duplicate_hydro_gparts(&tp, *parts, *gparts, *Ngas, Ndm); + if (with_hydro) + io_duplicate_hydro_gparts(&tp, *parts, *gparts, *Ngas, + Ndm + Ndm_background); /* Duplicate the stars particles into gparts */ if (with_stars) - io_duplicate_stars_gparts(&tp, *sparts, *gparts, *Nstars, Ndm + *Ngas); + io_duplicate_stars_gparts(&tp, *sparts, *gparts, *Nstars, + Ndm + Ndm_background + *Ngas); /* Duplicate the black holes particles into gparts */ if (with_black_holes) io_duplicate_black_holes_gparts(&tp, *bparts, *gparts, *Nblackholes, - Ndm + *Ngas + *Nstars); + Ndm + Ndm_background + *Ngas + *Nstars); threadpool_clean(&tp); } @@ -847,6 +867,7 @@ void write_output_serial(struct engine* e, const char* baseName, const int with_cooling = e->policy & engine_policy_cooling; const int with_temperature = e->policy & engine_policy_temperature; const int with_fof = e->policy & engine_policy_fof; + const int with_DM_background = e->s->with_DM_background; #ifdef HAVE_VELOCIRAPTOR const int with_stf = (e->policy & engine_policy_structure_finding) && (e->s->gpart_group_data != NULL); @@ -864,7 +885,13 @@ void write_output_serial(struct engine* e, const char* baseName, // const size_t Nbaryons = Ngas + Nstars; // const size_t Ndm = Ntot > 0 ? Ntot - Nbaryons : 0; - /* Number of particles that we will write */ + size_t Ndm_background = 0; + if (with_DM_background) { + Ndm_background = io_count_dm_background_gparts(gparts, Ntot); + } + + /* Number of particles that we will write + * Recall that background particles are never inhibited and have no extras */ const size_t Ntot_written = e->s->nr_gparts - e->s->nr_inhibited_gparts - e->s->nr_extra_gparts; const size_t Ngas_written = @@ -876,7 +903,7 @@ void write_output_serial(struct engine* e, const char* baseName, const size_t Nbaryons_written = Ngas_written + Nstars_written + Nblackholes_written; const size_t Ndm_written = - Ntot_written > 0 ? Ntot_written - Nbaryons_written : 0; + Ntot_written > 0 ? Ntot_written - Nbaryons_written - Ndm_background : 0; /* File name */ char fileName[FILENAME_BUFFER_SIZE]; @@ -888,7 +915,8 @@ void write_output_serial(struct engine* e, const char* baseName, e->snapshot_output_count); /* Compute offset in the file and total number of particles */ - size_t N[swift_type_count] = {Ngas_written, Ndm_written, 0, 0, + size_t N[swift_type_count] = {Ngas_written, Ndm_written, + Ndm_background, 0, Nstars_written, Nblackholes_written}; long long N_total[swift_type_count] = {0}; long long offset[swift_type_count] = {0}; @@ -1242,7 +1270,8 @@ void write_output_serial(struct engine* e, const char* baseName, case swift_type_dark_matter: { if (Ntot == Ndm_written) { - /* This is a DM-only run without inhibited particles */ + /* This is a DM-only run without background or inhibited particles + */ Nparticles = Ntot; darkmatter_write_particles(gparts, list, &num_fields); if (with_fof) { @@ -1293,6 +1322,45 @@ void write_output_serial(struct engine* e, const char* baseName, } } break; + case swift_type_dark_matter_background: { + + /* Ok, we need to fish out the particles we want */ + Nparticles = Ndm_background; + + /* Allocate temporary array */ + if (swift_memalign("gparts_written", (void**)&gparts_written, + gpart_align, + Ndm_background * sizeof(struct gpart)) != 0) + error("Error while allocating temporart memory for gparts"); + + if (with_stf) { + if (swift_memalign("gpart_group_written", + (void**)&gpart_group_data_written, gpart_align, + Ndm_background * + sizeof(struct velociraptor_gpart_data)) != + 0) + error( + "Error while allocating temporart memory for gparts STF " + "data"); + } + + /* Collect the non-inhibited DM particles from gpart */ + io_collect_gparts_background_to_write( + gparts, e->s->gpart_group_data, gparts_written, + gpart_group_data_written, Ntot, Ndm_background, with_stf); + + /* Select the fields to write */ + darkmatter_write_particles(gparts_written, list, &num_fields); + if (with_fof) { + num_fields += fof_write_gparts(gparts_written, list + num_fields); + } + if (with_stf) { + num_fields += velociraptor_write_gparts(gpart_group_data_written, + list + num_fields); + } + + } break; + case swift_type_stars: { if (Nstars == Nstars_written) { diff --git a/src/serial_io.h b/src/serial_io.h index 7d994181b135e9758a9e3a52971366c2d871f627..c6ca7ad66df038791fbd62277f406a7f34340e04 100644 --- a/src/serial_io.h +++ b/src/serial_io.h @@ -38,12 +38,12 @@ void read_ic_serial(char* fileName, const struct unit_system* internal_units, double dim[3], struct part** parts, struct gpart** gparts, struct spart** sparts, struct bpart** bparts, size_t* Ngas, - size_t* Ngparts, size_t* Nstars, size_t* Nblackholes, - int* flag_entropy, int with_hydro, int with_gravity, - int with_stars, int with_black_holes, int cleanup_h, - int cleanup_sqrt_a, double h, double a, int mpi_rank, - int mpi_size, MPI_Comm comm, MPI_Info info, int n_threads, - int dry_run); + size_t* Ngparts, size_t* Ngparts_background, size_t* Nstars, + size_t* Nblackholes, int* flag_entropy, int with_hydro, + int with_gravity, int with_stars, int with_black_holes, + int cleanup_h, int cleanup_sqrt_a, double h, double a, + int mpi_rank, int mpi_size, MPI_Comm comm, MPI_Info info, + int n_threads, int dry_run); void write_output_serial(struct engine* e, const char* baseName, const struct unit_system* internal_units, @@ -56,6 +56,7 @@ void writeArray(const struct engine* e, hid_t grp, char* fileName, int mpi_rank, long long offset, const struct unit_system* internal_units, const struct unit_system* snapshot_units); -#endif + +#endif /* HAVE_HDF5 && WITH_MPI && !HAVE_PARALLEL_HDF5 */ #endif /* SWIFT_SERIAL_IO_H */ diff --git a/src/single_io.c b/src/single_io.c index 76a5630120df5e946093e9f046503f73bce706b6..017f9498ffc7d11e1a03d27eca733d2d417b9777 100644 --- a/src/single_io.c +++ b/src/single_io.c @@ -404,11 +404,11 @@ void read_ic_single(const char* fileName, const struct unit_system* internal_units, double dim[3], struct part** parts, struct gpart** gparts, struct spart** sparts, struct bpart** bparts, size_t* Ngas, - size_t* Ngparts, size_t* Nstars, size_t* Nblackholes, - int* flag_entropy, int with_hydro, int with_gravity, - int with_stars, int with_black_holes, int cleanup_h, - int cleanup_sqrt_a, double h, double a, int n_threads, - int dry_run) { + size_t* Ngparts, size_t* Ngparts_background, size_t* Nstars, + size_t* Nblackholes, int* flag_entropy, int with_hydro, + int with_gravity, int with_stars, int with_black_holes, + int cleanup_h, int cleanup_sqrt_a, double h, double a, + int n_threads, int dry_run) { hid_t h_file = 0, h_grp = 0; /* GADGET has only cubic boxes (in cosmological mode) */ @@ -419,9 +419,11 @@ void read_ic_single(const char* fileName, size_t N[swift_type_count] = {0}; int dimension = 3; /* Assume 3D if nothing is specified */ size_t Ndm = 0; + size_t Ndm_background = 0; /* Initialise counters */ - *Ngas = 0, *Ngparts = 0, *Nstars = 0, *Nblackholes = 0; + *Ngas = 0, *Ngparts = 0, *Ngparts_background = 0, *Nstars = 0, + *Nblackholes = 0; /* Open file */ /* message("Opening file '%s' as IC.", fileName); */ @@ -563,10 +565,13 @@ void read_ic_single(const char* fileName, /* Allocate memory to store all gravity particles */ if (with_gravity) { Ndm = N[swift_type_dark_matter]; + Ndm_background = N[swift_type_dark_matter_background]; *Ngparts = (with_hydro ? N[swift_type_gas] : 0) + N[swift_type_dark_matter] + + N[swift_type_dark_matter_background] + (with_stars ? N[swift_type_stars] : 0) + (with_black_holes ? N[swift_type_black_hole] : 0); + *Ngparts_background = Ndm_background; if (swift_memalign("gparts", (void**)gparts, gpart_align, *Ngparts * sizeof(struct gpart)) != 0) error("Error while allocating memory for gravity particles"); @@ -615,6 +620,13 @@ void read_ic_single(const char* fileName, } break; + case swift_type_dark_matter_background: + if (with_gravity) { + Nparticles = Ndm_background; + darkmatter_read_particles(*gparts + Ndm, list, &num_fields); + } + break; + case swift_type_stars: if (with_stars) { Nparticles = *Nstars; @@ -653,17 +665,23 @@ void read_ic_single(const char* fileName, /* Prepare the DM particles */ io_prepare_dm_gparts(&tp, *gparts, Ndm); + /* Prepare the DM background particles */ + io_prepare_dm_background_gparts(&tp, *gparts + Ndm, Ndm_background); + /* Duplicate the hydro particles into gparts */ - if (with_hydro) io_duplicate_hydro_gparts(&tp, *parts, *gparts, *Ngas, Ndm); + if (with_hydro) + io_duplicate_hydro_gparts(&tp, *parts, *gparts, *Ngas, + Ndm + Ndm_background); /* Duplicate the star particles into gparts */ if (with_stars) - io_duplicate_stars_gparts(&tp, *sparts, *gparts, *Nstars, Ndm + *Ngas); + io_duplicate_stars_gparts(&tp, *sparts, *gparts, *Nstars, + Ndm + Ndm_background + *Ngas); /* Duplicate the black hole particles into gparts */ if (with_black_holes) io_duplicate_black_holes_gparts(&tp, *bparts, *gparts, *Nblackholes, - Ndm + *Ngas + *Nstars); + Ndm + Ndm_background + *Ngas + *Nstars); threadpool_clean(&tp); } @@ -709,6 +727,7 @@ void write_output_single(struct engine* e, const char* baseName, const int with_cooling = e->policy & engine_policy_cooling; const int with_temperature = e->policy & engine_policy_temperature; const int with_fof = e->policy & engine_policy_fof; + const int with_DM_background = e->s->with_DM_background; #ifdef HAVE_VELOCIRAPTOR const int with_stf = (e->policy & engine_policy_structure_finding) && (e->s->gpart_group_data != NULL); @@ -724,7 +743,13 @@ void write_output_single(struct engine* e, const char* baseName, // const size_t Nbaryons = Ngas + Nstars; // const size_t Ndm = Ntot > 0 ? Ntot - Nbaryons : 0; - /* Number of particles that we will write */ + size_t Ndm_background = 0; + if (with_DM_background) { + Ndm_background = io_count_dm_background_gparts(gparts, Ntot); + } + + /* Number of particles that we will write + * Recall that background particles are never inhibited and have no extras */ const size_t Ntot_written = e->s->nr_gparts - e->s->nr_inhibited_gparts - e->s->nr_extra_gparts; const size_t Ngas_written = @@ -736,11 +761,12 @@ void write_output_single(struct engine* e, const char* baseName, const size_t Nbaryons_written = Ngas_written + Nstars_written + Nblackholes_written; const size_t Ndm_written = - Ntot_written > 0 ? Ntot_written - Nbaryons_written : 0; + Ntot_written > 0 ? Ntot_written - Nbaryons_written - Ndm_background : 0; /* Format things in a Gadget-friendly array */ long long N_total[swift_type_count] = { - (long long)Ngas_written, (long long)Ndm_written, 0, 0, + (long long)Ngas_written, (long long)Ndm_written, + (long long)Ndm_background, 0, (long long)Nstars_written, (long long)Nblackholes_written}; /* File name */ @@ -1040,7 +1066,7 @@ void write_output_single(struct engine* e, const char* baseName, case swift_type_dark_matter: { if (Ntot == Ndm_written) { - /* This is a DM-only run without inhibited particles */ + /* This is a DM-only run without background or inhibited particles */ N = Ntot; darkmatter_write_particles(gparts, list, &num_fields); if (with_fof) { @@ -1088,6 +1114,43 @@ void write_output_single(struct engine* e, const char* baseName, } } break; + case swift_type_dark_matter_background: { + + /* Ok, we need to fish out the particles we want */ + N = Ndm_background; + + /* Allocate temporary array */ + if (swift_memalign("gparts_written", (void**)&gparts_written, + gpart_align, + Ndm_background * sizeof(struct gpart)) != 0) + error("Error while allocating temporart memory for gparts"); + + if (with_stf) { + if (swift_memalign( + "gpart_group_written", (void**)&gpart_group_data_written, + gpart_align, + Ndm_background * sizeof(struct velociraptor_gpart_data)) != 0) + error( + "Error while allocating temporart memory for gparts STF " + "data"); + } + + /* Collect the non-inhibited DM particles from gpart */ + io_collect_gparts_background_to_write( + gparts, e->s->gpart_group_data, gparts_written, + gpart_group_data_written, Ntot, Ndm_background, with_stf); + + /* Select the fields to write */ + darkmatter_write_particles(gparts_written, list, &num_fields); + if (with_fof) { + num_fields += fof_write_gparts(gparts_written, list + num_fields); + } + if (with_stf) { + num_fields += velociraptor_write_gparts(gpart_group_data_written, + list + num_fields); + } + } break; + case swift_type_stars: { if (Nstars == Nstars_written) { @@ -1224,4 +1287,4 @@ void write_output_single(struct engine* e, const char* baseName, e->snapshot_output_count++; } -#endif /* HAVE_HDF5 */ +#endif /* HAVE_HDF5 && !WITH_MPI */ diff --git a/src/single_io.h b/src/single_io.h index 9ff04c893378d7f8c01621e7dbf387dc939d0157..47b575272c2fbe5b170eb4370743cd6830b99ae0 100644 --- a/src/single_io.h +++ b/src/single_io.h @@ -34,11 +34,11 @@ void read_ic_single(const char* fileName, const struct unit_system* internal_units, double dim[3], struct part** parts, struct gpart** gparts, struct spart** sparts, struct bpart** bparts, size_t* Ngas, - size_t* Ndm, size_t* Nstars, size_t* Nblackholes, - int* flag_entropy, int with_hydro, int with_gravity, - int with_stars, int with_black_holes, int cleanup_h, - int cleanup_sqrt_a, double h, double a, int nr_threads, - int dry_run); + size_t* Ndm, size_t* Ndm_background, size_t* Nstars, + size_t* Nblackholes, int* flag_entropy, int with_hydro, + int with_gravity, int with_stars, int with_black_holes, + int cleanup_h, int cleanup_sqrt_a, double h, double a, + int nr_threads, int dry_run); void write_output_single(struct engine* e, const char* baseName, const struct unit_system* internal_units, diff --git a/src/space.c b/src/space.c index 6594fab935d55e969faa7482e71f4a2b73954399..522347d03abff370b7e175f322166395d38e1321 100644 --- a/src/space.c +++ b/src/space.c @@ -1931,7 +1931,7 @@ void space_rebuild(struct space *s, int repartitioned, int verbose) { /* Check that the multipole construction went OK */ if (s->with_self_gravity) for (int k = 0; k < s->nr_cells; k++) - cell_check_multipole(&s->cells_top[k]); + cell_check_multipole(&s->cells_top[k], s->e->gravity_properties); #endif /* Clean up any stray sort indices in the cell buffer. */ @@ -3606,7 +3606,8 @@ void space_split_recursive(struct space *s, struct cell *c, if (s->with_self_gravity) { if (gcount > 0) { - gravity_P2M(c->grav.multipole, c->grav.parts, c->grav.count); + gravity_P2M(c->grav.multipole, c->grav.parts, c->grav.count, + e->gravity_properties); } else { @@ -3948,6 +3949,9 @@ void space_synchronize_particle_positions_mapper(void *map_data, int nr_gparts, if (gp->type == swift_type_dark_matter) continue; + else if (gp->type == swift_type_dark_matter_background) + continue; + else if (gp->type == swift_type_gas) { /* Get its gassy friend */ @@ -3991,6 +3995,10 @@ void space_synchronize_particle_positions_mapper(void *map_data, int nr_gparts, gp->mass = bp->mass; } + + else { + error("Invalid type!"); + } } } @@ -4526,6 +4534,7 @@ void space_convert_quantities(struct space *s, int verbose) { * @param hydro flag whether we are doing hydro or not? * @param self_gravity flag whether we are doing gravity or not? * @param star_formation flag whether we are doing star formation or not? + * @param DM_background Are we running with some DM background particles? * @param verbose Print messages to stdout or not. * @param dry_run If 1, just initialise stuff, don't do anything with the parts. * @@ -4540,7 +4549,8 @@ void space_init(struct space *s, struct swift_params *params, struct bpart *bparts, size_t Npart, size_t Ngpart, size_t Nspart, size_t Nbpart, int periodic, int replicate, int generate_gas_in_ics, int hydro, int self_gravity, - int star_formation, int verbose, int dry_run) { + int star_formation, int DM_background, int verbose, + int dry_run) { /* Clean-up everything */ bzero(s, sizeof(struct space)); @@ -4553,6 +4563,7 @@ void space_init(struct space *s, struct swift_params *params, s->with_self_gravity = self_gravity; s->with_hydro = hydro; s->with_star_formation = star_formation; + s->with_DM_background = DM_background; s->nr_parts = Npart; s->nr_gparts = Ngpart; s->nr_sparts = Nspart; @@ -4603,6 +4614,9 @@ void space_init(struct space *s, struct swift_params *params, error("Value of 'InitialConditions:replicate' (%d) is too small", replicate); if (replicate > 1) { + if (DM_background) + error("Can't replicate the space if background DM particles are in use."); + space_replicate(s, replicate, verbose); parts = s->parts; gparts = s->gparts; @@ -4841,16 +4855,19 @@ void space_replicate(struct space *s, int replicate, int verbose) { const size_t nr_parts = s->nr_parts; const size_t nr_gparts = s->nr_gparts; const size_t nr_sparts = s->nr_sparts; - const size_t nr_dm = nr_gparts - nr_parts - nr_sparts; + const size_t nr_bparts = s->nr_bparts; + const size_t nr_dm = nr_gparts - nr_parts - nr_sparts - nr_bparts; s->size_parts = s->nr_parts = nr_parts * factor; s->size_gparts = s->nr_gparts = nr_gparts * factor; s->size_sparts = s->nr_sparts = nr_sparts * factor; + s->size_bparts = s->nr_bparts = nr_bparts * factor; /* Allocate space for new particles */ struct part *parts = NULL; struct gpart *gparts = NULL; struct spart *sparts = NULL; + struct bpart *bparts = NULL; if (swift_memalign("parts", (void **)&parts, part_align, s->nr_parts * sizeof(struct part)) != 0) @@ -4864,6 +4881,10 @@ void space_replicate(struct space *s, int replicate, int verbose) { s->nr_sparts * sizeof(struct spart)) != 0) error("Failed to allocate new spart array."); + if (swift_memalign("bparts", (void **)&bparts, bpart_align, + s->nr_bparts * sizeof(struct bpart)) != 0) + error("Failed to allocate new bpart array."); + /* Replicate everything */ for (int i = 0; i < replicate; ++i) { for (int j = 0; j < replicate; ++j) { @@ -4875,6 +4896,8 @@ void space_replicate(struct space *s, int replicate, int verbose) { nr_parts * sizeof(struct part)); memcpy(sparts + offset * nr_sparts, s->sparts, nr_sparts * sizeof(struct spart)); + memcpy(bparts + offset * nr_bparts, s->bparts, + nr_bparts * sizeof(struct bpart)); memcpy(gparts + offset * nr_gparts, s->gparts, nr_gparts * sizeof(struct gpart)); @@ -4896,6 +4919,11 @@ void space_replicate(struct space *s, int replicate, int verbose) { sparts[n].x[1] += shift[1]; sparts[n].x[2] += shift[2]; } + for (size_t n = offset * nr_bparts; n < (offset + 1) * nr_bparts; ++n) { + bparts[n].x[0] += shift[0]; + bparts[n].x[1] += shift[1]; + bparts[n].x[2] += shift[2]; + } /* Set the correct links (recall gpart are sorted by type at start-up): first DM (unassociated gpart), then gas, then stars */ @@ -4917,6 +4945,16 @@ void space_replicate(struct space *s, int replicate, int verbose) { gparts[offset_gpart + n].id_or_neg_offset = -(offset_spart + n); } } + if (nr_bparts > 0 && nr_gparts > 0) { + const size_t offset_bpart = offset * nr_bparts; + const size_t offset_gpart = + offset * nr_gparts + nr_dm + nr_parts + nr_sparts; + + for (size_t n = 0; n < nr_bparts; ++n) { + bparts[offset_bpart + n].gpart = &gparts[offset_gpart + n]; + gparts[offset_gpart + n].id_or_neg_offset = -(offset_bpart + n); + } + } } } } @@ -4925,9 +4963,11 @@ void space_replicate(struct space *s, int replicate, int verbose) { swift_free("parts", s->parts); swift_free("gparts", s->gparts); swift_free("sparts", s->sparts); + swift_free("bparts", s->bparts); s->parts = parts; s->gparts = gparts; s->sparts = sparts; + s->bparts = bparts; /* Finally, update the domain size */ s->dim[0] *= replicate; diff --git a/src/space.h b/src/space.h index 1b31f0495890a68074225cc68c6acabd1abb53e8..0b332716645e733636b7ab0da57a0a31b28e3d31 100644 --- a/src/space.h +++ b/src/space.h @@ -103,6 +103,9 @@ struct space { /*! Are we doing star formation? */ int with_star_formation; + /*! Are we running with some DM background particles? */ + int with_DM_background; + /*! Width of the top-level cells. */ double width[3]; @@ -304,7 +307,8 @@ void space_init(struct space *s, struct swift_params *params, struct bpart *bparts, size_t Npart, size_t Ngpart, size_t Nspart, size_t Nbpart, int periodic, int replicate, int generate_gas_in_ics, int hydro, int gravity, - int star_formation, int verbose, int dry_run); + int star_formation, int DM_background, int verbose, + int dry_run); void space_sanitize(struct space *s); void space_map_cells_pre(struct space *s, int full, void (*fun)(struct cell *c, void *data), void *data); diff --git a/src/velociraptor_interface.c b/src/velociraptor_interface.c index 47c107d047e3abfcac32571f780cf52649a9c38d..8cb65f6ac13fb6d4f813d68656363640b082123f 100644 --- a/src/velociraptor_interface.c +++ b/src/velociraptor_interface.c @@ -283,6 +283,13 @@ void velociraptor_convert_particles_mapper(void *map_data, int nr_gparts, swift_parts[i].T = 0.f; break; + case swift_type_dark_matter_background: + + swift_parts[i].id = gparts[i].id_or_neg_offset; + swift_parts[i].u = 0.f; + swift_parts[i].T = 0.f; + break; + default: error("Particle type not handled by VELOCIraptor."); } @@ -334,13 +341,19 @@ void velociraptor_init(struct engine *e) { } else { sim_info.icosmologicalsim = 0; } - sim_info.izoomsim = 0; + + /* Are we running a zoom? */ + if (e->s->with_DM_background) { + sim_info.izoomsim = 1; + } else { + sim_info.izoomsim = 0; + } /* Tell VELOCIraptor what we have in the simulation */ sim_info.idarkmatter = (e->total_nr_gparts - e->total_nr_parts > 0); sim_info.igas = (e->policy & engine_policy_hydro); sim_info.istar = (e->policy & engine_policy_stars); - sim_info.ibh = 0; // sim_info.ibh = (e->policy&engine_policy_bh); + sim_info.ibh = (e->policy & engine_policy_black_holes); sim_info.iother = 0; /* Be nice, talk! */ @@ -443,14 +456,45 @@ void velociraptor_invoke(struct engine *e, const int linked_with_snap) { /* Are we running with cosmology? */ if (e->policy & engine_policy_cosmology) { sim_info.icosmologicalsim = 1; - sim_info.izoomsim = 0; - const size_t total_nr_baryons = e->total_nr_parts + e->total_nr_sparts; - const size_t total_nr_dmparts = e->total_nr_gparts - total_nr_baryons; - sim_info.interparticlespacing = sim_info.period / cbrt(total_nr_dmparts); + + /* Are we running a zoom? */ + if (e->s->with_DM_background) { + sim_info.izoomsim = 1; + } else { + sim_info.izoomsim = 0; + } + + /* Collect the mass of the non-background gpart */ + double high_res_DM_mass = 0.; + for (size_t i = 0; i < e->s->nr_gparts; ++i) { + const struct gpart *gp = &e->s->gparts[i]; + if (gp->type == swift_type_dark_matter && + gp->time_bin != time_bin_inhibited && + gp->time_bin != time_bin_not_created) { + high_res_DM_mass = gp->mass; + break; + } + } + +#ifdef WITH_MPI + /* We need to all-reduce this in case one of the nodes had 0 DM particles. + */ + MPI_Allreduce(MPI_IN_PLACE, &high_res_DM_mass, 1, MPI_DOUBLE, MPI_MAX, + MPI_COMM_WORLD); +#endif + + /* Linking length based on the mean DM inter-particle separation + * in the zoom region and assuming the mean density of the Universe + * is used in the zoom region. */ + const double mean_matter_density = + e->cosmology->Omega_m * e->cosmology->critical_density_0; + sim_info.interparticlespacing = + cbrt(high_res_DM_mass / mean_matter_density); + } else { - sim_info.icosmologicalsim = 0; sim_info.izoomsim = 0; - sim_info.interparticlespacing = -1; + sim_info.icosmologicalsim = 0; + sim_info.interparticlespacing = -1.; } /* Set the spatial extent of the simulation volume */ diff --git a/tests/testGravityDerivatives.c b/tests/testGravityDerivatives.c index f31967de7075bccfb2c7fb19c1ba262aa12da54f..032460d9f519c455e485e0dddfc5f8742138d60a 100644 --- a/tests/testGravityDerivatives.c +++ b/tests/testGravityDerivatives.c @@ -955,12 +955,11 @@ int main(int argc, char* argv[]) { const double r_inv = 1. / sqrt(r2); const double r = r2 * r_inv; const double eps = r / 10.; - const double eps_inv = 1. / eps; /* Compute all derivatives */ struct potential_derivatives_M2L pot; - potential_derivatives_compute_M2L(dx, dy, dz, r2, r_inv, eps, eps_inv, - periodic, r_s_inv, &pot); + potential_derivatives_compute_M2L(dx, dy, dz, r2, r_inv, eps, periodic, + r_s_inv, &pot); /* Minimal value we care about */ const double min = 1e-9; diff --git a/tests/testPotentialPair.c b/tests/testPotentialPair.c index 064c86d42f8df907d1ffaaab164b6a2f8b534b19..d5fbda36a9ef79352f79627b5cef908030401da2 100644 --- a/tests/testPotentialPair.c +++ b/tests/testPotentialPair.c @@ -125,7 +125,8 @@ int main(int argc, char *argv[]) { struct gravity_props props; props.theta_crit2 = 0.; - props.epsilon_cur = eps; + props.epsilon_DM_cur = eps; + props.epsilon_baryon_cur = eps; e.gravity_properties = &props; struct runner r; @@ -386,7 +387,7 @@ int main(int argc, char *argv[]) { /* Now let's make a multipole out of it. */ gravity_reset(ci.grav.multipole); - gravity_P2M(ci.grav.multipole, ci.grav.parts, ci.grav.count); + gravity_P2M(ci.grav.multipole, ci.grav.parts, ci.grav.count, &props); gravity_multipole_print(&ci.grav.multipole->m_pole); diff --git a/tests/testPotentialSelf.c b/tests/testPotentialSelf.c index 10eb499570a591daaf0de2e011f2346077905e8e..ff55558aff77441458e822cfa11922bd2dabfa06 100644 --- a/tests/testPotentialSelf.c +++ b/tests/testPotentialSelf.c @@ -115,7 +115,8 @@ int main(int argc, char *argv[]) { struct gravity_props props; props.a_smooth = 1.25; - props.epsilon_cur = eps; + props.epsilon_DM_cur = eps; + props.epsilon_baryon_cur = eps; e.gravity_properties = &props; struct runner r; diff --git a/tests/testReading.c b/tests/testReading.c index b2cf743a066920c3d28ea8768334a6a8b1c9b5f0..47f8d0dfdc043985c6344abecf31e605226e6899 100644 --- a/tests/testReading.c +++ b/tests/testReading.c @@ -28,7 +28,7 @@ int main(int argc, char *argv[]) { - size_t Ngas = 0, Ngpart = 0, Nspart = 0, Nbpart = 0; + size_t Ngas = 0, Ngpart = 0, Ngpart_background = 0, Nspart = 0, Nbpart = 0; int flag_entropy_ICs = -1; int i, j, k; double dim[3]; @@ -51,8 +51,15 @@ int main(int argc, char *argv[]) { /* Read data */ read_ic_single("input.hdf5", &us, dim, &parts, &gparts, &sparts, &bparts, - &Ngas, &Ngpart, &Nspart, &Nbpart, &flag_entropy_ICs, 1, 1, 0, - 0, 0, 0, 1., 1., 1, 0); + &Ngas, &Ngpart, &Ngpart_background, &Nspart, &Nbpart, + &flag_entropy_ICs, + /*with_hydro=*/1, + /*with_gravity=*/1, + /*with_stars=*/0, + /*with_black_holes=*/0, + /*cleanup_h=*/0, + /*cleanup_sqrt_a=*/0, + /*h=*/1., /*a=*/1., /*n_threads=*/1, /*dry_run=*/0); /* Check global properties read are correct */ assert(dim[0] == boxSize); diff --git a/tests/testSelectOutput.c b/tests/testSelectOutput.c index 0be250e48cb2748093c8cd8c1381303c3060c9ba..9797406d91b74c7e9effe14da7b4f0100d901148 100644 --- a/tests/testSelectOutput.c +++ b/tests/testSelectOutput.c @@ -84,7 +84,7 @@ int main(int argc, char *argv[]) { clocks_set_cpufreq(cpufreq); char *base_name = "testSelectOutput"; - size_t Ngas = 0, Ngpart = 0, Nspart = 0, Nbpart = 0; + size_t Ngas = 0, Ngpart = 0, Ngpart_background = 0, Nspart = 0, Nbpart = 0; int flag_entropy_ICs = -1; int periodic = 1; double dim[3]; @@ -112,8 +112,15 @@ int main(int argc, char *argv[]) { /* Read data */ message("Reading initial conditions."); read_ic_single("input.hdf5", &us, dim, &parts, &gparts, &sparts, &bparts, - &Ngas, &Ngpart, &Nspart, &Nbpart, &flag_entropy_ICs, 1, 0, 0, - 0, 0, 0, 1., 1., 1, 0); + &Ngas, &Ngpart, &Ngpart_background, &Nspart, &Nbpart, + &flag_entropy_ICs, + /*with_hydro=*/1, + /*with_gravity=*/0, + /*with_stars=*/0, + /*with_black_holes=*/0, + /*cleanup_h=*/0, + /*cleanup_sqrt_a=*/0, + /*h=*/1., /*a=*/1., /*n_threads=*/1, /*dry_run=*/0); /* pseudo initialization of the space */ message("Initialization of the space.");