diff --git a/configure.ac b/configure.ac index 4b883488cce19e78eec4fbc705357a687b29ace6..94819b51245649e63ace4f4843b39b4286f0cdc6 100644 --- a/configure.ac +++ b/configure.ac @@ -1186,8 +1186,9 @@ AC_ARG_WITH([subgrid], with_subgrid_cooling=none with_subgrid_chemistry=none with_subgrid_tracers=none -with_subgrid_hydro=none +with_subgrid_entropy_floor=none with_subgrid_stars=none +with_subgrid_star_formation=none with_subgrid_feedback=none case "$with_subgrid" in @@ -1200,16 +1201,18 @@ case "$with_subgrid" in with_subgrid_cooling=grackle with_subgrid_chemistry=GEAR with_subgrid_tracers=none - with_subgrid_hydro=gadget2 + with_subgrid_entropy_floor=none with_subgrid_stars=GEAR + with_subgrid_star_formation=none with_subgrid_feedback=thermal ;; EAGLE) with_subgrid_cooling=EAGLE with_subgrid_chemistry=EAGLE with_subgrid_tracers=EAGLE - with_subgrid_hydro=gadget2 - with_subgrid_stars=none + with_subgrid_entropy_floor=EAGLE + with_subgrid_stars=EAGLE + with_subgrid_star_formation=EAGLE with_subgrid_feedback=none ;; *) @@ -1247,14 +1250,6 @@ AC_ARG_WITH([hydro], [with_hydro="gadget2"] ) -if test "$with_subgrid" != "none"; then - if test "$with_hydro" != "gadget2"; then - AC_MSG_ERROR([Cannot provide with-subgrid and with-hydro together]) - else - with_hydro="$with_subgrid_hydro" - fi -fi - case "$with_hydro" in gadget2) AC_DEFINE([GADGET2_SPH], [1], [Gadget-2 SPH]) @@ -1586,7 +1581,7 @@ esac # Stellar model. AC_ARG_WITH([stars], [AS_HELP_STRING([--with-stars=<model>], - [Stellar model to use @<:@none, GEAR, debug default: none@:>@] + [Stellar model to use @<:@none, EAGLE, GEAR, debug default: none@:>@] )], [with_stars="$withval"], [with_stars="none"] @@ -1601,10 +1596,14 @@ if test "$with_subgrid" != "none"; then fi case "$with_stars" in + EAGLE) + AC_DEFINE([STARS_EAGLE], [1], [EAGLE stellar model]) + ;; GEAR) AC_DEFINE([STARS_GEAR], [1], [GEAR stellar model]) ;; none) + AC_DEFINE([STARS_NONE], [1], [None stellar model]) ;; *) @@ -1682,6 +1681,62 @@ case "$with_potential" in ;; esac +# Entropy floor +AC_ARG_WITH([entropy-floor], + [AS_HELP_STRING([--with-entropy-floor=<floor>], + [entropy floor @<:@none, EAGLE, default: none@:>@] + )], + [with_entropy_floor="$withval"], + [with_entropy_floor="none"] +) +if test "$with_subgrid" != "none"; then + if test "$with_entropy_floor" != "none"; then + AC_MSG_ERROR([Cannot provide with-subgrid and with-entropy-floor together]) + else + with_entropy_floor="$with_subgrid_entropy_floor" + fi +fi + +case "$with_entropy_floor" in + none) + AC_DEFINE([ENTROPY_FLOOR_NONE], [1], [No entropy floor]) + ;; + EAGLE) + AC_DEFINE([ENTROPY_FLOOR_EAGLE], [1], [EAGLE entropy floor]) + ;; + *) + AC_MSG_ERROR([Unknown entropy floor model]) + ;; +esac + +# Star formation +AC_ARG_WITH([star-formation], + [AS_HELP_STRING([--with-star-formation=<sfm>], + [star formation @<:@none, EAGLE, default: none@:>@] + )], + [with_star_formation="$withval"], + [with_star_formation="none"] +) +if test "$with_subgrid" != "none"; then + if test "$with_star_formation" != "none"; then + AC_MSG_ERROR([Cannot provide with-subgrid and with-star-formation together]) + else + with_star_formation="$with_subgrid_star_formation" + fi +fi + +case "$with_star_formation" in + none) + AC_DEFINE([STAR_FORMATION_NONE], [1], [No star formation]) + ;; + EAGLE) + AC_DEFINE([STAR_FORMATION_EAGLE], [1], [EAGLE star formation model (Schaye and Dalla Vecchia (2008))]) + ;; + *) + AC_MSG_ERROR([Unknown star formation model]) + ;; +esac + # Gravity multipole order AC_ARG_WITH([multipole-order], [AS_HELP_STRING([--with-multipole-order=<order>], @@ -1773,11 +1828,13 @@ AC_MSG_RESULT([ Make gravity glass : $gravity_glass_making External potential : $with_potential - Cooling function : $with_cooling - Chemistry : $with_chemistry - Tracers : $with_tracers - Stellar model : $with_stars - Feedback model : $with_feedback + Entropy floor : $with_entropy_floor + Cooling function : $with_cooling + Chemistry : $with_chemistry + Tracers : $with_tracers + Stellar model : $with_stars + Star formation model : $with_star_formation + Feedback model : $with_feedback Individual timers : $enable_timers Task debugging : $enable_task_debugging diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in index b310ce3a6edbc79eef4524dbadbbde20515621ae..fe48398e4b0dd4bfdede6781e708bd222b6eedae 100644 --- a/doc/Doxyfile.in +++ b/doc/Doxyfile.in @@ -772,6 +772,8 @@ INPUT += @top_srcdir@/src/cooling/const_lambda INPUT += @top_srcdir@/src/cooling/Compton INPUT += @top_srcdir@/src/cooling/EAGLE INPUT += @top_srcdir@/src/chemistry/EAGLE +INPUT += @top_srcdir@/src/entropy_floor/EAGLE +INPUT += @top_srcdir@/src/star_formation/EAGLE INPUT += @top_srcdir@/src/tracers/EAGLE # This tag can be used to specify the character encoding of the source files diff --git a/doc/RTD/source/SubgridModels/EAGLE/EAGLE_entropy_floor.svg b/doc/RTD/source/SubgridModels/EAGLE/EAGLE_entropy_floor.svg new file mode 100644 index 0000000000000000000000000000000000000000..383b074fc947ed072dc50015152ba694b929c611 --- /dev/null +++ b/doc/RTD/source/SubgridModels/EAGLE/EAGLE_entropy_floor.svg @@ -0,0 +1,2102 @@ +<?xml version="1.0" encoding="utf-8" standalone="no"?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" + "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<!-- Created with matplotlib (http://matplotlib.org/) --> +<svg height="226pt" version="1.1" viewBox="0 0 226 226" width="226pt" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> + <defs> + <style type="text/css"> +*{stroke-linecap:butt;stroke-linejoin:round;} + </style> + </defs> + <g id="figure_1"> + <g id="patch_1"> + <path d="M 0 226.8 +L 226.8 226.8 +L 226.8 0 +L 0 0 +z +" style="fill:#ffffff;"/> + </g> + <g id="axes_1"> + <g id="patch_2"> + <path d="M 34.02 197.316 +L 224.532 197.316 +L 224.532 2.268 +L 34.02 2.268 +z +" style="fill:#ffffff;"/> + </g> + <g id="PolyCollection_1"> + <defs> + <path d="M 77.714425 -156.365649 +L 77.714425 -14.805175 +L 250.907152 -14.805175 +L 250.907152 -156.365649 +L 250.907152 -156.365649 +L 77.714425 -156.365649 +z +" id="m8f9d87720a" style="stroke:#e6e6e6;"/> + </defs> + <g clip-path="url(#p107a2e5a22)"> + <use style="fill:#e6e6e6;stroke:#e6e6e6;" x="0" xlink:href="#m8f9d87720a" y="226.8"/> + </g> + </g> + <g id="PolyCollection_2"> + <path clip-path="url(#p107a2e5a22)" d="M 146.991516 49022.756825 +L 146.991516 85.113175 +L 250.907152 -12.410825 +L 250.907152 49022.756825 +L 250.907152 49022.756825 +L 146.991516 49022.756825 +z +" style="fill:#e6e6e6;stroke:#e6e6e6;"/> + </g> + <g id="PathCollection_1"> + <defs> + <path d="M 0 1 +C 0.265203 1 0.51958 0.894634 0.707107 0.707107 +C 0.894634 0.51958 1 0.265203 1 0 +C 1 -0.265203 0.894634 -0.51958 0.707107 -0.707107 +C 0.51958 -0.894634 0.265203 -1 0 -1 +C -0.265203 -1 -0.51958 -0.894634 -0.707107 -0.707107 +C -0.894634 -0.51958 -1 -0.265203 -1 0 +C -1 0.265203 -0.894634 0.51958 -0.707107 0.707107 +C -0.51958 0.894634 -0.265203 1 0 1 +z +" id="me37d9803e9" style="stroke:#000000;"/> + </defs> + <g clip-path="url(#p107a2e5a22)"> + <use style="stroke:#000000;" x="77.714425" xlink:href="#me37d9803e9" y="70.434351"/> + </g> + </g> + <g id="PathCollection_2"> + <g clip-path="url(#p107a2e5a22)"> + <use style="stroke:#000000;" x="146.991516" xlink:href="#me37d9803e9" y="85.113175"/> + </g> + </g> + <g id="matplotlib.axis_1"> + <g id="xtick_1"> + <g id="line2d_1"> + <defs> + <path d="M 0 0 +L 0 3.5 +" id="mddab006ef2" style="stroke:#000000;stroke-width:0.8;"/> + </defs> + <g> + <use style="stroke:#000000;stroke-width:0.8;" x="60.395152" xlink:href="#mddab006ef2" y="197.316"/> + </g> + </g> + <g id="text_1"> + <!-- $10^{-6}$ --> + <defs> + <path d="M 29.09375 67.796875 +L 11.09375 58.703125 +L 11.09375 57.296875 +C 12.296875 57.796875 13.40625 58.203125 13.796875 58.40625 +C 15.59375 59.109375 17.296875 59.5 18.296875 59.5 +C 20.40625 59.5 21.296875 57.984375 21.296875 54.765625 +L 21.296875 9.25 +C 21.296875 5.921875 20.5 3.625 18.90625 2.703125 +C 17.40625 1.8125 16 1.5 11.796875 1.5 +L 11.796875 0 +L 39.40625 0 +L 39.40625 1.5 +C 31.5 1.5 29.90625 2.5 29.90625 7.34375 +L 29.90625 67.609375 +z +" id="Nimbus_Roman_No9_L_Regular-49"/> + <path d="M 25.40625 68 +C 19.90625 68 15.703125 66.3125 12 62.8125 +C 6.203125 57.203125 2.40625 45.703125 2.40625 34 +C 2.40625 23.109375 5.703125 11.40625 10.40625 5.8125 +C 14.09375 1.40625 19.203125 -1 25 -1 +C 30.09375 -1 34.40625 0.703125 38 4.203125 +C 43.796875 9.703125 47.59375 21.3125 47.59375 33.40625 +C 47.59375 53.90625 38.5 68 25.40625 68 +z +M 25.09375 65.40625 +C 33.5 65.40625 38 54.109375 38 33.203125 +C 38 12.3125 33.59375 1.609375 25 1.609375 +C 16.40625 1.609375 12 12.3125 12 33.109375 +C 12 54.3125 16.5 65.40625 25.09375 65.40625 +z +" id="Nimbus_Roman_No9_L_Regular-48"/> + <path d="M 65.90625 23 +C 67.59375 23 69.40625 23 69.40625 25 +C 69.40625 27 67.59375 27 65.90625 27 +L 11.796875 27 +C 10.09375 27 8.296875 27 8.296875 25 +C 8.296875 23 10.09375 23 11.796875 23 +z +" id="CMSY10-0"/> + <path d="M 44.59375 68.609375 +C 33.203125 67.609375 27.40625 65.703125 20.09375 60.609375 +C 9.296875 52.90625 3.40625 41.5 3.40625 28.15625 +C 3.40625 19.5 6.09375 10.75 10.40625 5.78125 +C 14.203125 1.390625 19.59375 -1 25.796875 -1 +C 38.203125 -1 46.796875 8.453125 46.796875 22.203125 +C 46.796875 34.9375 39.5 43 28 43 +C 23.59375 43 21.5 42.296875 15.203125 38.5 +C 17.90625 53.609375 29.09375 64.40625 44.796875 67 +z +M 24.203125 38.40625 +C 32.796875 38.40625 37.796875 31.25 37.796875 18.8125 +C 37.796875 7.875 33.90625 1.8125 26.90625 1.8125 +C 18.09375 1.8125 12.703125 11.15625 12.703125 26.5625 +C 12.703125 31.640625 13.5 34.421875 15.5 35.921875 +C 17.59375 37.5 20.703125 38.40625 24.203125 38.40625 +z +" id="Nimbus_Roman_No9_L_Regular-54"/> + </defs> + <g transform="translate(50.706631 211.234498)scale(0.1 -0.1)"> + <use transform="scale(0.996264)" xlink:href="#Nimbus_Roman_No9_L_Regular-49"/> + <use transform="translate(49.8132 0)scale(0.996264)" xlink:href="#Nimbus_Roman_No9_L_Regular-48"/> + <use transform="translate(99.626401 36.163231)scale(0.737241)" xlink:href="#CMSY10-0"/> + <use transform="translate(156.909271 36.163231)scale(0.737241)" xlink:href="#Nimbus_Roman_No9_L_Regular-54"/> + </g> + </g> + </g> + <g id="xtick_2"> + <g id="line2d_2"> + <g> + <use style="stroke:#000000;stroke-width:0.8;" x="95.033698" xlink:href="#mddab006ef2" y="197.316"/> + </g> + </g> + <g id="text_2"> + <!-- $10^{-4}$ --> + <defs> + <path d="M 47.203125 23.390625 +L 37 23.390625 +L 37 68 +L 32.59375 68 +L 1.203125 23.390625 +L 1.203125 17 +L 29.296875 17 +L 29.296875 0.5 +L 37 0.5 +L 37 17 +L 47.203125 17 +z +M 29.203125 23.390625 +L 5.203125 23.390625 +L 29.203125 57.78125 +z +" id="Nimbus_Roman_No9_L_Regular-52"/> + </defs> + <g transform="translate(85.345176 211.234498)scale(0.1 -0.1)"> + <use transform="scale(0.996264)" xlink:href="#Nimbus_Roman_No9_L_Regular-49"/> + <use transform="translate(49.8132 0)scale(0.996264)" xlink:href="#Nimbus_Roman_No9_L_Regular-48"/> + <use transform="translate(99.626401 36.163231)scale(0.737241)" xlink:href="#CMSY10-0"/> + <use transform="translate(156.909271 36.163231)scale(0.737241)" xlink:href="#Nimbus_Roman_No9_L_Regular-52"/> + </g> + </g> + </g> + <g id="xtick_3"> + <g id="line2d_3"> + <g> + <use style="stroke:#000000;stroke-width:0.8;" x="129.672243" xlink:href="#mddab006ef2" y="197.316"/> + </g> + </g> + <g id="text_3"> + <!-- $10^{-2}$ --> + <defs> + <path d="M 47.5 13.671875 +L 46.203125 14.171875 +C 42.5 8.5 41.203125 7.59375 36.703125 7.59375 +L 12.796875 7.59375 +L 29.59375 25.140625 +C 38.5 34.40625 42.40625 41.984375 42.40625 49.765625 +C 42.40625 59.734375 34.296875 67.390625 23.90625 67.390625 +C 18.40625 67.390625 13.203125 65.203125 9.5 61.21875 +C 6.296875 57.8125 4.796875 54.625 3.09375 47.546875 +L 5.203125 47.046875 +C 9.203125 56.8125 12.796875 60 19.703125 60 +C 28.09375 60 33.796875 54.3125 33.796875 45.9375 +C 33.796875 38.171875 29.203125 28.90625 20.796875 20.03125 +L 3 1.203125 +L 3 0 +L 42 0 +z +" id="Nimbus_Roman_No9_L_Regular-50"/> + </defs> + <g transform="translate(119.983722 211.234498)scale(0.1 -0.1)"> + <use transform="scale(0.996264)" xlink:href="#Nimbus_Roman_No9_L_Regular-49"/> + <use transform="translate(49.8132 0)scale(0.996264)" xlink:href="#Nimbus_Roman_No9_L_Regular-48"/> + <use transform="translate(99.626401 36.163231)scale(0.737241)" xlink:href="#CMSY10-0"/> + <use transform="translate(156.909271 36.163231)scale(0.737241)" xlink:href="#Nimbus_Roman_No9_L_Regular-50"/> + </g> + </g> + </g> + <g id="xtick_4"> + <g id="line2d_4"> + <g> + <use style="stroke:#000000;stroke-width:0.8;" x="164.310789" xlink:href="#mddab006ef2" y="197.316"/> + </g> + </g> + <g id="text_4"> + <!-- $10^{0}$ --> + <g transform="translate(157.486382 211.234498)scale(0.1 -0.1)"> + <use transform="scale(0.996264)" xlink:href="#Nimbus_Roman_No9_L_Regular-49"/> + <use transform="translate(49.8132 0)scale(0.996264)" xlink:href="#Nimbus_Roman_No9_L_Regular-48"/> + <use transform="translate(99.626401 36.163231)scale(0.737241)" xlink:href="#Nimbus_Roman_No9_L_Regular-48"/> + </g> + </g> + </g> + <g id="xtick_5"> + <g id="line2d_5"> + <g> + <use style="stroke:#000000;stroke-width:0.8;" x="198.949334" xlink:href="#mddab006ef2" y="197.316"/> + </g> + </g> + <g id="text_5"> + <!-- $10^{2}$ --> + <g transform="translate(192.124927 211.234498)scale(0.1 -0.1)"> + <use transform="scale(0.996264)" xlink:href="#Nimbus_Roman_No9_L_Regular-49"/> + <use transform="translate(49.8132 0)scale(0.996264)" xlink:href="#Nimbus_Roman_No9_L_Regular-48"/> + <use transform="translate(99.626401 36.163231)scale(0.737241)" xlink:href="#Nimbus_Roman_No9_L_Regular-50"/> + </g> + </g> + </g> + <g id="text_6"> + <!-- ${\rm Density}~n_{\rm H}~[{\rm cm^{-3}}]$ --> + <defs> + <path d="M 10.40625 10.609375 +C 10.40625 3.390625 9.203125 2.09375 1.59375 2.09375 +L 1.59375 0 +L 30 0 +C 41.59375 0 52.09375 3.28125 58.296875 8.875 +C 64.796875 14.75 68.5 23.625 68.5 33.296875 +C 68.5 42.28125 65.5 50.046875 60 55.53125 +C 53.203125 62.40625 42.296875 66 28.59375 66 +L 1.59375 66 +L 1.59375 64.09375 +C 9.5 63.390625 10.40625 62.5 10.40625 55.078125 +z +M 20.59375 58.40625 +C 20.59375 61.5 21.703125 62.296875 25.796875 62.296875 +C 34.40625 62.296875 40.90625 60.703125 45.703125 57.3125 +C 53.5 51.921875 57.59375 43.359375 57.59375 32.609375 +C 57.59375 20.84375 53.5 12.46875 45.40625 7.78125 +C 40.296875 4.90625 34.5 3.703125 25.796875 3.703125 +C 21.796875 3.703125 20.59375 4.59375 20.59375 7.78125 +z +" id="Nimbus_Roman_No9_L_Regular-68"/> + <path d="M 40.796875 16.453125 +C 36 8.8125 31.703125 5.90625 25.296875 5.90625 +C 19.59375 5.90625 15.296875 8.8125 12.40625 14.53125 +C 10.59375 18.34375 9.90625 21.65625 9.703125 27.796875 +L 40.5 27.796875 +C 39.703125 34.265625 38.703125 37.140625 36.203125 40.328125 +C 33.203125 43.921875 28.59375 46 23.40625 46 +C 18.40625 46 13.703125 44.203125 9.90625 40.796875 +C 5.203125 36.703125 2.5 29.59375 2.5 21.40625 +C 2.5 7.59375 9.703125 -1 21.203125 -1 +C 30.703125 -1 38.203125 4.921875 42.40625 15.75 +z +M 9.90625 31 +C 11 38.734375 14.40625 42.40625 20.5 42.40625 +C 26.59375 42.40625 29 39.609375 30.296875 31 +z +" id="Nimbus_Roman_No9_L_Regular-101"/> + <path d="M 1.59375 40.296875 +C 2.203125 40.59375 3.203125 40.703125 4.296875 40.703125 +C 7.09375 40.703125 8 39.203125 8 34.296875 +L 8 9.5 +C 8 3.796875 6.90625 2.40625 1.796875 2 +L 1.796875 0.5 +L 23 0.5 +L 23 2 +C 17.90625 2.40625 16.40625 3.59375 16.40625 7.203125 +L 16.40625 35.296875 +C 21.203125 39.796875 23.40625 41 26.703125 41 +C 31.59375 41 34 37.90625 34 31.296875 +L 34 10.40625 +C 34 4.09375 32.703125 2.40625 27.703125 2 +L 27.703125 0.5 +L 48.5 0.5 +L 48.5 2 +C 43.59375 2.5 42.40625 3.703125 42.40625 8.59375 +L 42.40625 31.5 +C 42.40625 40.90625 38 46.5 30.59375 46.5 +C 26 46.5 22.90625 44.796875 16.09375 38.40625 +L 16.09375 46.296875 +L 15.40625 46.5 +C 10.5 44.703125 7.09375 43.59375 1.59375 42 +z +" id="Nimbus_Roman_No9_L_Regular-110"/> + <path d="M 31.5 31.40625 +L 31.09375 45 +L 30 45 +L 29.796875 44.796875 +C 28.90625 44.09375 28.796875 44 28.40625 44 +C 27.796875 44 26.796875 44.203125 25.703125 44.703125 +C 23.5 45.546875 21.296875 46 18.703125 46 +C 10.796875 46 5.09375 40.875 5.09375 33.65625 +C 5.09375 28.0625 8.296875 24.046875 16.796875 19.234375 +L 22.59375 15.9375 +C 26.09375 13.9375 27.796875 11.515625 27.796875 8.421875 +C 27.796875 4 24.59375 1.203125 19.5 1.203125 +C 16.09375 1.203125 13 2.484375 11.09375 4.65625 +C 9 7.109375 8.09375 9.375 6.796875 15 +L 5.203125 15 +L 5.203125 -0.609375 +L 6.5 -0.609375 +C 7.203125 0.515625 7.59375 0.75 8.796875 0.75 +C 9.703125 0.75 11.09375 0.546875 13.40625 -0.03125 +C 16.203125 -0.609375 18.90625 -1 20.703125 -1 +C 28.40625 -1 34.796875 4.8125 34.796875 11.828125 +C 34.796875 16.828125 32.40625 20.140625 26.40625 23.75 +L 15.59375 30.15625 +C 12.796875 31.765625 11.296875 34.28125 11.296875 36.984375 +C 11.296875 41 14.40625 43.796875 19 43.796875 +C 24.703125 43.796875 27.703125 40.359375 30 31.40625 +z +" id="Nimbus_Roman_No9_L_Regular-115"/> + <path d="M 17.5 45.765625 +L 2 40.296875 +L 2 38.8125 +L 2.796875 38.90625 +C 4 39.09375 5.296875 39.203125 6.203125 39.203125 +C 8.59375 39.203125 9.5 37.59375 9.5 33.203125 +L 9.5 10 +C 9.5 2.796875 8.5 1.703125 1.59375 1.703125 +L 1.59375 0 +L 25.296875 0 +L 25.296875 1.5 +C 18.703125 2 17.90625 2.984375 17.90625 10.15625 +L 17.90625 45.46875 +z +M 12.796875 68 +C 10.09375 68 7.796875 65.703125 7.796875 62.90625 +C 7.796875 60.109375 10 57.796875 12.796875 57.796875 +C 15.703125 57.796875 18 60 18 62.90625 +C 18 65.703125 15.703125 68 12.796875 68 +z +" id="Nimbus_Roman_No9_L_Regular-105"/> + <path d="M 25.5 45 +L 15.40625 45 +L 15.40625 56.59375 +C 15.40625 57.59375 15.296875 57.90625 14.703125 57.90625 +C 14 57 13.40625 56.09375 12.703125 55.09375 +C 8.90625 49.59375 4.59375 44.796875 3 44.390625 +C 1.90625 43.65625 1.296875 42.9375 1.296875 42.421875 +C 1.296875 42.109375 1.40625 41.90625 1.703125 41.90625 +L 7 41.90625 +L 7 11.734375 +C 7 3.3125 10 -1 15.90625 -1 +C 20.796875 -1 24.59375 1.40625 27.90625 6.609375 +L 26.59375 7.703125 +C 24.5 5.203125 22.796875 4.203125 20.59375 4.203125 +C 16.90625 4.203125 15.40625 6.921875 15.40625 13.234375 +L 15.40625 41.90625 +L 25.5 41.90625 +z +" id="Nimbus_Roman_No9_L_Regular-116"/> + <path d="M 47.5 45 +L 34 45 +L 34 43.5 +C 37.203125 43.5 38.796875 42.59375 38.796875 40.984375 +C 38.796875 40.578125 38.703125 39.984375 38.40625 39.28125 +L 28.703125 11.59375 +L 17.203125 37.140625 +C 16.59375 38.5625 16.203125 39.875 16.203125 40.96875 +C 16.203125 42.796875 17.703125 43.5 22 43.5 +L 22 45 +L 1.40625 45 +L 1.40625 43.59375 +C 4 43.203125 5.703125 42.09375 6.5 40.390625 +L 17.90625 15.703125 +L 18.203125 14.890625 +L 19.703125 11.890625 +C 22.5 6.875 24.09375 3.265625 24.09375 1.75 +C 24.09375 0.25 21.796875 -6.078125 20.09375 -9.09375 +C 18.703125 -11.703125 16.5 -13.609375 15.09375 -13.609375 +C 14.5 -13.609375 13.59375 -13.40625 12.59375 -12.90625 +C 10.703125 -12.203125 9 -11.796875 7.296875 -11.796875 +C 5 -11.796875 3 -13.796875 3 -16.203125 +C 3 -19.5 6.203125 -22 10.40625 -22 +C 17.09375 -22 21.90625 -16.390625 27.296875 -1.9375 +L 42.703125 38.984375 +C 44 42.203125 45.09375 43.203125 47.5 43.5 +z +" id="Nimbus_Roman_No9_L_Regular-121"/> + <path d="M 46 11.546875 +L 43.90625 8.9375 +C 41 5.234375 39.203125 3.625 37.796875 3.625 +C 37 3.625 36.203125 4.421875 36.203125 5.21875 +C 36.203125 5.9375 36.203125 5.9375 37.59375 11.53125 +L 43.296875 32.1875 +C 43.796875 34.28125 44.203125 36.484375 44.203125 37.890625 +C 44.203125 41.5 41.5 44 37.59375 44 +C 31.203125 44 24.90625 38 14.59375 21.96875 +L 21.296875 43.796875 +L 21 43.984375 +C 15.59375 42.890625 13.5 42.5 4.796875 40.90625 +L 4.796875 39.21875 +C 9.90625 39.21875 11.203125 38.625 11.203125 36.609375 +C 11.203125 36 11.09375 35.40625 11 34.90625 +L 1.40625 -0.1875 +L 8.90625 -0.1875 +C 13.59375 15.65625 14.5 17.875 18.90625 24.6875 +C 24.90625 33.890625 30 38.921875 33.703125 38.921875 +C 35.203125 38.921875 36.09375 37.8125 36.09375 36 +C 36.09375 34.8125 35.5 31.5 34.703125 28.390625 +L 30.296875 11.84375 +C 29 6.734375 28.703125 5.328125 28.703125 4.328125 +C 28.703125 0.515625 30.09375 -1.078125 33.40625 -1.078125 +C 37.90625 -1.078125 40.5 1.03125 47.40625 10.25 +z +" id="Nimbus_Roman_No9_L_Regular_Italic-110"/> + <path d="M 20.90625 36 +L 20.90625 55.203125 +C 20.90625 62.34375 22 63.421875 29.703125 64.125 +L 29.703125 66 +L 1.90625 66 +L 1.90625 64.125 +C 9.59375 63.421875 10.703125 62.328125 10.703125 55.109375 +L 10.703125 11.703125 +C 10.703125 3.28125 9.703125 2.09375 1.90625 2.09375 +L 1.90625 0 +L 29.703125 0 +L 29.703125 1.890625 +C 22.203125 2.484375 20.90625 3.78125 20.90625 10.921875 +L 20.90625 31.59375 +L 51.203125 31.59375 +L 51.203125 11.828125 +C 51.203125 3.296875 50.203125 2.09375 42.40625 2.09375 +L 42.40625 0 +L 70.203125 0 +L 70.203125 1.890625 +C 62.703125 2.484375 61.40625 3.78125 61.40625 10.875 +L 61.40625 55.140625 +C 61.40625 62.328125 62.5 63.421875 70.203125 64.125 +L 70.203125 66 +L 42.40625 66 +L 42.40625 64.125 +C 50.09375 63.421875 51.203125 62.34375 51.203125 55.203125 +L 51.203125 36 +z +" id="Nimbus_Roman_No9_L_Regular-72"/> + <path d="M 25.5 -25 +L 25.5 -20.984375 +L 15.796875 -20.984375 +L 15.796875 71 +L 25.5 71 +L 25.5 75.015625 +L 11.796875 75.015625 +L 11.796875 -25 +z +" id="CMR10-91"/> + <path d="M 39.796875 15.59375 +C 35 8.59375 31.40625 6.203125 25.703125 6.203125 +C 16.59375 6.203125 10.203125 14.203125 10.203125 25.703125 +C 10.203125 36 15.703125 43.09375 23.796875 43.09375 +C 27.40625 43.09375 28.703125 42 29.703125 38.296875 +L 30.296875 36.09375 +C 31.09375 33.296875 32.90625 31.5 35 31.5 +C 37.59375 31.5 39.796875 33.40625 39.796875 35.703125 +C 39.796875 41.296875 32.796875 46 24.40625 46 +C 19.5 46 14.40625 44 10.296875 40.40625 +C 5.296875 36 2.5 29.203125 2.5 21.296875 +C 2.5 8.296875 10.40625 -1 21.5 -1 +C 26 -1 30 0.59375 33.59375 3.703125 +C 36.296875 6.09375 38.203125 8.796875 41.203125 14.703125 +z +" id="Nimbus_Roman_No9_L_Regular-99"/> + <path d="M 1.90625 39.796875 +C 3.203125 40.09375 4 40.203125 5.09375 40.203125 +C 7.703125 40.203125 8.59375 38.59375 8.59375 33.78125 +L 8.59375 8.421875 +C 8.59375 3 7.203125 1.5 1.59375 1.5 +L 1.59375 0 +L 23.796875 0 +L 23.796875 1.5 +C 18.5 1.5 17 2.59375 17 6.53125 +L 17 34.90625 +C 17 35.09375 17.796875 36.09375 18.5 36.796875 +C 21 39.09375 25.296875 40.796875 28.796875 40.796875 +C 33.203125 40.796875 35.40625 37.265625 35.40625 30.1875 +L 35.40625 8.25 +C 35.40625 2.609375 34.296875 1.5 28.59375 1.5 +L 28.59375 0 +L 51 0 +L 51 1.5 +C 45.296875 1.5 43.796875 3.203125 43.796875 9.421875 +L 43.796875 34.703125 +C 46.796875 39 50.09375 40.796875 54.703125 40.796875 +C 60.40625 40.796875 62.203125 38.09375 62.203125 29.796875 +L 62.203125 8.703125 +C 62.203125 3 61.40625 2.203125 55.59375 1.5 +L 55.59375 0 +L 77.5 0 +L 77.5 1.5 +L 74.90625 1.796875 +C 71.90625 1.796875 70.59375 3.59375 70.59375 7.5 +L 70.59375 28.15625 +C 70.59375 39.984375 66.703125 46 59 46 +C 53.203125 46 48.09375 43.40625 42.703125 37.609375 +C 40.90625 43.296875 37.5 46 32.09375 46 +C 27.703125 46 24.90625 44.59375 16.59375 38.296875 +L 16.59375 45.796875 +L 15.90625 46 +C 10.796875 44.09375 7.40625 43 1.90625 41.5 +z +" id="Nimbus_Roman_No9_L_Regular-109"/> + <path d="M 15.296875 33.40625 +C 21.203125 33.40625 23.5 33.203125 25.90625 32.3125 +C 32.09375 30.109375 36 24.40625 36 17.5 +C 36 9.109375 30.296875 2.609375 22.90625 2.609375 +C 20.203125 2.609375 18.203125 3.3125 14.5 5.703125 +C 11.5 7.5 9.796875 8.203125 8.09375 8.203125 +C 5.796875 8.203125 4.296875 6.8125 4.296875 4.703125 +C 4.296875 1.203125 8.59375 -1 15.59375 -1 +C 23.296875 -1 31.203125 1.609375 35.90625 5.703125 +C 40.59375 9.8125 43.203125 15.609375 43.203125 22.3125 +C 43.203125 27.40625 41.59375 32.109375 38.703125 35.203125 +C 36.703125 37.40625 34.796875 38.609375 30.40625 40.5 +C 37.296875 45.203125 39.796875 48.90625 39.796875 54.3125 +C 39.796875 62.40625 33.40625 68 24.203125 68 +C 19.203125 68 14.796875 66.3125 11.203125 63.109375 +C 8.203125 60.40625 6.703125 57.796875 4.5 51.796875 +L 6 51.40625 +C 10.09375 58.703125 14.59375 62 20.90625 62 +C 27.40625 62 31.90625 57.609375 31.90625 51.3125 +C 31.90625 47.703125 30.40625 44.109375 27.90625 41.609375 +C 24.90625 38.609375 22.09375 37.109375 15.296875 34.703125 +z +" id="Nimbus_Roman_No9_L_Regular-51"/> + <path d="M 15.90625 75.015625 +L 2.203125 75.015625 +L 2.203125 71 +L 11.90625 71 +L 11.90625 -20.984375 +L 2.203125 -20.984375 +L 2.203125 -25 +L 15.90625 -25 +z +" id="CMR10-93"/> + </defs> + <g transform="translate(91.250474 222.339856)scale(0.1 -0.1)"> + <use transform="translate(0 15.050129)scale(0.996264)" xlink:href="#Nimbus_Roman_No9_L_Regular-68"/> + <use transform="translate(71.929985 15.050129)scale(0.996264)" xlink:href="#Nimbus_Roman_No9_L_Regular-101"/> + <use transform="translate(116.163554 15.050129)scale(0.996264)" xlink:href="#Nimbus_Roman_No9_L_Regular-110"/> + <use transform="translate(165.976754 15.050129)scale(0.996264)" xlink:href="#Nimbus_Roman_No9_L_Regular-115"/> + <use transform="translate(204.73046 15.050129)scale(0.996264)" xlink:href="#Nimbus_Roman_No9_L_Regular-105"/> + <use transform="translate(232.42563 15.050129)scale(0.996264)" xlink:href="#Nimbus_Roman_No9_L_Regular-116"/> + <use transform="translate(260.120799 15.050129)scale(0.996264)" xlink:href="#Nimbus_Roman_No9_L_Regular-121"/> + <use transform="translate(341.163113 15.050129)scale(0.996264)" xlink:href="#Nimbus_Roman_No9_L_Regular_Italic-110"/> + <use transform="translate(390.976313 0)scale(0.737241)" xlink:href="#Nimbus_Roman_No9_L_Regular-72"/> + <use transform="translate(475.932143 15.050129)scale(0.996264)" xlink:href="#CMR10-91"/> + <use transform="translate(503.52765 15.050129)scale(0.996264)" xlink:href="#Nimbus_Roman_No9_L_Regular-99"/> + <use transform="translate(547.761218 15.050129)scale(0.996264)" xlink:href="#Nimbus_Roman_No9_L_Regular-109"/> + <use transform="translate(625.269588 51.213361)scale(0.737241)" xlink:href="#CMSY10-0"/> + <use transform="translate(682.552458 51.213361)scale(0.737241)" xlink:href="#Nimbus_Roman_No9_L_Regular-51"/> + <use transform="translate(719.912632 15.050129)scale(0.996264)" xlink:href="#CMR10-93"/> + </g> + </g> + </g> + <g id="matplotlib.axis_2"> + <g id="ytick_1"> + <g id="line2d_6"> + <defs> + <path d="M 0 0 +L -3.5 0 +" id="mec8c027021" style="stroke:#000000;stroke-width:0.8;"/> + </defs> + <g> + <use style="stroke:#000000;stroke-width:0.8;" x="34.02" xlink:href="#mec8c027021" y="163.232825"/> + </g> + </g> + <g id="text_7"> + <!-- $10^{2}$ --> + <g transform="translate(13.371186 166.692074)scale(0.1 -0.1)"> + <use transform="scale(0.996264)" xlink:href="#Nimbus_Roman_No9_L_Regular-49"/> + <use transform="translate(49.8132 0)scale(0.996264)" xlink:href="#Nimbus_Roman_No9_L_Regular-48"/> + <use transform="translate(99.626401 36.163231)scale(0.737241)" xlink:href="#Nimbus_Roman_No9_L_Regular-50"/> + </g> + </g> + </g> + <g id="ytick_2"> + <g id="line2d_7"> + <g> + <use style="stroke:#000000;stroke-width:0.8;" x="34.02" xlink:href="#mec8c027021" y="114.470825"/> + </g> + </g> + <g id="text_8"> + <!-- $10^{3}$ --> + <g transform="translate(13.371186 117.930074)scale(0.1 -0.1)"> + <use transform="scale(0.996264)" xlink:href="#Nimbus_Roman_No9_L_Regular-49"/> + <use transform="translate(49.8132 0)scale(0.996264)" xlink:href="#Nimbus_Roman_No9_L_Regular-48"/> + <use transform="translate(99.626401 36.163231)scale(0.737241)" xlink:href="#Nimbus_Roman_No9_L_Regular-51"/> + </g> + </g> + </g> + <g id="ytick_3"> + <g id="line2d_8"> + <g> + <use style="stroke:#000000;stroke-width:0.8;" x="34.02" xlink:href="#mec8c027021" y="65.708825"/> + </g> + </g> + <g id="text_9"> + <!-- $10^{4}$ --> + <g transform="translate(13.371186 69.168074)scale(0.1 -0.1)"> + <use transform="scale(0.996264)" xlink:href="#Nimbus_Roman_No9_L_Regular-49"/> + <use transform="translate(49.8132 0)scale(0.996264)" xlink:href="#Nimbus_Roman_No9_L_Regular-48"/> + <use transform="translate(99.626401 36.163231)scale(0.737241)" xlink:href="#Nimbus_Roman_No9_L_Regular-52"/> + </g> + </g> + </g> + <g id="ytick_4"> + <g id="line2d_9"> + <g> + <use style="stroke:#000000;stroke-width:0.8;" x="34.02" xlink:href="#mec8c027021" y="16.946825"/> + </g> + </g> + <g id="text_10"> + <!-- $10^{5}$ --> + <defs> + <path d="M 18.09375 59 +L 37.703125 59 +C 39.296875 59 39.703125 59.203125 40 59.90625 +L 43.796875 68.796875 +L 42.90625 69.5 +C 41.40625 67.40625 40.40625 66.90625 38.296875 66.90625 +L 17.40625 66.90625 +L 6.5 43.109375 +C 6.40625 42.90625 6.40625 42.8125 6.40625 42.609375 +C 6.40625 42.109375 6.796875 41.8125 7.59375 41.8125 +C 10.796875 41.8125 14.796875 41.109375 18.90625 39.796875 +C 30.40625 36.078125 35.703125 29.84375 35.703125 19.90625 +C 35.703125 10.25 29.59375 2.703125 21.796875 2.703125 +C 19.796875 2.703125 18.09375 3.40625 15.09375 5.625 +C 11.90625 7.9375 9.59375 8.9375 7.5 8.9375 +C 4.59375 8.9375 3.203125 7.734375 3.203125 5.21875 +C 3.203125 1.40625 7.90625 -1 15.40625 -1 +C 23.796875 -1 31 1.71875 36 6.84375 +C 40.59375 11.375 42.703125 17.09375 42.703125 24.734375 +C 42.703125 31.96875 40.796875 36.59375 35.796875 41.609375 +C 31.40625 46.046875 25.703125 48.34375 13.90625 50.453125 +z +" id="Nimbus_Roman_No9_L_Regular-53"/> + </defs> + <g transform="translate(13.371186 20.406074)scale(0.1 -0.1)"> + <use transform="scale(0.996264)" xlink:href="#Nimbus_Roman_No9_L_Regular-49"/> + <use transform="translate(49.8132 0)scale(0.996264)" xlink:href="#Nimbus_Roman_No9_L_Regular-48"/> + <use transform="translate(99.626401 36.163231)scale(0.737241)" xlink:href="#Nimbus_Roman_No9_L_Regular-53"/> + </g> + </g> + </g> + <g id="ytick_5"> + <g id="line2d_10"> + <defs> + <path d="M 0 0 +L -2 0 +" id="mc0ad7d39b4" style="stroke:#000000;stroke-width:0.6;"/> + </defs> + <g> + <use style="stroke:#000000;stroke-width:0.6;" x="34.02" xlink:href="#mc0ad7d39b4" y="197.316"/> + </g> + </g> + </g> + <g id="ytick_6"> + <g id="line2d_11"> + <g> + <use style="stroke:#000000;stroke-width:0.6;" x="34.02" xlink:href="#mc0ad7d39b4" y="188.729438"/> + </g> + </g> + </g> + <g id="ytick_7"> + <g id="line2d_12"> + <g> + <use style="stroke:#000000;stroke-width:0.6;" x="34.02" xlink:href="#mc0ad7d39b4" y="182.637175"/> + </g> + </g> + </g> + <g id="ytick_8"> + <g id="line2d_13"> + <g> + <use style="stroke:#000000;stroke-width:0.6;" x="34.02" xlink:href="#mc0ad7d39b4" y="177.911649"/> + </g> + </g> + </g> + <g id="ytick_9"> + <g id="line2d_14"> + <g> + <use style="stroke:#000000;stroke-width:0.6;" x="34.02" xlink:href="#mc0ad7d39b4" y="174.050613"/> + </g> + </g> + </g> + <g id="ytick_10"> + <g id="line2d_15"> + <g> + <use style="stroke:#000000;stroke-width:0.6;" x="34.02" xlink:href="#mc0ad7d39b4" y="170.786154"/> + </g> + </g> + </g> + <g id="ytick_11"> + <g id="line2d_16"> + <g> + <use style="stroke:#000000;stroke-width:0.6;" x="34.02" xlink:href="#mc0ad7d39b4" y="167.958351"/> + </g> + </g> + </g> + <g id="ytick_12"> + <g id="line2d_17"> + <g> + <use style="stroke:#000000;stroke-width:0.6;" x="34.02" xlink:href="#mc0ad7d39b4" y="165.464051"/> + </g> + </g> + </g> + <g id="ytick_13"> + <g id="line2d_18"> + <g> + <use style="stroke:#000000;stroke-width:0.6;" x="34.02" xlink:href="#mc0ad7d39b4" y="148.554"/> + </g> + </g> + </g> + <g id="ytick_14"> + <g id="line2d_19"> + <g> + <use style="stroke:#000000;stroke-width:0.6;" x="34.02" xlink:href="#mc0ad7d39b4" y="139.967438"/> + </g> + </g> + </g> + <g id="ytick_15"> + <g id="line2d_20"> + <g> + <use style="stroke:#000000;stroke-width:0.6;" x="34.02" xlink:href="#mc0ad7d39b4" y="133.875175"/> + </g> + </g> + </g> + <g id="ytick_16"> + <g id="line2d_21"> + <g> + <use style="stroke:#000000;stroke-width:0.6;" x="34.02" xlink:href="#mc0ad7d39b4" y="129.149649"/> + </g> + </g> + </g> + <g id="ytick_17"> + <g id="line2d_22"> + <g> + <use style="stroke:#000000;stroke-width:0.6;" x="34.02" xlink:href="#mc0ad7d39b4" y="125.288613"/> + </g> + </g> + </g> + <g id="ytick_18"> + <g id="line2d_23"> + <g> + <use style="stroke:#000000;stroke-width:0.6;" x="34.02" xlink:href="#mc0ad7d39b4" y="122.024154"/> + </g> + </g> + </g> + <g id="ytick_19"> + <g id="line2d_24"> + <g> + <use style="stroke:#000000;stroke-width:0.6;" x="34.02" xlink:href="#mc0ad7d39b4" y="119.196351"/> + </g> + </g> + </g> + <g id="ytick_20"> + <g id="line2d_25"> + <g> + <use style="stroke:#000000;stroke-width:0.6;" x="34.02" xlink:href="#mc0ad7d39b4" y="116.702051"/> + </g> + </g> + </g> + <g id="ytick_21"> + <g id="line2d_26"> + <g> + <use style="stroke:#000000;stroke-width:0.6;" x="34.02" xlink:href="#mc0ad7d39b4" y="99.792"/> + </g> + </g> + </g> + <g id="ytick_22"> + <g id="line2d_27"> + <g> + <use style="stroke:#000000;stroke-width:0.6;" x="34.02" xlink:href="#mc0ad7d39b4" y="91.205438"/> + </g> + </g> + </g> + <g id="ytick_23"> + <g id="line2d_28"> + <g> + <use style="stroke:#000000;stroke-width:0.6;" x="34.02" xlink:href="#mc0ad7d39b4" y="85.113175"/> + </g> + </g> + </g> + <g id="ytick_24"> + <g id="line2d_29"> + <g> + <use style="stroke:#000000;stroke-width:0.6;" x="34.02" xlink:href="#mc0ad7d39b4" y="80.387649"/> + </g> + </g> + </g> + <g id="ytick_25"> + <g id="line2d_30"> + <g> + <use style="stroke:#000000;stroke-width:0.6;" x="34.02" xlink:href="#mc0ad7d39b4" y="76.526613"/> + </g> + </g> + </g> + <g id="ytick_26"> + <g id="line2d_31"> + <g> + <use style="stroke:#000000;stroke-width:0.6;" x="34.02" xlink:href="#mc0ad7d39b4" y="73.262154"/> + </g> + </g> + </g> + <g id="ytick_27"> + <g id="line2d_32"> + <g> + <use style="stroke:#000000;stroke-width:0.6;" x="34.02" xlink:href="#mc0ad7d39b4" y="70.434351"/> + </g> + </g> + </g> + <g id="ytick_28"> + <g id="line2d_33"> + <g> + <use style="stroke:#000000;stroke-width:0.6;" x="34.02" xlink:href="#mc0ad7d39b4" y="67.940051"/> + </g> + </g> + </g> + <g id="ytick_29"> + <g id="line2d_34"> + <g> + <use style="stroke:#000000;stroke-width:0.6;" x="34.02" xlink:href="#mc0ad7d39b4" y="51.03"/> + </g> + </g> + </g> + <g id="ytick_30"> + <g id="line2d_35"> + <g> + <use style="stroke:#000000;stroke-width:0.6;" x="34.02" xlink:href="#mc0ad7d39b4" y="42.443438"/> + </g> + </g> + </g> + <g id="ytick_31"> + <g id="line2d_36"> + <g> + <use style="stroke:#000000;stroke-width:0.6;" x="34.02" xlink:href="#mc0ad7d39b4" y="36.351175"/> + </g> + </g> + </g> + <g id="ytick_32"> + <g id="line2d_37"> + <g> + <use style="stroke:#000000;stroke-width:0.6;" x="34.02" xlink:href="#mc0ad7d39b4" y="31.625649"/> + </g> + </g> + </g> + <g id="ytick_33"> + <g id="line2d_38"> + <g> + <use style="stroke:#000000;stroke-width:0.6;" x="34.02" xlink:href="#mc0ad7d39b4" y="27.764613"/> + </g> + </g> + </g> + <g id="ytick_34"> + <g id="line2d_39"> + <g> + <use style="stroke:#000000;stroke-width:0.6;" x="34.02" xlink:href="#mc0ad7d39b4" y="24.500154"/> + </g> + </g> + </g> + <g id="ytick_35"> + <g id="line2d_40"> + <g> + <use style="stroke:#000000;stroke-width:0.6;" x="34.02" xlink:href="#mc0ad7d39b4" y="21.672351"/> + </g> + </g> + </g> + <g id="ytick_36"> + <g id="line2d_41"> + <g> + <use style="stroke:#000000;stroke-width:0.6;" x="34.02" xlink:href="#mc0ad7d39b4" y="19.178051"/> + </g> + </g> + </g> + <g id="ytick_37"> + <g id="line2d_42"> + <g> + <use style="stroke:#000000;stroke-width:0.6;" x="34.02" xlink:href="#mc0ad7d39b4" y="2.268"/> + </g> + </g> + </g> + <g id="text_11"> + <!-- ${\rm Temperature}~T~[{\rm K}]$ --> + <defs> + <path d="M 25.40625 62 +L 25.40625 11.734375 +C 25.40625 3.1875 24.296875 2.09375 16 2.09375 +L 16 0 +L 45.203125 0 +L 45.203125 2.09375 +C 37 2.09375 35.59375 3.390625 35.59375 10.734375 +L 35.59375 62 +L 41 62 +C 52.40625 62 54.59375 60.203125 56.90625 49.203125 +L 59.296875 49.203125 +L 58.703125 66.203125 +L 2.296875 66.203125 +L 1.703125 49.203125 +L 4.09375 49.203125 +C 6.5 60.09375 8.796875 62 20 62 +z +" id="Nimbus_Roman_No9_L_Regular-84"/> + <path d="M 0.90625 39.3125 +C 1.796875 39.40625 2.5 39.40625 3.40625 39.40625 +C 6.796875 39.40625 7.5 38.40625 7.5 33.671875 +L 7.5 -13.359375 +C 7.5 -18.578125 6.40625 -19.703125 0.5 -20.296875 +L 0.5 -22 +L 24.703125 -22 +L 24.703125 -20.203125 +C 17.203125 -20.203125 15.90625 -19.09375 15.90625 -12.75 +L 15.90625 3.109375 +C 19.40625 -0.203125 21.796875 -1.203125 26 -1.203125 +C 37.796875 -1.203125 47 10.046875 47 24.609375 +C 47 37.0625 40 46 30.296875 46 +C 24.703125 46 20.296875 43.5 15.90625 38.09375 +L 15.90625 45.796875 +L 15.296875 46 +C 9.90625 43.90625 6.40625 42.59375 0.90625 40.90625 +z +M 15.90625 33.375 +C 15.90625 36.390625 21.5 40 26.09375 40 +C 33.5 40 38.40625 32.359375 38.40625 20.6875 +C 38.40625 9.546875 33.5 2 26.296875 2 +C 21.59375 2 15.90625 5.609375 15.90625 8.625 +z +" id="Nimbus_Roman_No9_L_Regular-112"/> + <path d="M 0.703125 39 +C 2.09375 39.296875 3 39.40625 4.203125 39.40625 +C 6.703125 39.40625 7.59375 37.796875 7.59375 33.40625 +L 7.59375 8.40625 +C 7.59375 3.40625 6.90625 2.703125 0.5 1.5 +L 0.5 0 +L 24.5 0 +L 24.5 1.59375 +C 17.703125 1.59375 16 3.109375 16 8.828125 +L 16 31.453125 +C 16 34.671875 20.296875 39.703125 23 39.703125 +C 23.59375 39.703125 24.5 39.203125 25.59375 38.203125 +C 27.203125 36.796875 28.296875 36.203125 29.59375 36.203125 +C 32 36.203125 33.5 37.90625 33.5 40.703125 +C 33.5 44 31.40625 46 28 46 +C 23.796875 46 20.90625 43.703125 16 36.609375 +L 16 45.796875 +L 15.5 46 +C 10.203125 43.796875 6.59375 42.515625 0.703125 40.609375 +z +" id="Nimbus_Roman_No9_L_Regular-114"/> + <path d="M 44.203125 6.609375 +C 42.5 5.203125 41.296875 4.703125 39.796875 4.703125 +C 37.5 4.703125 36.796875 6.09375 36.796875 10.5 +L 36.796875 30 +C 36.796875 35.203125 36.296875 38.09375 34.796875 40.5 +C 32.59375 44.09375 28.296875 46 22.40625 46 +C 13 46 5.59375 41.09375 5.59375 34.796875 +C 5.59375 32.5 7.59375 30.5 9.90625 30.5 +C 12.296875 30.5 14.40625 32.5 14.40625 34.703125 +C 14.40625 35.09375 14.296875 35.59375 14.203125 36.296875 +C 14 37.203125 13.90625 38 13.90625 38.703125 +C 13.90625 41.40625 17.09375 43.59375 21.09375 43.59375 +C 26 43.59375 28.703125 40.703125 28.703125 35.296875 +L 28.703125 29.203125 +C 13.296875 23 11.59375 22.203125 7.296875 18.40625 +C 5.09375 16.40625 3.703125 13 3.703125 9.703125 +C 3.703125 3.40625 8.09375 -1 14.203125 -1 +C 18.59375 -1 22.703125 1.09375 28.796875 6.296875 +C 29.296875 1.09375 31.09375 -1 35.203125 -1 +C 38.59375 -1 40.703125 0.203125 44.203125 4 +z +M 28.703125 12.234375 +C 28.703125 9.125 28.203125 8.21875 26.09375 7.015625 +C 23.703125 5.609375 20.90625 4.703125 18.796875 4.703125 +C 15.296875 4.703125 12.5 8.125 12.5 12.4375 +L 12.5 12.84375 +C 12.5 18.765625 16.59375 22.390625 28.703125 26.796875 +z +" id="Nimbus_Roman_No9_L_Regular-97"/> + <path d="M 47.90625 5 +L 47.40625 5 +C 42.796875 5 41.703125 6.09375 41.703125 10.703125 +L 41.703125 45 +L 25.90625 45 +L 25.90625 43.09375 +C 32.09375 43.09375 33.296875 42.09375 33.296875 37.109375 +L 33.296875 13.671875 +C 33.296875 10.890625 32.796875 9.484375 31.40625 8.390625 +C 28.703125 6.203125 25.59375 5 22.59375 5 +C 18.703125 5 15.5 8.390625 15.5 12.578125 +L 15.5 45 +L 0.90625 45 +L 0.90625 43.40625 +C 5.703125 43.40625 7.09375 41.90625 7.09375 37.296875 +L 7.09375 12.03125 +C 7.09375 4.109375 11.90625 -1 19.203125 -1 +C 22.90625 -1 26.796875 0.59375 29.5 3.296875 +L 33.796875 7.59375 +L 33.796875 -0.703125 +L 34.203125 -0.90625 +C 39.203125 1.09375 42.796875 2.203125 47.90625 3.59375 +z +" id="Nimbus_Roman_No9_L_Regular-117"/> + <path d="M 63.296875 65 +L 10.09375 65 +L 5.90625 49.671875 +L 7.703125 49.265625 +C 13 59.921875 16.203125 61.609375 31.5 61.609375 +L 17.09375 8.984375 +C 15.5 3.6875 13.09375 2.09375 6.5 1.59375 +L 6.5 0 +L 35.5 0 +L 35.5 1.59375 +C 33.796875 1.59375 32.296875 2 31.703125 2 +C 27.703125 2 26.5 2.890625 26.5 5.90625 +C 26.5 7.203125 26.796875 8.390625 27.703125 11.78125 +L 41.59375 61.609375 +L 47.09375 61.609375 +C 54.296875 61.609375 57.5 59.09375 57.5 53.46875 +C 57.5 52.171875 57.40625 50.6875 57.203125 48.96875 +L 58.90625 48.765625 +z +" id="Nimbus_Roman_No9_L_Regular_Italic-84"/> + <path d="M 41.296875 64.203125 +C 42.5 64 43.5 64 43.90625 64 +C 46.90625 64 48.09375 63.203125 48.09375 61.203125 +C 48.09375 58.984375 45.796875 55.984375 40.296875 50.890625 +L 22.59375 34.75 +L 22.59375 55.21875 +C 22.59375 62.5 23.703125 63.609375 31.796875 64.203125 +L 31.796875 66.109375 +L 3.40625 66.109375 +L 3.40625 64.203125 +C 11.203125 63.609375 12.40625 62.3125 12.40625 55.171875 +L 12.40625 11.71875 +C 12.40625 3.390625 11.296875 2.09375 3.40625 2.09375 +L 3.40625 0 +L 31.59375 0 +L 31.59375 2.09375 +C 23.796875 2.09375 22.59375 3.296875 22.59375 10.671875 +L 22.59375 29.546875 +L 25.203125 31.65625 +L 35.796875 21.171875 +C 43.40625 13.6875 48.796875 6.59375 48.796875 4.203125 +C 48.796875 2.796875 47.40625 2.09375 44.59375 2.09375 +C 44.09375 2.09375 43 2.09375 41.796875 1.890625 +L 41.796875 0 +L 72.296875 0 +L 72.296875 2.09375 +C 67.09375 2.09375 65.703125 3.09375 56.59375 12.75 +L 33.296875 37.640625 +L 52.296875 56.421875 +C 59.09375 62.90625 60.703125 63.703125 67.5 64.203125 +L 67.5 66.109375 +L 41.296875 66.109375 +z +" id="Nimbus_Roman_No9_L_Regular-75"/> + </defs> + <g transform="translate(8.880526 137.975632)rotate(-90)scale(0.1 -0.1)"> + <use transform="scale(0.996264)" xlink:href="#Nimbus_Roman_No9_L_Regular-84"/> + <use transform="translate(53.898284 0)scale(0.996264)" xlink:href="#Nimbus_Roman_No9_L_Regular-101"/> + <use transform="translate(98.131853 0)scale(0.996264)" xlink:href="#Nimbus_Roman_No9_L_Regular-109"/> + <use transform="translate(175.640223 0)scale(0.996264)" xlink:href="#Nimbus_Roman_No9_L_Regular-112"/> + <use transform="translate(225.453424 0)scale(0.996264)" xlink:href="#Nimbus_Roman_No9_L_Regular-101"/> + <use transform="translate(269.686992 0)scale(0.996264)" xlink:href="#Nimbus_Roman_No9_L_Regular-114"/> + <use transform="translate(302.862222 0)scale(0.996264)" xlink:href="#Nimbus_Roman_No9_L_Regular-97"/> + <use transform="translate(347.095791 0)scale(0.996264)" xlink:href="#Nimbus_Roman_No9_L_Regular-116"/> + <use transform="translate(374.79096 0)scale(0.996264)" xlink:href="#Nimbus_Roman_No9_L_Regular-117"/> + <use transform="translate(424.604161 0)scale(0.996264)" xlink:href="#Nimbus_Roman_No9_L_Regular-114"/> + <use transform="translate(457.779391 0)scale(0.996264)" xlink:href="#Nimbus_Roman_No9_L_Regular-101"/> + <use transform="translate(533.242072 0)scale(0.996264)" xlink:href="#Nimbus_Roman_No9_L_Regular_Italic-84"/> + <use transform="translate(632.514439 0)scale(0.996264)" xlink:href="#CMR10-91"/> + <use transform="translate(660.109945 0)scale(0.996264)" xlink:href="#Nimbus_Roman_No9_L_Regular-75"/> + <use transform="translate(732.03993 0)scale(0.996264)" xlink:href="#CMR10-93"/> + </g> + </g> + </g> + <g id="line2d_43"> + <path clip-path="url(#p107a2e5a22)" d="M 77.714425 70.434351 +L 227.8 70.434351 +L 227.8 70.434351 +" style="fill:none;stroke:#000000;stroke-linecap:square;"/> + </g> + <g id="line2d_44"> + <path clip-path="url(#p107a2e5a22)" d="M 146.991516 85.113175 +L 227.8 9.275054 +L 227.8 9.275054 +" style="fill:none;stroke:#000000;stroke-linecap:square;"/> + </g> + <g id="line2d_45"> + <path clip-path="url(#p107a2e5a22)" d="M -1 70.434351 +L 77.714425 70.434351 +" style="fill:none;stroke:#000000;stroke-dasharray:0.6,0.99;stroke-dashoffset:0;stroke-width:0.6;"/> + </g> + <g id="line2d_46"> + <path clip-path="url(#p107a2e5a22)" d="M -1 85.113175 +L 146.991516 85.113175 +" style="fill:none;stroke:#000000;stroke-dasharray:0.6,0.99;stroke-dashoffset:0;stroke-width:0.6;"/> + </g> + <g id="line2d_47"> + <path clip-path="url(#p107a2e5a22)" d="M 77.714425 197.316 +L 77.714425 70.434351 +" style="fill:none;stroke:#000000;stroke-dasharray:0.6,0.99;stroke-dashoffset:0;stroke-width:0.6;"/> + </g> + <g id="line2d_48"> + <path clip-path="url(#p107a2e5a22)" d="M 146.991516 197.316 +L 146.991516 85.113175 +" style="fill:none;stroke:#000000;stroke-dasharray:0.6,0.99;stroke-dashoffset:0;stroke-width:0.6;"/> + </g> + <g id="line2d_49"> + <path clip-path="url(#p107a2e5a22)" d="M 68.658545 43.904505 +L 103.297091 43.904505 +" style="fill:none;stroke:#000000;stroke-dasharray:2.22,0.96;stroke-dashoffset:0;stroke-width:0.6;"/> + </g> + <g id="line2d_50"> + <path clip-path="url(#p107a2e5a22)" d="M 155.254909 57.122263 +L 189.893455 24.614263 +" style="fill:none;stroke:#000000;stroke-dasharray:2.22,0.96;stroke-dashoffset:0;stroke-width:0.6;"/> + </g> + <g id="patch_3"> + <path d="M 34.02 197.316 +L 34.02 2.268 +" style="fill:none;stroke:#000000;stroke-linecap:square;stroke-linejoin:miter;stroke-width:0.8;"/> + </g> + <g id="patch_4"> + <path d="M 224.532 197.316 +L 224.532 2.268 +" style="fill:none;stroke:#000000;stroke-linecap:square;stroke-linejoin:miter;stroke-width:0.8;"/> + </g> + <g id="patch_5"> + <path d="M 34.02 197.316 +L 224.532 197.316 +" style="fill:none;stroke:#000000;stroke-linecap:square;stroke-linejoin:miter;stroke-width:0.8;"/> + </g> + <g id="patch_6"> + <path d="M 34.02 2.268 +L 224.532 2.268 +" style="fill:none;stroke:#000000;stroke-linecap:square;stroke-linejoin:miter;stroke-width:0.8;"/> + </g> + <g id="text_12"> + <!-- $n_{\rm H}~\widehat{}~{\tt Cool\_gamma\_effective}$ --> + <defs> + <path d="M 27.703125 68.5 +L 54.90625 56.203125 +L 56.09375 58.40625 +L 27.796875 74.40625 +L -0.5 58.40625 +L 0.59375 56.203125 +z +" id="CMEX10-98"/> + <path d="M 47.40625 58.296875 +C 47.40625 59.890625 47.40625 62.09375 44.59375 62.09375 +C 42.796875 62.09375 42.296875 61 41.90625 60.296875 +C 41.59375 59.5 40.796875 57.703125 40.5 57 +C 36.40625 60.59375 31.796875 62.09375 27.59375 62.09375 +C 14.703125 62.09375 4 48.390625 4 30.59375 +C 4 12.40625 15 -1 27.59375 -1 +C 39.296875 -1 47.40625 8.21875 47.40625 16.96875 +C 47.40625 20.03125 45.296875 20.03125 44.09375 20.03125 +C 42.703125 20.03125 41.09375 19.53125 40.90625 17.859375 +C 40.09375 5.109375 30 5.109375 28.296875 5.109375 +C 19 5.109375 10.5 15.859375 10.5 30.75 +C 10.5 45.65625 19.09375 56.296875 28.203125 56.296875 +C 33.59375 56.296875 39.5 52 40.90625 42.796875 +C 41.203125 40.59375 42.09375 40 44.09375 40 +C 47.40625 40 47.40625 41.796875 47.40625 43.796875 +z +" id="CMTT12-67"/> + <path d="M 45.59375 21.640625 +C 45.59375 34.109375 36.5 44 25.703125 44 +C 14.90625 44 5.796875 34.109375 5.796875 21.640625 +C 5.796875 9.078125 15 -0.5 25.703125 -0.5 +C 36.40625 -0.5 45.59375 9.078125 45.59375 21.640625 +z +M 25.703125 5.296875 +C 18.5 5.296875 12.296875 12.875 12.296875 22.34375 +C 12.296875 31.609375 18.703125 38.203125 25.703125 38.203125 +C 32.703125 38.203125 39.09375 31.609375 39.09375 22.34375 +C 39.09375 12.78125 32.90625 5.296875 25.703125 5.296875 +z +" id="CMTT12-111"/> + <path d="M 29 56.90625 +C 29 60 28.40625 61 25 61 +L 10.296875 61 +C 8.90625 61 6.296875 61 6.296875 58.109375 +C 6.296875 55.203125 8.90625 55.203125 10.296875 55.203125 +L 22.5 55.203125 +L 22.5 5.796875 +L 10.296875 5.796875 +C 8.90625 5.796875 6.296875 5.796875 6.296875 2.90625 +C 6.296875 0 8.90625 0 10.296875 0 +L 41.203125 0 +C 42.59375 0 45.203125 0 45.203125 2.90625 +C 45.203125 5.796875 42.59375 5.796875 41.203125 5.796875 +L 29 5.796875 +z +" id="CMTT12-108"/> + <path d="M 19 6.59375 +C 17.796875 6.59375 13.203125 6.59375 13.203125 12.015625 +C 13.203125 13.921875 13.5 14.3125 13.90625 15.109375 +C 15.90625 13.703125 19.203125 12.40625 22.796875 12.40625 +C 31.90625 12.40625 38.90625 19.703125 38.90625 28.28125 +C 38.90625 30.78125 38.296875 33.890625 36.203125 37.1875 +C 38.796875 38.421875 41.203125 38.703125 42.703125 38.703125 +C 43.296875 36 46.203125 36 46.296875 36 +C 47.5 36 50 36.796875 50 39.796875 +C 50 41.703125 48.5 45 42.90625 45 +C 41.09375 45 36.59375 44.5625 32.40625 40.90625 +C 29.09375 43.203125 25.703125 44 22.90625 44 +C 13.796875 44 6.796875 36.765625 6.796875 28.21875 +C 6.796875 26.03125 7.296875 22.265625 10.09375 18.703125 +C 8.203125 15.90625 7.90625 12.90625 7.90625 11.703125 +C 7.90625 8.203125 9.59375 5.40625 10.40625 4.5 +C 4.90625 1.484375 2.90625 -3.9375 2.90625 -7.84375 +C 2.90625 -16.171875 13 -22.5 25.703125 -22.5 +C 38.40625 -22.5 48.5 -16.28125 48.5 -7.84375 +C 48.5 6.59375 30.796875 6.59375 27.5 6.59375 +z +M 22.796875 18 +C 17.796875 18 13.296875 22.359375 13.296875 28.203125 +C 13.296875 34.046875 17.90625 38.390625 22.796875 38.390625 +C 28.09375 38.390625 32.40625 33.84375 32.40625 28.203125 +C 32.40625 22.546875 28.09375 18 22.796875 18 +z +M 25.703125 -16.890625 +C 15.90625 -16.890625 8.59375 -12.484375 8.59375 -7.84375 +C 8.59375 -6.328125 9.09375 -2.8125 12.796875 -0.515625 +C 15.09375 1 16.09375 1 23 1 +C 31.796875 1 42.796875 1 42.796875 -7.84375 +C 42.796875 -12.484375 35.5 -16.890625 25.703125 -16.890625 +z +" id="CMTT12-103"/> + <path d="M 41.40625 28.375 +C 41.40625 35.984375 35.703125 44 22.203125 44 +C 18 44 8.296875 44 8.296875 37.1875 +C 8.296875 34.53125 10.203125 33.046875 12.40625 33.046875 +C 13 33.046875 16.296875 33.046875 16.40625 37.3125 +C 16.40625 37.796875 16.5 37.90625 18.59375 38.09375 +C 19.796875 38.203125 21.09375 38.203125 22.296875 38.203125 +C 24.59375 38.203125 28 38.203125 31.296875 35.65625 +C 34.90625 32.8125 34.90625 29.9375 34.90625 27 +C 29 27 23.203125 27 17 24.984375 +C 12 23.265625 5.59375 19.625 5.59375 12.75 +C 5.59375 5.5625 11.90625 -0.5 21.203125 -0.5 +C 24.40625 -0.5 30.59375 0 35.796875 3.53125 +C 37.796875 0 42.796875 0 46.59375 0 +C 49 0 51.40625 0 51.40625 2.859375 +C 51.40625 5.703125 48.796875 5.703125 47.40625 5.703125 +C 44.796875 5.703125 42.796875 5.90625 41.40625 6.515625 +z +M 34.90625 13.296875 +C 34.90625 11 34.90625 8.890625 30.796875 7 +C 27.296875 5.296875 22.59375 5.296875 22.296875 5.296875 +C 16.40625 5.296875 12.09375 8.5 12.09375 12.59375 +C 12.09375 18.5 22.796875 21.890625 34.90625 21.890625 +z +" id="CMTT12-97"/> + <path d="M 45.296875 30.359375 +C 45.296875 32.5625 45.296875 43.796875 36.5 43.796875 +C 33 43.796875 29.59375 42.1875 26.90625 38.484375 +C 26.296875 39.984375 24.09375 43.796875 19.296875 43.796875 +C 14.796875 43.796875 11.703125 40.828125 10.90625 39.921875 +C 10.796875 43 8.703125 43 6.90625 43 +L 3.90625 43 +C 2.5 43 -0.09375 43 -0.09375 40.109375 +C -0.09375 37.203125 2.203125 37.203125 5.296875 37.203125 +L 5.296875 5.796875 +C 2.09375 5.796875 -0.09375 5.796875 -0.09375 2.90625 +C -0.09375 0 2.5 0 3.90625 0 +L 12.296875 0 +C 13.703125 0 16.296875 0 16.296875 2.90625 +C 16.296875 5.796875 14 5.796875 10.90625 5.796875 +L 10.90625 24.25 +C 10.90625 32.671875 14.5 38 18.90625 38 +C 21.703125 38 22.5 34.484375 22.5 29.765625 +L 22.5 5.796875 +C 20.796875 5.796875 18.09375 5.796875 18.09375 2.90625 +C 18.09375 0 20.796875 0 22.203125 0 +L 29.5 0 +C 30.90625 0 33.5 0 33.5 2.90625 +C 33.5 5.796875 31.203125 5.796875 28.09375 5.796875 +L 28.09375 24.25 +C 28.09375 32.671875 31.703125 38 36.09375 38 +C 38.90625 38 39.703125 34.484375 39.703125 29.765625 +L 39.703125 5.796875 +C 38 5.796875 35.296875 5.796875 35.296875 2.90625 +C 35.296875 0 38 0 39.40625 0 +L 46.703125 0 +C 48.09375 0 50.703125 0 50.703125 2.90625 +C 50.703125 5.796875 48.40625 5.796875 45.296875 5.796875 +z +" id="CMTT12-109"/> + <path d="M 41.59375 19.5 +C 43.703125 19.5 45.59375 19.5 45.59375 23.15625 +C 45.59375 34.703125 39 44 26.5 44 +C 14.90625 44 5.59375 34.015625 5.59375 21.84375 +C 5.59375 9.28125 15.703125 -0.5 28 -0.5 +C 40.90625 -0.5 45.59375 8.453125 45.59375 11.078125 +C 45.59375 11.6875 45.40625 13.921875 42.296875 13.921875 +C 40.40625 13.921875 39.796875 13.203125 39.203125 11.6875 +C 36.703125 5.796875 30.203125 5.296875 28.296875 5.296875 +C 20 5.296875 13.40625 11.6875 12.296875 19.5 +z +M 12.40625 25 +C 13.703125 33.3125 20.203125 38.203125 26.5 38.203125 +C 36.5 38.203125 38.59375 29.890625 39 25 +z +" id="CMTT12-101"/> + <path d="M 24.703125 37.203125 +L 36.796875 37.203125 +C 38.203125 37.203125 40.796875 37.203125 40.796875 40.109375 +C 40.796875 43 38.203125 43 36.796875 43 +L 24.703125 43 +L 24.703125 48.078125 +C 24.703125 56 31.703125 56 34.90625 56 +C 34.90625 55.796875 35.703125 52.03125 39 52.03125 +C 40.59375 52.03125 42.90625 53.234375 42.90625 56.0625 +C 42.90625 61.796875 35.296875 61.796875 33.796875 61.796875 +C 26.203125 61.796875 18.203125 57.453125 18.203125 48.453125 +L 18.203125 43 +L 8.296875 43 +C 6.90625 43 4.203125 43 4.203125 40.109375 +C 4.203125 37.203125 6.796875 37.203125 8.203125 37.203125 +L 18.203125 37.203125 +L 18.203125 5.796875 +L 8.703125 5.796875 +C 7.296875 5.796875 4.703125 5.796875 4.703125 2.90625 +C 4.703125 0 7.296875 0 8.703125 0 +L 34.203125 0 +C 35.59375 0 38.203125 0 38.203125 2.90625 +C 38.203125 5.796875 35.59375 5.796875 34.203125 5.796875 +L 24.703125 5.796875 +z +" id="CMTT12-102"/> + <path d="M 45.59375 10.96875 +C 45.59375 13.5625 43.09375 13.5625 42.296875 13.5625 +C 40 13.5625 39.59375 12.765625 39.09375 11.375 +C 36.90625 5.890625 32 5.296875 29.59375 5.296875 +C 21.09375 5.296875 13.90625 12.375 13.90625 21.640625 +C 13.90625 26.734375 16.796875 38.203125 29.90625 38.203125 +C 32.59375 38.203125 34.703125 38 35.59375 37.90625 +C 36.296875 37.703125 36.40625 37.578125 36.40625 37.078125 +C 36.703125 32.921875 39.796875 32.921875 40.40625 32.921875 +C 42.59375 32.921875 44.5 34.421875 44.5 37.109375 +C 44.5 44 34.40625 44 30 44 +C 12.90625 44 7.40625 30.03125 7.40625 21.640625 +C 7.40625 9.484375 16.703125 -0.5 28.703125 -0.5 +C 42.09375 -0.5 45.59375 9.375 45.59375 10.96875 +z +" id="CMTT12-99"/> + <path d="M 21.59375 37.203125 +L 37.796875 37.203125 +C 39.203125 37.203125 41.796875 37.203125 41.796875 40.109375 +C 41.796875 43 39.203125 43 37.796875 43 +L 21.59375 43 +L 21.59375 51.328125 +C 21.59375 53.15625 21.59375 55.5 18.40625 55.5 +C 15.09375 55.5 15.09375 53.15625 15.09375 51.328125 +L 15.09375 43 +L 6.59375 43 +C 5.203125 43 2.5 43 2.5 40.109375 +C 2.5 37.203125 5.09375 37.203125 6.5 37.203125 +L 15.09375 37.203125 +L 15.09375 12.125 +C 15.09375 2.875 21.5 -0.5 28.703125 -0.5 +C 34.09375 -0.5 44 2.171875 44 12.34375 +C 44 14.34375 44 16.53125 40.703125 16.53125 +C 37.5 16.53125 37.5 14.34375 37.5 12.265625 +C 37.40625 6.296875 31.703125 5.296875 29.40625 5.296875 +C 21.59375 5.296875 21.59375 10.265625 21.59375 12.640625 +z +" id="CMTT12-116"/> + <path d="M 30.203125 56.5 +C 30.203125 59 28.203125 61 25.703125 61 +C 23.203125 61 21.203125 59 21.203125 56.5 +C 21.203125 54 23.203125 52 25.703125 52 +C 28.203125 52 30.203125 54 30.203125 56.5 +z +M 13 43 +C 11.59375 43 9 43 9 40.109375 +C 9 37.203125 11.59375 37.203125 13 37.203125 +L 23.703125 37.203125 +L 23.703125 5.796875 +L 12.296875 5.796875 +C 10.90625 5.796875 8.203125 5.796875 8.203125 2.90625 +C 8.203125 0 10.90625 0 12.296875 0 +L 40.09375 0 +C 41.5 0 44.09375 0 44.09375 2.90625 +C 44.09375 5.796875 41.5 5.796875 40.09375 5.796875 +L 30.203125 5.796875 +L 30.203125 38.921875 +C 30.203125 42 29.59375 43 26.203125 43 +z +" id="CMTT12-105"/> + <path d="M 42.40625 37.203125 +L 45 37.203125 +C 46.40625 37.203125 49.09375 37.203125 49.09375 40.109375 +C 49.09375 43 46.40625 43 45 43 +L 34 43 +C 32.59375 43 29.90625 43 29.90625 40.109375 +C 29.90625 37.203125 32.59375 37.203125 34 37.203125 +L 36.5 37.203125 +L 25.703125 5.078125 +L 14.90625 37.203125 +L 17.40625 37.203125 +C 18.796875 37.203125 21.5 37.203125 21.5 40.109375 +C 21.5 43 18.796875 43 17.40625 43 +L 6.40625 43 +C 5 43 2.296875 43 2.296875 40.109375 +C 2.296875 37.203125 5 37.203125 6.40625 37.203125 +L 9 37.203125 +L 20.5 2.890625 +C 21.59375 -0.5 23.796875 -0.5 25.703125 -0.5 +C 27.59375 -0.5 29.796875 -0.5 30.90625 2.890625 +z +" id="CMTT12-118"/> + </defs> + <g transform="translate(68.658545 53.766087)scale(0.07 -0.07)"> + <use transform="translate(0 15.050129)scale(0.996264)" xlink:href="#Nimbus_Roman_No9_L_Regular_Italic-110"/> + <use transform="translate(49.8132 0)scale(0.737241)" xlink:href="#Nimbus_Roman_No9_L_Regular-72"/> + <use transform="translate(107.123069 15.050129)scale(0.996264)" xlink:href="#CMEX10-98"/> + <use transform="translate(165.998143 15.050129)scale(0.996264)" xlink:href="#CMTT12-67"/> + <use transform="translate(217.264254 15.050129)scale(0.996264)" xlink:href="#CMTT12-111"/> + <use transform="translate(268.530365 15.050129)scale(0.996264)" xlink:href="#CMTT12-111"/> + <use transform="translate(319.796475 15.050129)scale(0.996264)" xlink:href="#CMTT12-108"/> + <use transform="translate(404.790082 15.050129)scale(0.996264)" xlink:href="#CMTT12-103"/> + <use transform="translate(456.056192 15.050129)scale(0.996264)" xlink:href="#CMTT12-97"/> + <use transform="translate(507.322303 15.050129)scale(0.996264)" xlink:href="#CMTT12-109"/> + <use transform="translate(558.588414 15.050129)scale(0.996264)" xlink:href="#CMTT12-109"/> + <use transform="translate(609.854525 15.050129)scale(0.996264)" xlink:href="#CMTT12-97"/> + <use transform="translate(694.848131 15.050129)scale(0.996264)" xlink:href="#CMTT12-101"/> + <use transform="translate(746.114242 15.050129)scale(0.996264)" xlink:href="#CMTT12-102"/> + <use transform="translate(797.380353 15.050129)scale(0.996264)" xlink:href="#CMTT12-102"/> + <use transform="translate(848.646464 15.050129)scale(0.996264)" xlink:href="#CMTT12-101"/> + <use transform="translate(899.912575 15.050129)scale(0.996264)" xlink:href="#CMTT12-99"/> + <use transform="translate(951.178685 15.050129)scale(0.996264)" xlink:href="#CMTT12-116"/> + <use transform="translate(1002.444796 15.050129)scale(0.996264)" xlink:href="#CMTT12-105"/> + <use transform="translate(1053.710907 15.050129)scale(0.996264)" xlink:href="#CMTT12-118"/> + <use transform="translate(1104.977018 15.050129)scale(0.996264)" xlink:href="#CMTT12-101"/> + <path d="M 376.683597 15.050129 +L 404.790082 15.050129 +L 404.790082 15.448629 +L 376.683597 15.448629 +L 376.683597 15.050129 +z +"/> + <path d="M 666.741647 15.050129 +L 694.848131 15.050129 +L 694.848131 15.448629 +L 666.741647 15.448629 +L 666.741647 15.050129 +z +"/> + </g> + </g> + <g id="text_13"> + <!-- $n_{\rm H}~\widehat{}~{\tt Jeans\_gamma\_effective}$ --> + <defs> + <path d="M 40 55.203125 +L 42.703125 55.203125 +C 44.09375 55.203125 46.796875 55.203125 46.796875 58.109375 +C 46.796875 61 44.09375 61 42.703125 61 +L 25.796875 61 +C 24.40625 61 21.796875 61 21.796875 58.109375 +C 21.796875 55.203125 24.40625 55.203125 25.796875 55.203125 +L 33.5 55.203125 +L 33.5 14.234375 +C 33.5 5.515625 25.40625 4.90625 23.703125 4.90625 +C 22.5 4.90625 17.5 4.90625 14.90625 7.984375 +C 15.40625 8.59375 15.703125 9.46875 15.703125 10.375 +C 15.703125 12.453125 14.09375 14.34375 11.703125 14.34375 +C 9.40625 14.34375 7.59375 12.84375 7.59375 10.0625 +C 7.59375 3.6875 14.40625 -1 23.59375 -1 +C 32 -1 40 4.265625 40 13.53125 +z +" id="CMTT12-74"/> + <path d="M 41.796875 29.359375 +C 41.796875 39.171875 37.203125 43.796875 29 43.796875 +C 22.203125 43.796875 17.796875 40 16.09375 38.09375 +C 16.09375 41.65625 16.09375 43 12.09375 43 +L 5.5 43 +C 4.09375 43 1.5 43 1.5 40.109375 +C 1.5 37.203125 4.09375 37.203125 5.5 37.203125 +L 9.59375 37.203125 +L 9.59375 5.796875 +L 5.5 5.796875 +C 4.09375 5.796875 1.5 5.796875 1.5 2.90625 +C 1.5 0 4.09375 0 5.5 0 +L 20.203125 0 +C 21.59375 0 24.203125 0 24.203125 2.90625 +C 24.203125 5.796875 21.59375 5.796875 20.203125 5.796875 +L 16.09375 5.796875 +L 16.09375 23.953125 +C 16.09375 33.671875 22.90625 38 28.296875 38 +C 34.09375 38 35.296875 34.671875 35.296875 28.96875 +L 35.296875 5.796875 +L 31.203125 5.796875 +C 29.796875 5.796875 27.203125 5.796875 27.203125 2.90625 +C 27.203125 0 29.796875 0 31.203125 0 +L 45.90625 0 +C 47.296875 0 49.90625 0 49.90625 2.90625 +C 49.90625 5.796875 47.296875 5.796875 45.90625 5.796875 +L 41.796875 5.796875 +z +" id="CMTT12-110"/> + <path d="M 42 40.203125 +C 42 41.796875 42 44 39.203125 44 +C 36.796875 44 36.203125 41.703125 36.203125 41.59375 +C 32.203125 44 27.59375 44 25.59375 44 +C 9.296875 44 7.09375 35.71875 7.09375 32.328125 +C 7.09375 28.234375 9.5 25.453125 12.90625 23.546875 +C 16.09375 21.75 19 21.265625 27.203125 19.96875 +C 31.09375 19.265625 39.09375 17.96875 39.09375 12.484375 +C 39.09375 8.78125 35.703125 5.296875 26.40625 5.296875 +C 20 5.296875 15.796875 7.796875 13.703125 15 +C 13.203125 16.390625 12.90625 17.5 10.40625 17.5 +C 7.09375 17.5 7.09375 15.59375 7.09375 13.59375 +L 7.09375 3.296875 +C 7.09375 1.6875 7.09375 -0.5 9.90625 -0.5 +C 11.09375 -0.5 12 -0.5 13.5 3.59375 +C 18.09375 -0.5 23.296875 -0.5 26.40625 -0.5 +C 44.90625 -0.5 44.90625 11.46875 44.90625 12.46875 +C 44.90625 22.828125 32.5 24.9375 27.703125 25.625 +C 18.90625 27.125 12.90625 28.125 12.90625 32.3125 +C 12.90625 35.015625 16 38.203125 25.40625 38.203125 +C 34.90625 38.203125 35.296875 33.703125 35.5 31.09375 +C 35.703125 29.09375 37.5 28.796875 38.703125 28.796875 +C 42 28.796875 42 30.59375 42 32.59375 +z +" id="CMTT12-115"/> + </defs> + <g transform="translate(158.822024 66.279355)rotate(-43)scale(0.07 -0.07)"> + <use transform="translate(0 15.050129)scale(0.996264)" xlink:href="#Nimbus_Roman_No9_L_Regular_Italic-110"/> + <use transform="translate(49.8132 0)scale(0.737241)" xlink:href="#Nimbus_Roman_No9_L_Regular-72"/> + <use transform="translate(107.123069 15.050129)scale(0.996264)" xlink:href="#CMEX10-98"/> + <use transform="translate(165.998143 15.050129)scale(0.996264)" xlink:href="#CMTT12-74"/> + <use transform="translate(217.264254 15.050129)scale(0.996264)" xlink:href="#CMTT12-101"/> + <use transform="translate(268.530365 15.050129)scale(0.996264)" xlink:href="#CMTT12-97"/> + <use transform="translate(319.796475 15.050129)scale(0.996264)" xlink:href="#CMTT12-110"/> + <use transform="translate(371.062586 15.050129)scale(0.996264)" xlink:href="#CMTT12-115"/> + <use transform="translate(456.056192 15.050129)scale(0.996264)" xlink:href="#CMTT12-103"/> + <use transform="translate(507.322303 15.050129)scale(0.996264)" xlink:href="#CMTT12-97"/> + <use transform="translate(558.588414 15.050129)scale(0.996264)" xlink:href="#CMTT12-109"/> + <use transform="translate(609.854525 15.050129)scale(0.996264)" xlink:href="#CMTT12-109"/> + <use transform="translate(661.120636 15.050129)scale(0.996264)" xlink:href="#CMTT12-97"/> + <use transform="translate(746.114242 15.050129)scale(0.996264)" xlink:href="#CMTT12-101"/> + <use transform="translate(797.380353 15.050129)scale(0.996264)" xlink:href="#CMTT12-102"/> + <use transform="translate(848.646464 15.050129)scale(0.996264)" xlink:href="#CMTT12-102"/> + <use transform="translate(899.912575 15.050129)scale(0.996264)" xlink:href="#CMTT12-101"/> + <use transform="translate(951.178685 15.050129)scale(0.996264)" xlink:href="#CMTT12-99"/> + <use transform="translate(1002.444796 15.050129)scale(0.996264)" xlink:href="#CMTT12-116"/> + <use transform="translate(1053.710907 15.050129)scale(0.996264)" xlink:href="#CMTT12-105"/> + <use transform="translate(1104.977018 15.050129)scale(0.996264)" xlink:href="#CMTT12-118"/> + <use transform="translate(1156.243129 15.050129)scale(0.996264)" xlink:href="#CMTT12-101"/> + <path d="M 427.949708 15.050129 +L 456.056192 15.050129 +L 456.056192 15.448629 +L 427.949708 15.448629 +L 427.949708 15.050129 +z +"/> + <path d="M 718.007758 15.050129 +L 746.114242 15.050129 +L 746.114242 15.448629 +L 718.007758 15.448629 +L 718.007758 15.050129 +z +"/> + </g> + </g> + <g id="text_14"> + <!-- ${\tt Cool\_density\_threshold\_H\_p\_cm3}$ --> + <defs> + <path d="M 41.796875 56.90625 +C 41.796875 60 41.203125 61 37.796875 61 +L 31.203125 61 +C 29.796875 61 27.203125 61 27.203125 58.109375 +C 27.203125 55.203125 29.796875 55.203125 31.203125 55.203125 +L 35.296875 55.203125 +L 35.296875 38.796875 +C 33.703125 40.390625 29.59375 43.796875 23.5 43.796875 +C 12.90625 43.796875 3.703125 34.1875 3.703125 21.59375 +C 3.703125 9.296875 12.296875 -0.5 22.59375 -0.5 +C 29.09375 -0.5 33.40625 3.359375 35.296875 5.546875 +C 35.296875 1.3125 35.296875 0 39.296875 0 +L 45.90625 0 +C 47.296875 0 49.90625 0 49.90625 2.90625 +C 49.90625 5.796875 47.296875 5.796875 45.90625 5.796875 +L 41.796875 5.796875 +z +M 35.296875 19.09375 +C 35.296875 13.5 30.703125 5.296875 23.203125 5.296875 +C 16 5.296875 10.203125 12.59375 10.203125 21.59375 +C 10.203125 31.1875 17 38 24.09375 38 +C 30.59375 38 35.296875 32.09375 35.296875 26.890625 +z +" id="CMTT12-100"/> + <path d="M 42.40625 37.203125 +L 45 37.203125 +C 46.40625 37.203125 49.09375 37.203125 49.09375 40.109375 +C 49.09375 43 46.40625 43 45 43 +L 34 43 +C 32.59375 43 29.90625 43 29.90625 40.109375 +C 29.90625 37.203125 32.59375 37.203125 34 37.203125 +L 36.5 37.203125 +C 33.703125 29.0625 28 12.515625 26.59375 6.859375 +L 26.5 6.859375 +C 26 9.046875 25.59375 10.125 24.59375 12.8125 +L 15.296875 37.203125 +L 17.59375 37.203125 +C 19 37.203125 21.703125 37.203125 21.703125 40.109375 +C 21.703125 43 19 43 17.59375 43 +L 6.59375 43 +C 5.203125 43 2.5 43 2.5 40.109375 +C 2.5 37.203125 5.203125 37.203125 6.59375 37.203125 +L 9.296875 37.203125 +L 23.296875 1.46875 +C 23.703125 0.46875 23.703125 0.265625 23.703125 0.171875 +C 23.703125 -0.03125 21.09375 -8.671875 19.59375 -11.4375 +C 19 -12.4375 16.5 -17.109375 11.703125 -16.609375 +C 11.796875 -16.296875 12.09375 -15.703125 12.09375 -14.609375 +C 12.09375 -12.296875 10.5 -10.703125 8.203125 -10.703125 +C 5.703125 -10.703125 4.203125 -12.40625 4.203125 -14.703125 +C 4.203125 -18.5 7.40625 -22.5 12.40625 -22.5 +C 22.09375 -22.5 26.40625 -9.6875 26.703125 -8.890625 +z +" id="CMTT12-121"/> + <path d="M 41.796875 29.359375 +C 41.796875 39.171875 37.203125 43.796875 29 43.796875 +C 22.203125 43.796875 17.796875 40 16.09375 38.09375 +L 16.09375 56.9375 +C 16.09375 60.015625 15.5 61 12.09375 61 +L 5.5 61 +C 4.09375 61 1.5 61 1.5 58.109375 +C 1.5 55.203125 4.09375 55.203125 5.5 55.203125 +L 9.59375 55.203125 +L 9.59375 5.796875 +L 5.5 5.796875 +C 4.09375 5.796875 1.5 5.796875 1.5 2.90625 +C 1.5 0 4.09375 0 5.5 0 +L 20.203125 0 +C 21.59375 0 24.203125 0 24.203125 2.90625 +C 24.203125 5.796875 21.59375 5.796875 20.203125 5.796875 +L 16.09375 5.796875 +L 16.09375 23.953125 +C 16.09375 33.671875 22.90625 38 28.296875 38 +C 34.09375 38 35.296875 34.671875 35.296875 28.96875 +L 35.296875 5.796875 +L 31.203125 5.796875 +C 29.796875 5.796875 27.203125 5.796875 27.203125 2.90625 +C 27.203125 0 29.796875 0 31.203125 0 +L 45.90625 0 +C 47.296875 0 49.90625 0 49.90625 2.90625 +C 49.90625 5.796875 47.296875 5.796875 45.90625 5.796875 +L 41.796875 5.796875 +z +" id="CMTT12-104"/> + <path d="M 21.59375 18.9375 +C 21.59375 30.875 30 38 38.5 38 +C 39 38 39.59375 38 40.09375 37.890625 +C 40.40625 34.140625 43.203125 33.828125 43.90625 33.828125 +C 46.203125 33.828125 47.796875 35.546875 47.796875 37.78125 +C 47.796875 42.15625 43.59375 43.796875 38.59375 43.796875 +C 31.90625 43.796875 26.203125 40.734375 21.59375 35.015625 +L 21.59375 38.921875 +C 21.59375 42 21 43 17.59375 43 +L 7.5 43 +C 6.09375 43 3.5 43 3.5 40.109375 +C 3.5 37.203125 6.09375 37.203125 7.5 37.203125 +L 15.09375 37.203125 +L 15.09375 5.796875 +L 7.5 5.796875 +C 6.09375 5.796875 3.5 5.796875 3.5 2.90625 +C 3.5 0 6.09375 0 7.5 0 +L 32.09375 0 +C 33.5 0 36.09375 0 36.09375 2.90625 +C 36.09375 5.796875 33.5 5.796875 32.09375 5.796875 +L 21.59375 5.796875 +z +" id="CMTT12-114"/> + <path d="M 42.796875 55.203125 +L 45 55.203125 +C 46.40625 55.203125 49 55.203125 49 58.109375 +C 49 61 46.5 61 45 61 +L 34.09375 61 +C 32.703125 61 30 61 30 58.109375 +C 30 55.203125 32.703125 55.203125 34.09375 55.203125 +L 36.296875 55.203125 +L 36.296875 34.796875 +L 15.09375 34.796875 +L 15.09375 55.203125 +L 17.296875 55.203125 +C 18.703125 55.203125 21.40625 55.203125 21.40625 58.109375 +C 21.40625 61 18.703125 61 17.296875 61 +L 6.40625 61 +C 4.90625 61 2.40625 61 2.40625 58.109375 +C 2.40625 55.203125 5 55.203125 6.40625 55.203125 +L 8.59375 55.203125 +L 8.59375 5.796875 +L 6.40625 5.796875 +C 5 5.796875 2.40625 5.796875 2.40625 2.90625 +C 2.40625 0 4.90625 0 6.40625 0 +L 17.296875 0 +C 18.703125 0 21.40625 0 21.40625 2.90625 +C 21.40625 5.796875 18.703125 5.796875 17.296875 5.796875 +L 15.09375 5.796875 +L 15.09375 29 +L 36.296875 29 +L 36.296875 5.796875 +L 34.09375 5.796875 +C 32.703125 5.796875 30 5.796875 30 2.90625 +C 30 0 32.703125 0 34.09375 0 +L 45 0 +C 46.5 0 49 0 49 2.90625 +C 49 5.796875 46.40625 5.796875 45 5.796875 +L 42.796875 5.796875 +z +" id="CMTT12-72"/> + <path d="M 20.203125 -22 +C 21.59375 -22 24.203125 -22 24.203125 -19.09375 +C 24.203125 -16.203125 21.59375 -16.203125 20.203125 -16.203125 +L 16.09375 -16.203125 +L 16.09375 5.09375 +C 18.5 2.390625 22.203125 -0.5 27.796875 -0.5 +C 38.40625 -0.5 47.703125 9.046875 47.703125 21.796875 +C 47.703125 34.15625 39.296875 44 28.90625 44 +C 21.59375 44 17 39.578125 16.09375 38.578125 +C 16.09375 41.625 16.09375 43 12.09375 43 +L 5.5 43 +C 4.09375 43 1.5 43 1.5 40.109375 +C 1.5 37.203125 4.09375 37.203125 5.5 37.203125 +L 9.59375 37.203125 +L 9.59375 -16.203125 +L 5.5 -16.203125 +C 4.09375 -16.203125 1.5 -16.203125 1.5 -19.09375 +C 1.5 -22 4.09375 -22 5.5 -22 +z +M 16.09375 26.828125 +C 16.09375 32.5625 21.703125 38.203125 28.203125 38.203125 +C 35.40625 38.203125 41.203125 30.84375 41.203125 21.796875 +C 41.203125 12.140625 34.40625 5.296875 27.296875 5.296875 +C 19.796875 5.296875 16.09375 13.84375 16.09375 18.875 +z +" id="CMTT12-112"/> + <path d="M 25.59375 30.59375 +C 36 30.59375 40.59375 23.21875 40.59375 17.765625 +C 40.59375 11.078125 34.796875 4.796875 26 4.796875 +C 16 4.796875 11.5 10.25 11.5 11.671875 +C 11.5 11.859375 11.59375 12.0625 11.703125 12.171875 +C 12.09375 12.875 12.40625 13.703125 12.40625 14.609375 +C 12.40625 16.734375 10.796875 18.65625 8.40625 18.65625 +C 6.296875 18.65625 4.296875 17.34375 4.296875 14.234375 +C 4.296875 5.453125 13.796875 -1 26 -1 +C 38.59375 -1 47.09375 8.078125 47.09375 17.65625 +C 47.09375 22.8125 44.296875 29.96875 35.5 33.796875 +C 41.59375 37.609375 44.296875 43.625 44.296875 48.84375 +C 44.296875 56.375 36.796875 62.890625 26 62.890625 +C 14.90625 62.890625 7.09375 58.078125 7.09375 50.65625 +C 7.09375 47.34375 9.59375 46.34375 11.203125 46.34375 +C 13 46.34375 15.203125 47.765625 15.203125 50.515625 +C 15.203125 52.125 14.40625 53.046875 14.40625 53.140625 +C 17.40625 57 24.296875 57 26 57 +C 32.796875 57 37.796875 53.3125 37.796875 48.484375 +C 37.796875 45.515625 35.90625 37 25.40625 37 +C 21.703125 37 20.09375 36.796875 19.703125 36.796875 +C 17.703125 36.578125 17.203125 35.203125 17.203125 33.703125 +C 17.203125 30.59375 19.296875 30.59375 21 30.59375 +z +" id="CMTT12-51"/> + </defs> + <g transform="translate(75.778884 192.590474)rotate(-90)scale(0.07 -0.07)"> + <use transform="scale(0.996264)" xlink:href="#CMTT12-67"/> + <use transform="translate(51.266111 0)scale(0.996264)" xlink:href="#CMTT12-111"/> + <use transform="translate(102.532222 0)scale(0.996264)" xlink:href="#CMTT12-111"/> + <use transform="translate(153.798333 0)scale(0.996264)" xlink:href="#CMTT12-108"/> + <use transform="translate(238.791939 0)scale(0.996264)" xlink:href="#CMTT12-100"/> + <use transform="translate(290.05805 0)scale(0.996264)" xlink:href="#CMTT12-101"/> + <use transform="translate(341.32416 0)scale(0.996264)" xlink:href="#CMTT12-110"/> + <use transform="translate(392.590271 0)scale(0.996264)" xlink:href="#CMTT12-115"/> + <use transform="translate(443.856382 0)scale(0.996264)" xlink:href="#CMTT12-105"/> + <use transform="translate(495.122493 0)scale(0.996264)" xlink:href="#CMTT12-116"/> + <use transform="translate(546.388604 0)scale(0.996264)" xlink:href="#CMTT12-121"/> + <use transform="translate(631.38221 0)scale(0.996264)" xlink:href="#CMTT12-116"/> + <use transform="translate(682.648321 0)scale(0.996264)" xlink:href="#CMTT12-104"/> + <use transform="translate(733.914432 0)scale(0.996264)" xlink:href="#CMTT12-114"/> + <use transform="translate(785.180542 0)scale(0.996264)" xlink:href="#CMTT12-101"/> + <use transform="translate(836.446653 0)scale(0.996264)" xlink:href="#CMTT12-115"/> + <use transform="translate(887.712764 0)scale(0.996264)" xlink:href="#CMTT12-104"/> + <use transform="translate(938.978875 0)scale(0.996264)" xlink:href="#CMTT12-111"/> + <use transform="translate(990.244986 0)scale(0.996264)" xlink:href="#CMTT12-108"/> + <use transform="translate(1041.511097 0)scale(0.996264)" xlink:href="#CMTT12-100"/> + <use transform="translate(1126.504703 0)scale(0.996264)" xlink:href="#CMTT12-72"/> + <use transform="translate(1211.498309 0)scale(0.996264)" xlink:href="#CMTT12-112"/> + <use transform="translate(1296.491915 0)scale(0.996264)" xlink:href="#CMTT12-99"/> + <use transform="translate(1347.758026 0)scale(0.996264)" xlink:href="#CMTT12-109"/> + <use transform="translate(1399.024137 0)scale(0.996264)" xlink:href="#CMTT12-51"/> + <path d="M 210.685454 0 +L 238.791939 0 +L 238.791939 0.3985 +L 210.685454 0.3985 +L 210.685454 0 +z +"/> + <path d="M 603.275726 0 +L 631.38221 0 +L 631.38221 0.3985 +L 603.275726 0.3985 +L 603.275726 0 +z +"/> + <path d="M 1098.398219 0 +L 1126.504703 0 +L 1126.504703 0.3985 +L 1098.398219 0.3985 +L 1098.398219 0 +z +"/> + <path d="M 1183.391825 0 +L 1211.498309 0 +L 1211.498309 0.3985 +L 1183.391825 0.3985 +L 1183.391825 0 +z +"/> + <path d="M 1268.385431 0 +L 1296.491915 0 +L 1296.491915 0.3985 +L 1268.385431 0.3985 +L 1268.385431 0 +z +"/> + </g> + </g> + <g id="text_15"> + <!-- ${\tt Jeans\_density\_threshold\_H\_p\_cm3}$ --> + <g transform="translate(145.055974 192.590474)rotate(-90)scale(0.07 -0.07)"> + <use transform="scale(0.996264)" xlink:href="#CMTT12-74"/> + <use transform="translate(51.266111 0)scale(0.996264)" xlink:href="#CMTT12-101"/> + <use transform="translate(102.532222 0)scale(0.996264)" xlink:href="#CMTT12-97"/> + <use transform="translate(153.798333 0)scale(0.996264)" xlink:href="#CMTT12-110"/> + <use transform="translate(205.064443 0)scale(0.996264)" xlink:href="#CMTT12-115"/> + <use transform="translate(290.05805 0)scale(0.996264)" xlink:href="#CMTT12-100"/> + <use transform="translate(341.32416 0)scale(0.996264)" xlink:href="#CMTT12-101"/> + <use transform="translate(392.590271 0)scale(0.996264)" xlink:href="#CMTT12-110"/> + <use transform="translate(443.856382 0)scale(0.996264)" xlink:href="#CMTT12-115"/> + <use transform="translate(495.122493 0)scale(0.996264)" xlink:href="#CMTT12-105"/> + <use transform="translate(546.388604 0)scale(0.996264)" xlink:href="#CMTT12-116"/> + <use transform="translate(597.654715 0)scale(0.996264)" xlink:href="#CMTT12-121"/> + <use transform="translate(682.648321 0)scale(0.996264)" xlink:href="#CMTT12-116"/> + <use transform="translate(733.914432 0)scale(0.996264)" xlink:href="#CMTT12-104"/> + <use transform="translate(785.180542 0)scale(0.996264)" xlink:href="#CMTT12-114"/> + <use transform="translate(836.446653 0)scale(0.996264)" xlink:href="#CMTT12-101"/> + <use transform="translate(887.712764 0)scale(0.996264)" xlink:href="#CMTT12-115"/> + <use transform="translate(938.978875 0)scale(0.996264)" xlink:href="#CMTT12-104"/> + <use transform="translate(990.244986 0)scale(0.996264)" xlink:href="#CMTT12-111"/> + <use transform="translate(1041.511097 0)scale(0.996264)" xlink:href="#CMTT12-108"/> + <use transform="translate(1092.777208 0)scale(0.996264)" xlink:href="#CMTT12-100"/> + <use transform="translate(1177.770814 0)scale(0.996264)" xlink:href="#CMTT12-72"/> + <use transform="translate(1262.76442 0)scale(0.996264)" xlink:href="#CMTT12-112"/> + <use transform="translate(1347.758026 0)scale(0.996264)" xlink:href="#CMTT12-99"/> + <use transform="translate(1399.024137 0)scale(0.996264)" xlink:href="#CMTT12-109"/> + <use transform="translate(1450.290248 0)scale(0.996264)" xlink:href="#CMTT12-51"/> + <path d="M 261.951565 0 +L 290.05805 0 +L 290.05805 0.3985 +L 261.951565 0.3985 +L 261.951565 0 +z +"/> + <path d="M 654.541837 0 +L 682.648321 0 +L 682.648321 0.3985 +L 654.541837 0.3985 +L 654.541837 0 +z +"/> + <path d="M 1149.664329 0 +L 1177.770814 0 +L 1177.770814 0.3985 +L 1149.664329 0.3985 +L 1149.664329 0 +z +"/> + <path d="M 1234.657936 0 +L 1262.76442 0 +L 1262.76442 0.3985 +L 1234.657936 0.3985 +L 1234.657936 0 +z +"/> + <path d="M 1319.651542 0 +L 1347.758026 0 +L 1347.758026 0.3985 +L 1319.651542 0.3985 +L 1319.651542 0 +z +"/> + </g> + </g> + <g id="text_16"> + <!-- ${\tt Cool\_temperature\_norm\_K}$ --> + <defs> + <path d="M 41.796875 38.921875 +C 41.796875 42 41.203125 43 37.796875 43 +L 31.203125 43 +C 29.796875 43 27.203125 43 27.203125 40.109375 +C 27.203125 37.203125 29.796875 37.203125 31.203125 37.203125 +L 35.296875 37.203125 +L 35.296875 15.625 +C 35.296875 7.484375 28.5 5.296875 24 5.296875 +C 16.09375 5.296875 16.09375 8.875 16.09375 11.96875 +L 16.09375 38.921875 +C 16.09375 42 15.5 43 12.09375 43 +L 5.5 43 +C 4.09375 43 1.5 43 1.5 40.109375 +C 1.5 37.203125 4.09375 37.203125 5.5 37.203125 +L 9.59375 37.203125 +L 9.59375 11.4375 +C 9.59375 2.28125 15.59375 -0.5 23.296875 -0.5 +C 29.40625 -0.5 33.203125 1.984375 35.203125 3.671875 +C 35.203125 0 37.59375 0 39.296875 0 +L 45.90625 0 +C 47.296875 0 49.90625 0 49.90625 2.90625 +C 49.90625 5.796875 47.296875 5.796875 45.90625 5.796875 +L 41.796875 5.796875 +z +" id="CMTT12-117"/> + <path d="M 27.09375 35.734375 +L 42.40625 55.203125 +C 45.296875 55.203125 47.59375 55.203125 47.59375 58.109375 +C 47.59375 61 45 61 43.59375 61 +L 35.203125 61 +C 33.796875 61 31.203125 61 31.203125 58.109375 +C 31.203125 55.203125 33.796875 55.203125 35.203125 55.203125 +L 14.203125 28.453125 +L 14.203125 55.203125 +L 16.203125 55.203125 +C 17.59375 55.203125 20.203125 55.203125 20.203125 58.109375 +C 20.203125 61 17.59375 61 16.203125 61 +L 6.59375 61 +C 5.203125 61 2.59375 61 2.59375 58.109375 +C 2.59375 55.203125 5.203125 55.203125 6.59375 55.203125 +L 8.59375 55.203125 +L 8.59375 5.796875 +L 6.59375 5.796875 +C 5.203125 5.796875 2.59375 5.796875 2.59375 2.90625 +C 2.59375 0 5.203125 0 6.59375 0 +L 16.203125 0 +C 17.59375 0 20.203125 0 20.203125 2.90625 +C 20.203125 5.796875 17.59375 5.796875 16.203125 5.796875 +L 14.203125 5.796875 +L 14.203125 19.375 +L 23.296875 30.953125 +L 37.203125 5.796875 +C 35.90625 5.796875 33.296875 5.796875 33.296875 2.90625 +C 33.296875 0 35.90625 0 37.296875 0 +L 44.5 0 +C 45.90625 0 48.5 0 48.5 2.90625 +C 48.5 5.796875 46.09375 5.796875 43.59375 5.796875 +z +" id="CMTT12-75"/> + </defs> + <g transform="translate(37.862259 66.86623)scale(0.07 -0.07)"> + <use transform="scale(0.996264)" xlink:href="#CMTT12-67"/> + <use transform="translate(51.266111 0)scale(0.996264)" xlink:href="#CMTT12-111"/> + <use transform="translate(102.532222 0)scale(0.996264)" xlink:href="#CMTT12-111"/> + <use transform="translate(153.798333 0)scale(0.996264)" xlink:href="#CMTT12-108"/> + <use transform="translate(238.791939 0)scale(0.996264)" xlink:href="#CMTT12-116"/> + <use transform="translate(290.05805 0)scale(0.996264)" xlink:href="#CMTT12-101"/> + <use transform="translate(341.32416 0)scale(0.996264)" xlink:href="#CMTT12-109"/> + <use transform="translate(392.590271 0)scale(0.996264)" xlink:href="#CMTT12-112"/> + <use transform="translate(443.856382 0)scale(0.996264)" xlink:href="#CMTT12-101"/> + <use transform="translate(495.122493 0)scale(0.996264)" xlink:href="#CMTT12-114"/> + <use transform="translate(546.388604 0)scale(0.996264)" xlink:href="#CMTT12-97"/> + <use transform="translate(597.654715 0)scale(0.996264)" xlink:href="#CMTT12-116"/> + <use transform="translate(648.920825 0)scale(0.996264)" xlink:href="#CMTT12-117"/> + <use transform="translate(700.186936 0)scale(0.996264)" xlink:href="#CMTT12-114"/> + <use transform="translate(751.453047 0)scale(0.996264)" xlink:href="#CMTT12-101"/> + <use transform="translate(836.446653 0)scale(0.996264)" xlink:href="#CMTT12-110"/> + <use transform="translate(887.712764 0)scale(0.996264)" xlink:href="#CMTT12-111"/> + <use transform="translate(938.978875 0)scale(0.996264)" xlink:href="#CMTT12-114"/> + <use transform="translate(990.244986 0)scale(0.996264)" xlink:href="#CMTT12-109"/> + <use transform="translate(1075.238592 0)scale(0.996264)" xlink:href="#CMTT12-75"/> + <path d="M 210.685454 0 +L 238.791939 0 +L 238.791939 0.3985 +L 210.685454 0.3985 +L 210.685454 0 +z +"/> + <path d="M 808.340169 0 +L 836.446653 0 +L 836.446653 0.3985 +L 808.340169 0.3985 +L 808.340169 0 +z +"/> + <path d="M 1047.132108 0 +L 1075.238592 0 +L 1075.238592 0.3985 +L 1047.132108 0.3985 +L 1047.132108 0 +z +"/> + </g> + </g> + <g id="text_17"> + <!-- ${\tt Jeans\_temperature\_norm\_K}$ --> + <g transform="translate(37.862259 81.545055)scale(0.07 -0.07)"> + <use transform="scale(0.996264)" xlink:href="#CMTT12-74"/> + <use transform="translate(51.266111 0)scale(0.996264)" xlink:href="#CMTT12-101"/> + <use transform="translate(102.532222 0)scale(0.996264)" xlink:href="#CMTT12-97"/> + <use transform="translate(153.798333 0)scale(0.996264)" xlink:href="#CMTT12-110"/> + <use transform="translate(205.064443 0)scale(0.996264)" xlink:href="#CMTT12-115"/> + <use transform="translate(290.05805 0)scale(0.996264)" xlink:href="#CMTT12-116"/> + <use transform="translate(341.32416 0)scale(0.996264)" xlink:href="#CMTT12-101"/> + <use transform="translate(392.590271 0)scale(0.996264)" xlink:href="#CMTT12-109"/> + <use transform="translate(443.856382 0)scale(0.996264)" xlink:href="#CMTT12-112"/> + <use transform="translate(495.122493 0)scale(0.996264)" xlink:href="#CMTT12-101"/> + <use transform="translate(546.388604 0)scale(0.996264)" xlink:href="#CMTT12-114"/> + <use transform="translate(597.654715 0)scale(0.996264)" xlink:href="#CMTT12-97"/> + <use transform="translate(648.920825 0)scale(0.996264)" xlink:href="#CMTT12-116"/> + <use transform="translate(700.186936 0)scale(0.996264)" xlink:href="#CMTT12-117"/> + <use transform="translate(751.453047 0)scale(0.996264)" xlink:href="#CMTT12-114"/> + <use transform="translate(802.719158 0)scale(0.996264)" xlink:href="#CMTT12-101"/> + <use transform="translate(887.712764 0)scale(0.996264)" xlink:href="#CMTT12-110"/> + <use transform="translate(938.978875 0)scale(0.996264)" xlink:href="#CMTT12-111"/> + <use transform="translate(990.244986 0)scale(0.996264)" xlink:href="#CMTT12-114"/> + <use transform="translate(1041.511097 0)scale(0.996264)" xlink:href="#CMTT12-109"/> + <use transform="translate(1126.504703 0)scale(0.996264)" xlink:href="#CMTT12-75"/> + <path d="M 261.951565 0 +L 290.05805 0 +L 290.05805 0.3985 +L 261.951565 0.3985 +L 261.951565 0 +z +"/> + <path d="M 859.60628 0 +L 887.712764 0 +L 887.712764 0.3985 +L 859.60628 0.3985 +L 859.60628 0 +z +"/> + <path d="M 1098.398219 0 +L 1126.504703 0 +L 1126.504703 0.3985 +L 1098.398219 0.3985 +L 1098.398219 0 +z +"/> + </g> + </g> + </g> + </g> + <defs> + <clipPath id="p107a2e5a22"> + <rect height="195.048" width="190.512" x="34.02" y="2.268"/> + </clipPath> + </defs> +</svg> diff --git a/doc/RTD/source/SubgridModels/EAGLE/index.rst b/doc/RTD/source/SubgridModels/EAGLE/index.rst index e2489452ef6ce73d9ca98e63f660fc65e0113f38..aab9de72ab1cd9dd029f7a4bb999de8ff1724295 100644 --- a/doc/RTD/source/SubgridModels/EAGLE/index.rst +++ b/doc/RTD/source/SubgridModels/EAGLE/index.rst @@ -9,6 +9,66 @@ This section of the documentation gives a brief description of the different components of the EAGLE sub-grid model. We mostly focus on the parameters and values output in the snapshots. +.. _EAGLE_entropy_floors: + +Entropy floors +~~~~~~~~~~~~~~ + +The gas particles in the EAGLE model are prevented from cooling below a +certain temperature. The temperature limit depends on the density of the +particles. Two floors are used in conjonction. Both are implemented as +polytropic "equations of states" :math:`P = P_c +\left(\rho/\rho_c\right)^\gamma`, with the constants derived from the user +input given in terms of temperature and Hydrogen number density. + +The first limit, labelled as ``Cool``, is typically used to prevent +low-density high-metallicity particles to cool below the warm phase because +of over-cooling induced by the absence of metal diffusion. This limit plays +only a small role in practice. The second limit, labelled as ``Jeans``, is +used to prevent the fragmentation of high-density gas into clumps that +cannot be resolved by the solver. The two limits are sketched on the +following figure. An additional over-density criterion is applied to +prevent gas not collapsed into structures from being affected. + +.. figure:: EAGLE_entropy_floor.svg + :width: 400px + :align: center + :figclass: align-center + :alt: Phase-space diagram displaying the two entropy floors used + in the EAGLE model. + + Temperature-density plane with the two entropy floors used in the EAGLE + model indicated by the black lines. Gas particles are not allowed to be + below either of these two floors; they are hence forbidden to enter the + grey-shaded region. The floors are specified by the position in the + plane of the starting point of each line (black circle) and their slope + (dashed lines). The parameter names governing the behaviour of the + floors are indicated on the figure. Note that unlike what is shown on + the figure for clarity reasons, typical values for EAGLE runs place + both anchors at the same temperature. + + +The model is governed by 4 parameters for each of the two +limits. These are given in the ``EAGLEEntropyFloor`` section of the +YAML file. The parameters are the Hydrogen number density (in +:math:`cm^{-3}`) and temperature (in :math:`K`) of the anchor point of +each floor as well as the power-law slope of each floor and the +minimal over-density required to apply the limit [#f1]_. For a normal +EAGLE run, that section of the parameter file reads: + +.. code:: YAML + + EAGLEEntropyFloor: + Jeans_density_threshold_H_p_cm3: 0.1 # Physical density above which the EAGLE Jeans limiter entropy floor kicks in, expressed in Hydrogen atoms per cm^3. + Jeans_over_density_threshold: 10. # Overdensity above which the EAGLE Jeans limiter entropy floor can kick in. + Jeans_temperature_norm_K: 8000 # Temperature of the EAGLE Jeans limiter entropy floor at the density threshold, expressed in Kelvin. + Jeans_gamma_effective: 1.3333333 # Slope the of the EAGLE Jeans limiter entropy floor + Cool_density_threshold_H_p_cm3: 1e-5 # Physical density above which the EAGLE Cool limiter entropy floor kicks in, expressed in Hydrogen atoms per cm^3. + Cool_over_density_threshold: 10. # Overdensity above which the EAGLE Cool limiter entropy floor can kick in. + Cool_temperature_norm_K: 8000 # Temperature of the EAGLE Cool limiter entropy floor at the density threshold, expressed in Kelvin. + Cool_gamma_effective: 1. # Slope the of the EAGLE Cool limiter entropy floor + + .. _EAGLE_chemical_tracers: Chemical tracers @@ -18,7 +78,7 @@ The gas particles in the EAGLE model carry metal abundance information in the form of metal mass fractions. We follow explicitly 9 of the 11 elements that `Wiersma et al. (2009)b <http://adsabs.harvard.edu/abs/2009MNRAS.399..574W>`_ traced in their chemical enrichment model. These are: `H`, `He`, `C`, `N`, `O`, -`Ne`, `Mg`, `Si` and `Fe` [#f1]_. We additionally follow the total metal mass fraction +`Ne`, `Mg`, `Si` and `Fe` [#f2]_. We additionally follow the total metal mass fraction (i.e. absolute metallicity) `Z`. This is typically larger than the sum of the 7 metals that are individually traced since this will also contain the contribution of all the elements that are not individually followed. We note @@ -336,9 +396,15 @@ Black-hole accretion AGN feedback ~~~~~~~~~~~~ -.. [#f1] `Wiersma et al. (2009)b +.. [#f1] Recall that in a non-cosmological run the critical density is + set to 0, effectively removing the over-density + constraint of the floors. + +.. [#f2] `Wiersma et al. (2009)b <http://adsabs.harvard.edu/abs/2009MNRAS.399..574W>`_ originally also followed explicitly `Ca` and and `S`. They are omitted in the EAGLE model but, when needed, their abundance with respect to solar is assumed to be the same as the abundance of `Si` with respect to solar (See the section :ref:`EAGLE_cooling`) + + diff --git a/doc/RTD/source/SubgridModels/EAGLE/plot_EAGLE_entropy_floor.py b/doc/RTD/source/SubgridModels/EAGLE/plot_EAGLE_entropy_floor.py new file mode 100644 index 0000000000000000000000000000000000000000..5b02dd657fdb32e411961f04d0d758119344b809 --- /dev/null +++ b/doc/RTD/source/SubgridModels/EAGLE/plot_EAGLE_entropy_floor.py @@ -0,0 +1,60 @@ +import matplotlib +matplotlib.use("Agg") +from pylab import * +from scipy import stats + +# Plot parameters +params = { + "axes.labelsize": 10, + "axes.titlesize": 10, + "font.size": 9, + "legend.fontsize": 9, + "xtick.labelsize": 10, + "ytick.labelsize": 10, + "text.usetex": True, + "figure.figsize": (3.15, 3.15), + "figure.subplot.left": 0.15, + "figure.subplot.right": 0.99, + "figure.subplot.bottom": 0.13, + "figure.subplot.top": 0.99, + "figure.subplot.wspace": 0.15, + "figure.subplot.hspace": 0.12, + "lines.markersize": 6, + "lines.linewidth": 2.0, + "text.latex.unicode": True, +} +rcParams.update(params) +rc("font", **{"family": "sans-serif", "sans-serif": ["Times"]}) + +# Equations of state +eos_cool_rho = np.logspace(-5, 5, 1000) +eos_cool_T = eos_cool_rho**0. * 8000. +eos_Jeans_rho = np.logspace(-1, 5, 1000) +eos_Jeans_T = (eos_Jeans_rho/ 10**(-1))**(1./3.) * 4000. + +# Plot the phase space diagram +figure() +subplot(111, xscale="log", yscale="log") +plot(eos_cool_rho, eos_cool_T, 'k-', lw=1.) +plot(eos_Jeans_rho, eos_Jeans_T, 'k-', lw=1.) +plot([1e-10, 1e-5], [8000, 8000], 'k:', lw=0.6) +plot([1e-10, 1e-1], [4000, 4000], 'k:', lw=0.6) +plot([1e-5, 1e-5], [20, 8000], 'k:', lw=0.6) +plot([1e-1, 1e-1], [20, 4000], 'k:', lw=0.6) +plot([3e-6, 3e-4], [28000, 28000], 'k--', lw=0.6) +text(3e-6, 22500, "$n_{\\rm H}~\\widehat{}~{\\tt Cool\\_gamma\\_effective}$", va="top", fontsize=7) +plot([3e-1, 3e1], [15000., 15000.*10.**(2./3.)], 'k--', lw=0.6) +text(3e-1, 200000, "$n_{\\rm H}~\\widehat{}~{\\tt Jeans\\_gamma\\_effective}$", va="top", rotation=43, fontsize=7) +text(0.95e-5, 25, "${\\tt Cool\\_density\\_threshold\\_H\\_p\\_cm3}$", rotation=90, va="bottom", ha="right", fontsize=7) +text(0.95e-1, 25, "${\\tt Jeans\\_density\\_threshold\\_H\\_p\\_cm3}$", rotation=90, va="bottom", ha="right", fontsize=7) +text(5e-8, 8800, "${\\tt Cool\\_temperature\\_norm\\_K}$", va="bottom", fontsize=7) +text(5e-8, 4400, "${\\tt Jeans\\_temperature\\_norm\\_K}$", va="bottom", fontsize=7) +fill_between([1e-5, 1e5], [10, 10], [8000, 8000], color='0.9') +fill_between([1e-1, 1e5], [4000, 400000], color='0.9') +scatter([1e-5], [8000], s=4, color='k') +scatter([1e-1], [4000], s=4, color='k') +xlabel("${\\rm Density}~n_{\\rm H}~[{\\rm cm^{-3}}]$", labelpad=0) +ylabel("${\\rm Temperature}~T~[{\\rm K}]$", labelpad=2) +xlim(3e-8, 3e3) +ylim(20., 2e5) +savefig("EAGLE_entropy_floor.png", dpi=200) diff --git a/examples/IsolatedGalaxy_starformation/README b/examples/IsolatedGalaxy_starformation/README new file mode 100644 index 0000000000000000000000000000000000000000..16d2abde23b742e421bbd8c04a632edb0e35108a --- /dev/null +++ b/examples/IsolatedGalaxy_starformation/README @@ -0,0 +1,40 @@ +Isolated Galaxy generated by the MakeNewDisk code from Springel, Di Matteo & +Hernquist (2005). The done analysis in this example is similar to the work +done by Schaye and Dalla Vecchia (2008) (After this SD08). The default example +runs the simulation for a galaxy with similar mass of their fiducial model +and should produce plots similar to their middle pannel Figure 4. + +The code can also be run for other situations to check to verify the law using +different parameters, changes that were done in SD08 are given by: + - gas fraction of 10% instead of 30%, change the IC to f10.hdf5, see getIC.sh, + should reproduce something similar to Figure 4 left hand pannel. Requires + change of fg=.1 + - gas fraction of 90% instead of 30%, change the IC to f90.hdf5, see getIC.sh, + should reproduce something similar to Figure 4 right hand pannel. Requires + change of fg=.9 + - Changing the effective equation of state to adiabatic, Jeans_gamma_effective + = 1.666667. Should result in something similar to Figure 5 left hand pannel + of SD08. + - Changing the effective equation of state to isothermal, Jeans_gamma_effective + = 1.0000. Should result in something similar to Figure 5 middle hand pannel + of SD08. + - Changing the slope of the Kennicutt-Schmidt law to 1.7, SchmidtLawExponent = + 1.7, this should result in a plot similar to Figure 6 of SD08. + - Increasing the density threshold by a factor of 10. thresh_norm_HpCM3 = 1.0, + should reproduce plot similar to Figure 7. + - Decreasing the density threshold by a factor of 10. thresh_norm_HpCM3 = 0.01, + should reproduce plot similar to Figure 7. + - Running with a lower resultion of a factor 8, change the IC to lowres8.hdf5, + see getIC.sh. + - Running with a lower resultion of a factor 64, change the IC to lowres64.hdf5, + see getIC.sh. + - Running with a lower resultion of a factor 512, change the IC to lowres512.hdf5, + see getIC.sh. + +Other options to verify the correctness of the code is by chaning the following +parameters: + - Changing the normalization to A/2 or 2A. + - Running the code with zero metallicity. + - Running the code with a factor 6 higher resolution idealized disks, use + highres6.hdf5, see getIC.sh. + - Running with different SPH schemes like Anarchy-PU. diff --git a/examples/IsolatedGalaxy_starformation/SFH.py b/examples/IsolatedGalaxy_starformation/SFH.py new file mode 100644 index 0000000000000000000000000000000000000000..fa9d9258530396fb7f95237a45af5db9c0da4603 --- /dev/null +++ b/examples/IsolatedGalaxy_starformation/SFH.py @@ -0,0 +1,100 @@ +""" +Makes a movie using sphviewer and ffmpeg. + +Edit low_frac and up_frac to focus on a certain view of the box. +The colour map can also be changed via colour_map. + +Usage: python3 makeMovie.py CoolingHalo_ + +Written by James Willis (james.s.willis@durham.ac.uk) +""" + +import glob +import h5py as h5 +import numpy as np +import matplotlib.pyplot as plt + +from tqdm import tqdm + + +def getSFH(filename): + + # Read the data + with h5.File(filename, "r") as f: + box_size = f["/Header"].attrs["BoxSize"][0] + coordinates = f["/PartType4/Coordinates"][:, :] + mass = f["/PartType4/Masses"][:] + # flag = f["/PartType4/NewStarFlag"][:] + birth_time = f["/PartType4/Birth_time"][:] + + absmaxz = 2 # kpc + absmaxxy = 10 # kpc + + part_mask = ( + ((coordinates[:, 0] - box_size / 2.0) > -absmaxxy) + & ((coordinates[:, 0] - box_size / 2.0) < absmaxxy) + & ((coordinates[:, 1] - box_size / 2.0) > -absmaxxy) + & ((coordinates[:, 1] - box_size / 2.0) < absmaxxy) + & ((coordinates[:, 2] - box_size / 2.0) > -absmaxz) + & ((coordinates[:, 2] - box_size / 2.0) < absmaxz) + ) # & (flag==1) + + birth_time = birth_time[part_mask] + mass = mass[part_mask] + + histogram = np.histogram(birth_time, bins=200, weights=mass * 2e4, range=[0, 0.1]) + values = histogram[0] + xvalues = (histogram[1][:-1] + histogram[1][1:]) / 2.0 + return xvalues, values + + +def getsfrsnapwide(): + + time = np.arange(1, 101, 1) + SFR_sparticles = np.zeros(100) + SFR_gparticles = np.zeros(100) + new_sparticles = np.zeros(100) + previous_mass = 0 + previous_numb = 0 + for i in tqdm(range(1, 100)): + # Read the data + filename = "output_%04d.hdf5" % i + with h5.File(filename, "r") as f: + box_size = f["/Header"].attrs["BoxSize"][0] + coordinates = f["/PartType0/Coordinates"][:, :] + SFR = f["/PartType0/SFR"][:] + coordinates_star = f["/PartType4/Coordinates"][:, :] + masses_star = f["/PartType4/Masses"][:] + + absmaxz = 2 # kpc + absmaxxy = 10 # kpc + + part_mask = ( + ((coordinates[:, 0] - box_size / 2.0) > -absmaxxy) + & ((coordinates[:, 0] - box_size / 2.0) < absmaxxy) + & ((coordinates[:, 1] - box_size / 2.0) > -absmaxxy) + & ((coordinates[:, 1] - box_size / 2.0) < absmaxxy) + & ((coordinates[:, 2] - box_size / 2.0) > -absmaxz) + & ((coordinates[:, 2] - box_size / 2.0) < absmaxz) + & (SFR > 0) + ) + + SFR = SFR[part_mask] + + total_SFR = np.sum(SFR) + SFR_gparticles[i] = total_SFR * 10 + + return time[:-1], SFR_gparticles[1:] + + +if __name__ == "__main__": + + time, SFR1 = getsfrsnapwide() # , SFR2, SFR_error = getsfrsnapwide() + time2, SFR3 = getSFH("output_%04d.hdf5" % 100) + plt.plot(time2[1:] * 1e3, SFR3[1:], label="Using birth_time of star particles") + plt.plot(time, SFR1, label="Using SFR of gas particles", color="g") + plt.xlabel("Time (Myr)") + plt.ylabel("SFH ($\\rm M_\odot \\rm yr^{-1}$)") + plt.ylim(0, 20) + plt.legend() + plt.savefig("SFH.png") diff --git a/examples/IsolatedGalaxy_starformation/getIC.sh b/examples/IsolatedGalaxy_starformation/getIC.sh new file mode 100755 index 0000000000000000000000000000000000000000..197bc332fc1d2d140d572ecb4bfd8ca9b30e50b9 --- /dev/null +++ b/examples/IsolatedGalaxy_starformation/getIC.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +wget https://www.strw.leidenuniv.nl/~nobels/swiftdata/fid.hdf5 +# wget https://www.strw.leidenuniv.nl/~nobels/swiftdata/f10.hdf5 +# wget https://www.strw.leidenuniv.nl/~nobels/swiftdata/f90.hdf5 +# wget https://www.strw.leidenuniv.nl/~nobels/swiftdata/lowres8.hdf5 +# wget https://www.strw.leidenuniv.nl/~nobels/swiftdata/lowres64.hdf5 +# wget https://www.strw.leidenuniv.nl/~nobels/swiftdata/lowres512.hdf5 +# wget https://www.strw.leidenuniv.nl/~nobels/swiftdata/highres6.hdf5 diff --git a/examples/IsolatedGalaxy_starformation/isolated_galaxy.yml b/examples/IsolatedGalaxy_starformation/isolated_galaxy.yml new file mode 100644 index 0000000000000000000000000000000000000000..d518732056f508cbf896dcd5f258663522a91eea --- /dev/null +++ b/examples/IsolatedGalaxy_starformation/isolated_galaxy.yml @@ -0,0 +1,111 @@ +# Define the system of units to use internally. +InternalUnitSystem: + UnitMass_in_cgs: 1.9891E43 # 10^10 solar masses + UnitLength_in_cgs: 3.08567758E21 # 1 kpc + UnitVelocity_in_cgs: 1E5 # km/s + UnitCurrent_in_cgs: 1 # Amperes + UnitTemp_in_cgs: 1 # Kelvin + +# 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). + +# Parameters governing the time integration (Set dt_min and dt_max to the same value for a fixed time-step run.) +TimeIntegration: + time_begin: 0. # The starting time of the simulation (in internal units). + time_end: 0.1 # The end time of the simulation (in internal units). + dt_min: 1e-9 # The minimal time-step size of the simulation (in internal units). + dt_max: 1e-2 # The maximal time-step size of the simulation (in internal units). + +# Parameters governing the snapshots +Snapshots: + basename: output # Common part of the name of output files + time_first: 0. # (Optional) Time of the first output if non-cosmological time-integration (in internal units) + delta_time: 0.001 # Time difference between consecutive outputs (in internal units) + + +# Parameters governing the conserved quantities statistics +Statistics: + delta_time: 1e-2 # Time between statistics output + time_first: 0. # (Optional) Time of the first stats output if non-cosmological time-integration (in internal units) + +# Parameters related to the initial conditions +InitialConditions: + file_name: fid.hdf5 # The file to read + periodic: 0 # Are we running with periodic ICs? + +# Parameters for the hydrodynamics scheme +SPH: + resolution_eta: 1.2348 # Target smoothing length in units of the mean inter-particle separation (1.2348 == 48Ngbs with the cubic spline kernel). + CFL_condition: 0.1 # Courant-Friedrich-Levy condition for time integration. + h_tolerance: 1e-4 # (Optional) Relative accuracy of the Netwon-Raphson scheme for the smoothing lengths. + h_max: 10. # (Optional) Maximal allowed smoothing length in internal units. Defaults to FLT_MAX if unspecified. + max_volume_change: 1.4 # (Optional) Maximal allowed change of kernel volume over one time-step. + max_ghost_iterations: 30 # (Optional) Maximal number of iterations allowed to converge towards the smoothing length. + minimal_temperature: 100 # (Optional) Minimal temperature (in internal units) allowed for the gas particles. Value is ignored if set to 0. + H_ionization_temperature: 1e4 # (Optional) Temperature of the transition from neutral to ionized Hydrogen for primoridal gas. + +EAGLECooling: + dir_name: ./coolingtables/ # Location of the Wiersma+08 cooling tables + H_reion_z: 11.5 # Redshift of Hydrogen re-ionization + He_reion_z_centre: 3.5 # Redshift of the centre of the Helium re-ionization Gaussian + He_reion_z_sigma: 0.5 # Spread in redshift of the Helium re-ionization Gaussian + He_reion_eV_p_H: 2.0 # Energy inject by Helium re-ionization in electron-volt per Hydrogen atom + +# Primordial abundances +EAGLEChemistry: + init_abundance_metal: 0.0129 # Inital fraction of particle mass in *all* metals + init_abundance_Hydrogen: 0.7065 # Inital fraction of particle mass in Hydrogen + init_abundance_Helium: 0.2806 # Inital fraction of particle mass in Helium + init_abundance_Carbon: 0.00207 # Inital fraction of particle mass in Carbon + init_abundance_Nitrogen: 0.000836 # Inital fraction of particle mass in Nitrogen + init_abundance_Oxygen: 0.00549 # Inital fraction of particle mass in Oxygen + init_abundance_Neon: 0.00141 # Inital fraction of particle mass in Neon + init_abundance_Magnesium: 0.000591 # Inital fraction of particle mass in Magnesium + init_abundance_Silicon: 0.000683 # Inital fraction of particle mass in Silicon + init_abundance_Iron: 0.0011 # Inital fraction of particle mass in Iron + +# Hernquist potential parameters +HernquistPotential: + useabspos: 0 # 0 -> positions based on centre, 1 -> absolute positions + position: [0.,0.,0.] # Location of centre of isothermal potential with respect to centre of the box (if 0) otherwise absolute (if 1) (internal units) + idealizeddisk: 1 # Run with an idealized galaxy disk + M200: 137.0 # M200 of the galaxy disk + h: 0.704 # reduced Hubble constant (value does not specify the used units!) + concentration: 9.0 # concentration of the Halo + diskfraction: 0.040 # Disk mass fraction + bulgefraction: 0.014 # Bulge mass fraction + timestep_mult: 0.01 # Dimensionless pre-factor for the time-step condition, basically determines the fraction of the orbital time we use to do the time integration + epsilon: 0.01 # Softening size (internal units) + +# EAGLE star formation parameters +EAGLEStarFormation: + EOS_density_norm_H_p_cm3: 0.1 # Physical density used for the normalisation of the EOS assumed for the star-forming gas in Hydrogen atoms per cm^3. + EOS_temperature_norm_K: 8000 # Temperature om the polytropic EOS assumed for star-forming gas at the density normalisation in Kelvin. + EOS_gamma_effective: 1.3333333 # Slope the of the polytropic EOS assumed for the star-forming gas. + gas_fraction: 0.3 # The gas fraction used internally by the model. + KS_normalisation: 1.515e-4 # The normalization of the Kennicutt-Schmidt law in Msun / kpc^2 / yr. + KS_exponent: 1.4 # The exponent of the Kennicutt-Schmidt law. + KS_min_over_density: 57.7 # The over-density above which star-formation is allowed. + KS_high_density_threshold_H_p_cm3: 1e3 # Hydrogen number density above which the Kennicut-Schmidt law changes slope in Hydrogen atoms per cm^3. + KS_high_density_exponent: 2.0 # Slope of the Kennicut-Schmidt law above the high-density threshold. + KS_temperature_margin_dex: 0.5 # Logarithm base 10 of the maximal temperature difference above the EOS allowed to form stars. + threshold_norm_H_p_cm3: 0.1 # Normalisation of the metal-dependant density threshold for star formation in Hydrogen atoms per cm^3. + threshold_Z0: 0.002 # Reference metallicity (metal mass fraction) for the metal-dependant threshold for star formation. + threshold_slope: -0.64 # Slope of the metal-dependant star formation threshold + threshold_max_density_H_p_cm3: 10.0 # Maximal density of the metal-dependant density threshold for star formation in Hydrogen atoms per cm^3. + +# Parameters for the EAGLE "equation of state" +EAGLEEntropyFloor: + Jeans_density_threshold_H_p_cm3: 0.1 # Physical density above which the EAGLE Jeans limiter entropy floor kicks in expressed in Hydrogen atoms per cm^3. + Jeans_over_density_threshold: 10. # Overdensity above which the EAGLE Jeans limiter entropy floor can kick in. + Jeans_temperature_norm_K: 8000 # Temperature of the EAGLE Jeans limiter entropy floor at the density threshold expressed in Kelvin. + Jeans_gamma_effective: 1.3333333 # Slope the of the EAGLE Jeans limiter entropy floor + Cool_density_threshold_H_p_cm3: 1e-5 # Physical density above which the EAGLE Cool limiter entropy floor kicks in expressed in Hydrogen atoms per cm^3. + Cool_over_density_threshold: 10. # Overdensity above which the EAGLE Cool limiter entropy floor can kick in. + Cool_temperature_norm_K: 8000 # Temperature of the EAGLE Cool limiter entropy floor at the density threshold expressed in Kelvin. + Cool_gamma_effective: 1. # Slope the of the EAGLE Cool limiter entropy floor diff --git a/examples/IsolatedGalaxy_starformation/plotSolution.py b/examples/IsolatedGalaxy_starformation/plotSolution.py new file mode 100644 index 0000000000000000000000000000000000000000..4e5fcf2ceb2b3f0682871cc533fab93039ff38e9 --- /dev/null +++ b/examples/IsolatedGalaxy_starformation/plotSolution.py @@ -0,0 +1,368 @@ +import matplotlib + +matplotlib.use("Agg") +from pylab import * +from scipy import stats +import h5py as h5 + +# Plot parameters +params = { + "axes.labelsize": 10, + "axes.titlesize": 10, + "font.size": 9, + "legend.fontsize": 9, + "xtick.labelsize": 10, + "ytick.labelsize": 10, + "text.usetex": True, + "figure.figsize": (3.15, 3.15), + "figure.subplot.left": 0.15, + "figure.subplot.right": 0.99, + "figure.subplot.bottom": 0.13, + "figure.subplot.top": 0.99, + "figure.subplot.wspace": 0.15, + "figure.subplot.hspace": 0.12, + "lines.markersize": 6, + "lines.linewidth": 2.0, + "text.latex.unicode": True, +} +rcParams.update(params) +rc("font", **{"family": "sans-serif", "sans-serif": ["Times"]}) + +snap = int(sys.argv[1]) +filename = "output_%.4d.hdf5"%snap + +f = h5.File(filename, "r") + +# Physical constants +k_in_cgs = 1.38064852e-16 +mH_in_cgs = 1.6737236e-24 +year_in_cgs = 3600.0 * 24 * 365.0 +Msun_in_cgs = 1.98848e33 +G_in_cgs = 6.67259e-8 +pc_in_cgs = 3.08567758e18 +Msun_p_pc2 = Msun_in_cgs / pc_in_cgs**2 + +# Gemoetry info +boxsize = f["/Header"].attrs["BoxSize"] +centre = boxsize / 2.0 + +# Read units +unit_length_in_cgs = f["/Units"].attrs["Unit length in cgs (U_L)"] +unit_mass_in_cgs = f["/Units"].attrs["Unit mass in cgs (U_M)"] +unit_time_in_cgs = f["/Units"].attrs["Unit time in cgs (U_t)"] + +# Calculate Gravitational constant in internal units +G = G_in_cgs * ( unit_length_in_cgs**3 / unit_mass_in_cgs / unit_time_in_cgs**2)**(-1) + +# Read parameters of the SF model +KS_law_slope = float(f["/Parameters"].attrs["EAGLEStarFormation:KS_exponent"]) +KS_law_norm = float(f["/Parameters"].attrs["EAGLEStarFormation:KS_normalisation"]) +KS_thresh_Z0 = float(f["/Parameters"].attrs["EAGLEStarFormation:threshold_Z0"]) +KS_thresh_slope = float(f["/Parameters"].attrs["EAGLEStarFormation:threshold_slope"]) +KS_thresh_norm = float(f["/Parameters"].attrs["EAGLEStarFormation:threshold_norm_H_p_cm3"]) +KS_gas_fraction = float(f["/Parameters"].attrs["EAGLEStarFormation:gas_fraction"]) +KS_thresh_max_norm = float(f["/Parameters"].attrs["EAGLEStarFormation:threshold_max_density_H_p_cm3"]) +KS_high_den_thresh = float(f["/Parameters"].attrs["EAGLEStarFormation:KS_high_density_threshold_H_p_cm3"]) +KS_law_slope_high_den = float(f["/Parameters"].attrs["EAGLEStarFormation:KS_high_density_exponent"]) +EOS_gamma_effective = float(f["/Parameters"].attrs["EAGLEStarFormation:EOS_gamma_effective"]) +EOS_density_norm = float(f["/Parameters"].attrs["EAGLEStarFormation:EOS_density_norm_H_p_cm3"]) +EOS_temp_norm = float(f["/Parameters"].attrs["EAGLEStarFormation:EOS_temperature_norm_K"]) + +# Read reference metallicity +EAGLE_Z = float(f["/Parameters"].attrs["EAGLEChemistry:init_abundance_metal"]) + +# Read parameters of the entropy floor +EAGLEfloor_Jeans_rho_norm = float(f["/Parameters"].attrs["EAGLEEntropyFloor:Jeans_density_threshold_H_p_cm3"]) +EAGLEfloor_Jeans_temperature_norm_K = float(f["/Parameters"].attrs["EAGLEEntropyFloor:Jeans_temperature_norm_K"]) +EAGLEfloor_Jeans_gamma_effective = float(f["/Parameters"].attrs["EAGLEEntropyFloor:Jeans_gamma_effective"]) +EAGLEfloor_cool_rho_norm = float(f["/Parameters"].attrs["EAGLEEntropyFloor:Cool_density_threshold_H_p_cm3"]) +EAGLEfloor_cool_temperature_norm_K = float(f["/Parameters"].attrs["EAGLEEntropyFloor:Cool_temperature_norm_K"]) +EAGLEfloor_cool_gamma_effective = float(f["/Parameters"].attrs["EAGLEEntropyFloor:Cool_gamma_effective"]) + +# Properties of the KS law +KS_law_norm_cgs = KS_law_norm * Msun_in_cgs / ( 1e6 * pc_in_cgs**2 * year_in_cgs ) +gamma = 5./3. +EOS_press_norm = k_in_cgs * EOS_temp_norm * EOS_density_norm + +# Star formation threshold +SF_thresh = KS_thresh_norm * (EAGLE_Z / KS_thresh_Z0)**(KS_thresh_slope) + +# Read gas properties +gas_pos = f["/PartType0/Coordinates"][:, :] +gas_mass = f["/PartType0/Masses"][:] +gas_rho = f["/PartType0/Density"][:] +gas_T = f["/PartType0/Temperature"][:] +gas_SFR = f["/PartType0/SFR"][:] +gas_XH = f["/PartType0/ElementAbundance"][:, 0] +gas_Z = f["/PartType0/Metallicity"][:] +gas_hsml = f["/PartType0/SmoothingLength"][:] +gas_sSFR = gas_SFR / gas_mass + +# Read the Star properties +stars_pos = f["/PartType4/Coordinates"][:, :] +stars_BirthDensity = f["/PartType4/BirthDensity"][:] +stars_BirthTime = f["/PartType4/Birth_time"][:] +stars_XH = f["/PartType4/ElementAbundance"][:,0] + +# Centre the box +gas_pos[:, 0] -= centre[0] +gas_pos[:, 1] -= centre[1] +gas_pos[:, 2] -= centre[2] + +stars_pos[:,0] -= centre[0] +stars_pos[:,1] -= centre[1] +stars_pos[:,2] -= centre[2] + +# Turn the mass into better units +gas_mass *= unit_mass_in_cgs / Msun_in_cgs + +# Turn the SFR into better units +gas_SFR = np.maximum(gas_SFR, np.zeros(np.size(gas_SFR))) +gas_SFR /= unit_time_in_cgs / year_in_cgs +gas_SFR *= unit_mass_in_cgs / Msun_in_cgs + +# Make it a Hydrogen number density +gas_nH = gas_rho * unit_mass_in_cgs / unit_length_in_cgs ** 3 +gas_nH /= mH_in_cgs +gas_nH *= gas_XH + +stars_BirthDensity *= unit_mass_in_cgs / unit_length_in_cgs ** 3 +stars_BirthDensity /= mH_in_cgs +stars_BirthDensity *= stars_XH + +# Equations of state +eos_cool_rho = np.logspace(-5, 5, 1000) +eos_cool_T = EAGLEfloor_cool_temperature_norm_K * (eos_cool_rho / EAGLEfloor_cool_rho_norm) ** ( EAGLEfloor_cool_gamma_effective - 1.0 ) +eos_Jeans_rho = np.logspace(-1, 5, 1000) +eos_Jeans_T = EAGLEfloor_Jeans_temperature_norm_K * (eos_Jeans_rho / EAGLEfloor_Jeans_rho_norm) ** (EAGLEfloor_Jeans_gamma_effective - 1.0 ) + +########################################################################3 + +# Plot the phase space diagram +figure() +subplot(111, xscale="log", yscale="log") +plot(eos_cool_rho, eos_cool_T, "k--", lw=0.6) +plot(eos_Jeans_rho, eos_Jeans_T, "k--", lw=0.6) +scatter(gas_nH, gas_T, s=0.2) +xlabel("${\\rm Density}~n_{\\rm H}~[{\\rm cm^{-3}}]$", labelpad=0) +ylabel("${\\rm Temperature}~T~[{\\rm K}]$", labelpad=2) +xlim(3e-6, 3e3) +ylim(500.0, 2e5) +savefig("rhoT.png", dpi=200) + +# Plot the phase space diagram for SF gas +figure() +subplot(111, xscale="log", yscale="log") +plot(eos_cool_rho, eos_cool_T, "k--", lw=0.6) +plot(eos_Jeans_rho, eos_Jeans_T, "k--", lw=0.6) +plot([SF_thresh, SF_thresh], [1, 1e10], "k:", lw=0.6) +text(SF_thresh*0.9, 2e4, "$n_{\\rm H, thresh}=%.3f~{\\rm cm^{-3}}$"%SF_thresh, fontsize=8, rotation=90, ha="right", va="bottom") +scatter(gas_nH[gas_SFR > 0.0], gas_T[gas_SFR > 0.0], s=0.2) +xlabel("${\\rm Density}~n_{\\rm H}~[{\\rm cm^{-3}}]$", labelpad=0) +ylabel("${\\rm Temperature}~T~[{\\rm K}]$", labelpad=2) +xlim(3e-6, 3e3) +ylim(500.0, 2e5) +savefig("rhoT_SF.png", dpi=200) + +########################################################################3 + +# 3D Density vs SFR +figure() +subplot(111, xscale="log", yscale="log") +scatter(gas_nH, gas_SFR, s=0.2) +plot([1, 100], 2e-5 * np.array([1, 100]) ** 0.266667, "k--", lw=1) +xlabel("${\\rm Density}~n_{\\rm H}~[{\\rm cm^{-3}}]$", labelpad=0) +ylabel("${\\rm SFR}~[{\\rm M_\\odot~\\cdot~yr^{-1}}]$", labelpad=-7) +xlim(1e-4, 3e3) +ylim(8e-6, 2.5e-4) +savefig("rho_SFR.png", dpi=200) + +########################################################################3 + +star_mask = ( + (stars_pos[:, 0] > -15) + & (stars_pos[:, 0] < 15) + & (stars_pos[:, 1] > -15) + & (stars_pos[:, 1] < 15) + & (stars_pos[:, 2] < 1.0) + & (stars_pos[:, 2] > -1.0) +) + +stars_BirthDensity = stars_BirthDensity[star_mask] +#stars_BirthFlag = stars_BirthFlag[star_mask] +stars_BirthTime = stars_BirthTime[star_mask] + +# Histogram of the birth density +figure() +subplot(111, xscale="linear", yscale="linear") +hist(np.log10(stars_BirthDensity),density=True,bins=20,range=[-2,5]) +xlabel("${\\rm Stellar~birth~density}~n_{\\rm H}~[{\\rm cm^{-3}}]$", labelpad=0) +ylabel("${\\rm Probability}$", labelpad=-7) +savefig("BirthDensity.png", dpi=200) + +# Plot of the specific star formation rate in the galaxy +rhos = 10**np.linspace(-1,np.log10(KS_high_den_thresh),100) +rhoshigh = 10**np.linspace(np.log10(KS_high_den_thresh),5,100) + +P_effective = EOS_press_norm * ( rhos / EOS_density_norm)**(EOS_gamma_effective) +P_norm_high = EOS_press_norm * (KS_high_den_thresh / EOS_density_norm)**(EOS_gamma_effective) +sSFR = KS_law_norm_cgs * (Msun_p_pc2)**(-KS_law_slope) * (gamma/G_in_cgs * KS_gas_fraction *P_effective)**((KS_law_slope-1.)/2.) +KS_law_norm_high_den_cgs = KS_law_norm_cgs * (Msun_p_pc2)**(-KS_law_slope) * (gamma/G_in_cgs * KS_gas_fraction * P_norm_high)**((KS_law_slope-1.)/2.) +sSFR_high_den = KS_law_norm_high_den_cgs * ((rhoshigh/KS_high_den_thresh)**EOS_gamma_effective)**((KS_law_slope_high_den-1)/2.) + +# density - sSFR plane +figure() +subplot(111) +hist2d(np.log10(gas_nH), np.log10(gas_sSFR), bins=50,range=[[-1.5,5],[-.5,2.5]]) +plot(np.log10(rhos),np.log10(sSFR)+np.log10(year_in_cgs)+9.,'k--',label='sSFR low density EAGLE') +plot(np.log10(rhoshigh),np.log10(sSFR_high_den)+np.log10(year_in_cgs)+9.,'k--',label='sSFR high density EAGLE') +xlabel("${\\rm Density}~n_{\\rm H}~[{\\rm cm^{-3}}]$", labelpad=2) +ylabel("${\\rm sSFR}~[{\\rm Gyr^{-1}}]$", labelpad=0) +xticks([-1, 0, 1, 2, 3, 4], ["$10^{-1}$", "$10^0$", "$10^1$", "$10^2$", "$10^3$", "$10^4$"]) +yticks([0, 1, 2], ["$10^0$", "$10^1$", "$10^2$"]) +xlim(-1.4, 4.9) +ylim(-0.5, 2.2) +savefig("density-sSFR.png", dpi=200) + +########################################################################3 + +# Select gas in a pillow box around the galaxy +mask = ( + (gas_pos[:, 0] > -15) + & (gas_pos[:, 0] < 15) + & (gas_pos[:, 1] > -15) + & (gas_pos[:, 1] < 15) + & (gas_pos[:, 2] < 1.0) + & (gas_pos[:, 2] > -1.0) +) +gas_pos = gas_pos[mask, :] +gas_SFR = gas_SFR[mask] +gas_nH = gas_nH[mask] +gas_rho = gas_rho[mask] +gas_T = gas_T[mask] +gas_mass = gas_mass[mask] +gas_Z = gas_Z[mask] +gas_hsml = gas_hsml[mask] + + +# Make a crude map of the gas +figure() +subplot(111) +scatter(gas_pos[:, 0], gas_pos[:, 1], s=0.1) +xlabel("${\\rm Pos}~x~[{\\rm kpc}]$", labelpad=0) +ylabel("${\\rm Pos}~y~[{\\rm kpc}]$", labelpad=-3) +xlim(-12, 12) +ylim(-12, 12) +savefig("face_on.png", dpi=200) + +figure() +subplot(111) +scatter(gas_pos[:, 0], gas_pos[:, 2], s=0.1) +xlabel("${\\rm Pos}~x~[{\\rm kpc}]$", labelpad=0) +ylabel("${\\rm Pos}~z~[{\\rm kpc}]$", labelpad=-3) +xlim(-12, 12) +ylim(-12, 12) +savefig("edge_on.png", dpi=200) + +# Now a SF map +rcParams.update({"figure.figsize": (4.15, 3.15)}) +figure() +subplot(111) +scatter(gas_pos[:, 0], gas_pos[:, 1], s=0.1, c=gas_SFR) +xlabel("${\\rm Pos}~x~[{\\rm kpc}]$", labelpad=0) +ylabel("${\\rm Pos}~y~[{\\rm kpc}]$", labelpad=-3) +colorbar() +xlim(-12, 12) +ylim(-12, 12) +savefig("SF_face_on.png", dpi=200) + + +########################################################################3 + +# Bin the data in kpc-size patches + +x_edges = np.linspace(-15, 15, 31) +y_edges = np.linspace(-15, 15, 31) + +map_mass, _, _, _ = stats.binned_statistic_2d( + gas_pos[:, 0], gas_pos[:, 1], gas_mass, statistic="sum", bins=(x_edges, y_edges) +) +map_SFR, _, _, _ = stats.binned_statistic_2d( + gas_pos[:, 0], gas_pos[:, 1], gas_SFR, statistic="sum", bins=(x_edges, y_edges) +) + +# Mass map +figure() +subplot(111) +pcolormesh(x_edges, y_edges, np.log10(map_mass)) +colorbar() +xlim(-12, 12) +ylim(-12, 12) +xlabel("${\\rm Pos}~x~[{\\rm kpc}]$", labelpad=0) +ylabel("${\\rm Pos}~y~[{\\rm kpc}]$", labelpad=-3) +savefig("Map_mass.png", dpi=200) + +# SF map +figure() +subplot(111) +pcolormesh(x_edges, y_edges, np.log10(map_SFR), vmax=-0.5, vmin=-4.5) +colorbar() +xlim(-12, 12) +ylim(-12, 12) +xlabel("${\\rm Pos}~x~[{\\rm kpc}]$", labelpad=0) +ylabel("${\\rm Pos}~y~[{\\rm kpc}]$", labelpad=-3) +savefig("Map_SFR.png", dpi=200) + +######################################################################### + +# Give a minimum SF surface density for the plots +map_SFR[map_SFR < 1e-6] = 1e-6 + +# Theoretical threshold (assumes all gas has the same Z) +KS_n_thresh = KS_thresh_norm * (gas_Z[0] / KS_thresh_Z0) ** KS_thresh_slope +if np.isfinite(KS_n_thresh) == False: + KS_n_thresh = KS_thresh_max_norm +KS_sigma_thresh = 29.0 * np.sqrt(KS_gas_fraction) * np.sqrt(KS_n_thresh) + +# Theoretical KS law +KS_sigma_mass = np.logspace(-1, 3, 100) +KS_sigma_SFR = KS_law_norm * KS_sigma_mass ** KS_law_slope + +# KS relation +rcParams.update({"figure.figsize": (3.15, 3.15), "figure.subplot.left": 0.18}) +figure() +subplot(111, xscale="log", yscale="log") +plot(KS_sigma_mass, KS_sigma_SFR, "k--", lw=0.6) +plot([KS_sigma_thresh, KS_sigma_thresh], [1e-8, 1e8], "k--", lw=0.6) +text( + KS_sigma_thresh * 0.95, + 2.2, + "$\\Sigma_{\\rm c} = %.2f~{\\rm M_\\odot\\cdot pc^{-2}}$" % KS_sigma_thresh, + va="top", + ha="right", + rotation=90, + fontsize=7, +) +text(16, 10 ** (-3.5), "$n_{\\rm H,c} = %.3f~{\\rm cm^{-3}}$" % KS_n_thresh, fontsize=7) +text( + 16, + 2e-6, + "${\\rm K\\textendash S~law}$:\n$\\Sigma_{\\rm SFR} = A \\times \\Sigma_g^n$\n$n=%.1f$\n$A=%.3f\\times10^{-4}~{\\rm M_\\odot / yr^{1} / kpc^{2}}$\n$f_{\\rm g} = %.1f$\n$\gamma_{\\rm eos} = %.3f$\n$Z=%1.4f$" + % ( + KS_law_slope, + KS_law_norm * 10 ** 4, + KS_gas_fraction, + EOS_gamma_effective, + EAGLE_Z, + ), + fontsize=7, +) +scatter(map_mass.flatten() / 1e6, map_SFR.flatten(), s=0.4) +xlim(0.3, 900) +ylim(3e-7, 3) +xlabel("$\\Sigma_g~[{\\rm M_\\odot\\cdot pc^{-2}}]$", labelpad=0) +ylabel( + "$\\Sigma_{\\rm SFR}~[{\\rm M_\\odot \\cdot yr^{-1} \\cdot kpc^{-2}}]$", labelpad=0 +) +savefig("KS_law.png", dpi=200) +close() diff --git a/examples/IsolatedGalaxy_starformation/run.sh b/examples/IsolatedGalaxy_starformation/run.sh new file mode 100755 index 0000000000000000000000000000000000000000..0b6aa8ea3b37ccb7e05fd33cbf414355b136db78 --- /dev/null +++ b/examples/IsolatedGalaxy_starformation/run.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +if [ ! -e fid.hdf5 ] +then + echo "Fetching initial conditions for the isolated galaxy example..." + ./getIC.sh +fi + +../swift --threads=32 --external-gravity --self-gravity --stars --star-formation --cooling --temperature --hydro isolated_galaxy.yml 2>&1 | tee output.log + +# Kennicutt-Schmidt law plot +python3 plotSolution.py + +# Plot that the random star formation matches the expected SFH +python3 SFH.py diff --git a/examples/SantaBarbara/rhoTPlot.py b/examples/SantaBarbara/rhoTPlot.py new file mode 100644 index 0000000000000000000000000000000000000000..c290268eaa548e188bb652104ea9e726ea88a267 --- /dev/null +++ b/examples/SantaBarbara/rhoTPlot.py @@ -0,0 +1,258 @@ +""" +Makes a rho-T plot. Uses the swiftsimio library. +""" + +import matplotlib.pyplot as plt +import numpy as np + +from swiftsimio import SWIFTDataset, SWIFTMetadata, SWIFTUnits + +from unyt import mh, cm, Gyr +from tqdm import tqdm +from matplotlib.colors import LogNorm +from matplotlib.animation import FuncAnimation + +# Constants; these could be put in the parameter file but are rarely changed. +density_bounds = [1e-8, 1e4] # in nh/cm^3 +temperature_bounds = [1e2, 1e8] # in K +bins = 128 + +# Plotting controls +cmap = "viridis" + + +def get_data(filename): + """ + Grabs the data (T in Kelvin and density in mh / cm^3). + """ + + data = SWIFTDataset(filename) + + data.gas.density.convert_to_units(mh / (cm ** 3)) + data.gas.temperature.convert_to_cgs() + + return data.gas.density, data.gas.temperature + + +def make_hist(filename, density_bounds, temperature_bounds, bins): + """ + Makes the histogram for filename with bounds as lower, higher + for the bins and "bins" the number of bins along each dimension. + + Also returns the edges for pcolormesh to use. + """ + + density_bins = np.logspace( + np.log10(density_bounds[0]), np.log10(density_bounds[1]), bins + ) + temperature_bins = np.logspace( + np.log10(temperature_bounds[0]), np.log10(temperature_bounds[1]), bins + ) + + H, density_edges, temperature_edges = np.histogram2d( + *get_data(filename), bins=[density_bins, temperature_bins] + ) + + return H.T, density_edges, temperature_edges + + +def setup_axes(): + """ + Creates the figure and axis object. + """ + fig, ax = plt.subplots(1, figsize=(6, 5), dpi=300) + + ax.set_xlabel("Density [$n_H$ cm$^{-3}$]") + ax.set_ylabel("Temperature [K]") + + ax.loglog() + + return fig, ax + + +def make_single_image(filename, density_bounds, temperature_bounds, bins): + """ + Makes a single image and saves it to rhoTPlot_{filename}.png. + + Filename should be given _without_ hdf5 extension. + """ + + fig, ax = setup_axes() + hist, d, T = make_hist( + "{:s}.hdf5".format(filename), density_bounds, temperature_bounds, bins + ) + + mappable = ax.pcolormesh(d, T, hist, cmap=cmap, norm=LogNorm()) + fig.colorbar(mappable, label="Number of particles", pad=0) + + fig.tight_layout() + + fig.savefig("rhoTPlot_{:s}.png".format(filename)) + + return + + +def make_movie(args, density_bounds, temperature_bounds, bins): + """ + Makes a movie and saves it to rhoTPlot_{stub}.mp4. + """ + + fig, ax = setup_axes() + + def grab_metadata(n): + filename = "{:s}_{:04d}.hdf5".format(args["stub"], n) + data = SWIFTMetadata(filename) + + return data + + def grab_data(n): + filename = "{:s}_{:04d}.hdf5".format(args["stub"], n) + + H, _, _ = make_hist(filename, density_bounds, temperature_bounds, bins) + + # Need to ravel because pcolormesh's set_array takes a 1D array. Might + # as well do it here, beacuse 1d arrays are easier to max() than 2d. + return H.ravel() + + histograms = [ + grab_data(n) + for n in tqdm( + range(args["initial"], args["final"] + 1), desc="Histogramming data" + ) + ] + + metadata = [ + grab_metadata(n) + for n in tqdm( + range(args["initial"], args["final"] + 1), desc="Grabbing metadata" + ) + ] + + units = SWIFTUnits("{:s}_{:04d}.hdf5".format(args["stub"], args["initial"])) + + # Need to get a reasonable norm so that we don't overshoot. + max_particles = max([x.max() for x in histograms]) + + norm = LogNorm(vmin=1, vmax=max_particles) + + # First, let's make the initial frame (we need this for our d, T values that we + # got rid of in grab_data. + hist, d, T = make_hist( + "{:s}_{:04d}.hdf5".format(args["stub"], args["initial"]), + density_bounds, + temperature_bounds, + bins, + ) + + mappable = ax.pcolormesh(d, T, hist, cmap=cmap, norm=norm) + fig.colorbar(mappable, label="Number of particles", pad=0) + + fig.tight_layout() + + # Once we've rearranged the figure with tight_layout(), we can start laing + # Down the metadata text. + + def format_metadata(metadata: SWIFTMetadata): + t = metadata.t * units.units["Unit time in cgs (U_t)"] + t.convert_to_units(Gyr) + + x = "$a$: {:2.2f}\n$z$: {:2.2f}\n$t$: {:2.2f}".format( + metadata.a, metadata.z, t + ) + + return x + + text = ax.text( + 0.025, + 0.975, + format_metadata(metadata[0]), + ha="left", + va="top", + transform=ax.transAxes, + ) + + ax.text( + 0.975, + 0.975, + metadata[0].code["Git Revision"].decode("utf-8"), + ha="right", + va="top", + transform=ax.transAxes, + ) + + def animate(data): + mappable.set_array(histograms[data]) + text.set_text(format_metadata(metadata[data])) + + return mappable + + animation = FuncAnimation( + fig, animate, range(len(histograms)), fargs=[], interval=1000 / 25 + ) + + animation.save("rhoTPlot_{:s}.mp4".format(args["stub"])) + + return + + +if __name__ == "__main__": + import argparse as ap + + parser = ap.ArgumentParser( + description=""" + Plotting script for making a rho-T plot. + Takes the filename handle, start, and (optionally) stop + snapshots. If stop is not given, png plot is produced for + that snapshot. If given, a movie is made. + """ + ) + + parser.add_argument( + "-i", + "--initial", + help="""Initial snapshot number. Default: 0.""", + default=0, + required=False, + type=int, + ) + + parser.add_argument( + "-f", + "--final", + help="""Final snapshot number. Default: 0.""", + default=0, + required=False, + type=int, + ) + + parser.add_argument( + "-s", + "--stub", + help="""Stub for the filename (e.g. santabarbara). This is + the first part of the filename for the snapshots, + not including the final underscore. Required.""", + type=str, + required=True, + ) + + args = vars(parser.parse_args()) + + if args["final"] <= args["initial"]: + # Run in single image mode. + filename = "{:s}_{:04d}".format(args["stub"], args["initial"]) + + make_single_image( + filename, + density_bounds=density_bounds, + temperature_bounds=temperature_bounds, + bins=bins, + ) + + else: + # Movie mode! + make_movie( + args, + density_bounds=density_bounds, + temperature_bounds=temperature_bounds, + bins=bins, + ) diff --git a/examples/SmallCosmoVolume/small_cosmo_volume.yml b/examples/SmallCosmoVolume/small_cosmo_volume.yml index a6ce1f28198a99422ea1c80178fc8000b66d777e..32846227c93e7d747fade2dc306b4c5c5246c14f 100644 --- a/examples/SmallCosmoVolume/small_cosmo_volume.yml +++ b/examples/SmallCosmoVolume/small_cosmo_volume.yml @@ -57,3 +57,15 @@ InitialConditions: cleanup_velocity_factors: 1 generate_gas_in_ics: 1 # Generate gas particles from the DM-only ICs cleanup_smoothing_lengths: 1 # Since we generate gas, make use of the (expensive) cleaning-up procedure. + +# Parameters for the EAGLE "equation of state" +EAGLEEntropyFloor: + Jeans_density_threshold_H_p_cm3: 0.1 # Physical density above which the EAGLE Jeans limiter entropy floor kicks in expressed in Hydrogen atoms per cm^3. + Jeans_over_density_threshold: 10. # Overdensity above which the EAGLE Jeans limiter entropy floor can kick in. + Jeans_temperature_norm_K: 8000 # Temperature of the EAGLE Jeans limiter entropy floor at the density threshold expressed in Kelvin. + Jeans_gamma_effective: 1.3333333 # Slope the of the EAGLE Jeans limiter entropy floor + Cool_density_threshold_H_p_cm3: 1e-5 # Physical density above which the EAGLE Cool limiter entropy floor kicks in expressed in Hydrogen atoms per cm^3. + Cool_over_density_threshold: 10. # Overdensity above which the EAGLE Cool limiter entropy floor can kick in. + Cool_temperature_norm_K: 8000 # Temperature of the EAGLE Cool limiter entropy floor at the density threshold expressed in Kelvin. + Cool_gamma_effective: 1. # Slope the of the EAGLE Cool limiter entropy floor + diff --git a/examples/main.c b/examples/main.c index 7e16e7096243736e49be7d773452ee8c0132ebef..1d46ee954b55c5965a6ab65dae5b5038e4c72394 100644 --- a/examples/main.c +++ b/examples/main.c @@ -90,11 +90,13 @@ int main(int argc, char *argv[]) { struct cooling_function_data cooling_func; struct cosmology cosmo; struct external_potential potential; + struct star_formation starform; struct pm_mesh mesh; struct gpart *gparts = NULL; struct gravity_props gravity_properties; struct hydro_props hydro_properties; struct stars_props stars_properties; + struct entropy_floor_properties entropy_floor; struct part *parts = NULL; struct phys_const prog_const; struct space s; @@ -692,6 +694,13 @@ int main(int argc, char *argv[]) { else bzero(&eos, sizeof(struct eos_parameters)); + /* Initialise the entropy floor */ + if (with_hydro) + entropy_floor_init(&entropy_floor, &prog_const, &us, &hydro_properties, + params); + else + bzero(&entropy_floor, sizeof(struct entropy_floor_properties)); + /* Initialise the stars properties */ if (with_stars) stars_props_init(&stars_properties, &prog_const, &us, params, @@ -883,6 +892,12 @@ int main(int argc, char *argv[]) { cooling_init(params, &us, &prog_const, &cooling_func); if (myrank == 0) cooling_print(&cooling_func); + /* Initialise the star formation law and its properties */ + if (with_star_formation) + starformation_init(params, &prog_const, &us, &hydro_properties, + &starform); + if (myrank == 0) starformation_print(&starform); + /* Initialise the chemistry */ bzero(&chemistry, sizeof(struct chemistry_global_data)); chemistry_init(params, &us, &prog_const, &chemistry); @@ -911,8 +926,9 @@ int main(int argc, char *argv[]) { if (myrank == 0) clocks_gettime(&tic); engine_init(&e, &s, params, N_total[0], N_total[1], N_total[2], engine_policies, talking, &reparttype, &us, &prog_const, &cosmo, - &hydro_properties, &gravity_properties, &stars_properties, - &mesh, &potential, &cooling_func, &chemistry); + &hydro_properties, &entropy_floor, &gravity_properties, + &stars_properties, &mesh, &potential, &cooling_func, &starform, + &chemistry); engine_config(0, &e, params, nr_nodes, myrank, nr_threads, with_aff, talking, restart_file); diff --git a/examples/parameter_example.yml b/examples/parameter_example.yml index ca0d47b5c2cc8c05168fa1bd16ac62e64d3068ce..dae922378b24614211e38cef22548cf0404ee196 100644 --- a/examples/parameter_example.yml +++ b/examples/parameter_example.yml @@ -253,6 +253,18 @@ SineWavePotential: timestep_limit: 1. # Time-step dimensionless pre-factor. growth_time: 0. # (Optional) Time for the potential to grow to its final size. +# Parameters related to entropy floors ---------------------------------------------- + +EAGLEEntropyFloor: + Jeans_density_threshold_H_p_cm3: 0.1 # Physical density above which the EAGLE Jeans limiter entropy floor kicks in expressed in Hydrogen atoms per cm^3. + Jeans_over_density_threshold: 10. # Overdensity above which the EAGLE Jeans limiter entropy floor can kick in. + Jeans_temperature_norm_K: 8000 # Temperature of the EAGLE Jeans limiter entropy floor at the density threshold expressed in Kelvin. + Jeans_gamma_effective: 1.3333333 # Slope the of the EAGLE Jeans limiter entropy floor + Cool_density_threshold_H_p_cm3: 1e-5 # Physical density above which the EAGLE Cool limiter entropy floor kicks in expressed in Hydrogen atoms per cm^3. + Cool_over_density_threshold: 10. # Overdensity above which the EAGLE Cool limiter entropy floor can kick in. + Cool_temperature_norm_K: 8000 # Temperature of the EAGLE Cool limiter entropy floor at the density threshold expressed in Kelvin. + Cool_gamma_effective: 1. # Slope the of the EAGLE Cool limiter entropy floor + # Parameters related to cooling function ---------------------------------------------- # Constant du/dt cooling function @@ -304,3 +316,24 @@ EAGLEChemistry: init_abundance_Magnesium: 0.000 # Inital fraction of particle mass in Magnesium init_abundance_Silicon: 0.000 # Inital fraction of particle mass in Silicon init_abundance_Iron: 0.000 # Inital fraction of particle mass in Iron + +# Parameters related to star formation models ----------------------------------------------- + +# EAGLE star formation model (Schaye and Dalla Vecchia 2008) +EAGLEStarFormation: + EOS_density_norm_H_p_cm3: 0.1 # Physical density used for the normalisation of the EOS assumed for the star-forming gas in Hydrogen atoms per cm^3. + EOS_temperature_norm_K: 8000 # Temperature om the polytropic EOS assumed for star-forming gas at the density normalisation in Kelvin. + EOS_gamma_effective: 1.3333333 # Slope the of the polytropic EOS assumed for the star-forming gas. + gas_fraction: 0.25 # (Optional) The gas fraction used internally by the model (Defaults to 1). + KS_normalisation: 1.515e-4 # The normalization of the Kennicutt-Schmidt law in Msun / kpc^2 / yr. + KS_exponent: 1.4 # The exponent of the Kennicutt-Schmidt law. + KS_min_over_density: 57.7 # The over-density above which star-formation is allowed. + KS_high_density_threshold_H_p_cm3: 1e3 # Hydrogen number density above which the Kennicut-Schmidt law changes slope in Hydrogen atoms per cm^3. + KS_high_density_exponent: 2.0 # Slope of the Kennicut-Schmidt law above the high-density threshold. + KS_max_density_threshold_H_p_cm3: 1e5 # (Optional) Density above which a gas particle gets automatically turned into a star in Hydrogen atoms per cm^3 (Defaults to FLT_MAX). + KS_temperature_margin_dex: 0.5 # (Optional) Logarithm base 10 of the maximal temperature difference above the EOS allowed to form stars (Defaults to FLT_MAX). + threshold_norm_H_p_cm3: 0.1 # Normalisation of the metal-dependant density threshold for star formation in Hydrogen atoms per cm^3. + threshold_Z0: 0.002 # Reference metallicity (metal mass fraction) for the metal-dependant threshold for star formation. + threshold_slope: -0.64 # Slope of the metal-dependant star formation threshold + threshold_max_density_H_p_cm3: 10.0 # Maximal density of the metal-dependant density threshold for star formation in Hydrogen atoms per cm^3. + diff --git a/src/Makefile.am b/src/Makefile.am index f1c20865af9ade70257abd6e683895f363c55813..5a356ba6707eee0664b9cb7817c8f2195d5512b2 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -44,12 +44,14 @@ include_HEADERS = space.h runner.h queue.h task.h lock.h cell.h part.h const.h \ common_io.h single_io.h multipole.h map.h tools.h partition.h partition_fixed_costs.h \ clocks.h parser.h physical_constants.h physical_constants_cgs.h potential.h version.h \ hydro_properties.h riemann.h threadpool.h cooling_io.h cooling.h cooling_struct.h \ - statistics.h memswap.h cache.h runner_doiact_vec.h profiler.h \ + statistics.h memswap.h cache.h runner_doiact_vec.h profiler.h entropy_floor.h \ dump.h logger.h active.h timeline.h xmf.h gravity_properties.h gravity_derivatives.h \ gravity_softened_derivatives.h vector_power.h collectgroup.h hydro_space.h sort_part.h \ chemistry.h chemistry_io.h chemistry_struct.h cosmology.h restart.h space_getsid.h utilities.h \ mesh_gravity.h cbrt.h exp10.h velociraptor_interface.h swift_velociraptor_part.h outputlist.h \ - logger_io.h tracers_io.h tracers.h tracers_struct.h velociraptor_struct.h velociraptor_io.h + logger_io.h tracers_io.h tracers.h tracers_struct.h star_formation_io.h \ + star_formation_struct.h star_formation.h velociraptor_struct.h velociraptor_io.h \ + random.h # source files for EAGLE cooling EAGLE_COOLING_SOURCES = @@ -63,7 +65,7 @@ AM_SOURCES = space.c runner.c queue.c task.c cell.c engine.c engine_maketasks.c proxy.c parallel_io.c units.c common_io.c single_io.c multipole.c version.c map.c \ kernel_hydro.c tools.c part.c partition.c clocks.c parser.c \ physical_constants.c potential.c hydro_properties.c \ - threadpool.c cooling.c \ + threadpool.c cooling.c star_formation.c \ statistics.c runner_doiact_vec.c profiler.c dump.c logger.c \ part_type.c xmf.c gravity_properties.c gravity.c \ collectgroup.c hydro_space.c equation_of_state.c \ @@ -135,9 +137,15 @@ nobase_noinst_HEADERS = align.h approx_math.h atomic.h barrier.h cycle.h error.h stars.h stars_io.h \ stars/Default/stars.h stars/Default/stars_iact.h stars/Default/stars_io.h \ stars/Default/stars_debug.h stars/Default/stars_part.h \ + stars/EAGLE/stars.h stars/EAGLE/stars_iact.h stars/EAGLE/stars_io.h \ + stars/EAGLE/stars_debug.h stars/EAGLE/stars_part.h \ potential/none/potential.h potential/point_mass/potential.h \ potential/isothermal/potential.h potential/disc_patch/potential.h \ potential/sine_wave/potential.h \ + star_formation/none/star_formation.h star_formation/none/star_formation_struct.h \ + star_formation/none/star_formation_io.h \ + star_formation/EAGLE/star_formation.h star_formation/EAGLE/star_formation_struct.h \ + star_formation/EAGLE/star_formation_io.h \ cooling/none/cooling.h cooling/none/cooling_struct.h \ cooling/none/cooling_io.h \ cooling/Compton/cooling.h cooling/Compton/cooling_struct.h \ @@ -162,10 +170,12 @@ nobase_noinst_HEADERS = align.h approx_math.h atomic.h barrier.h cycle.h error.h chemistry/EAGLE/chemistry_io.h \ chemistry/EAGLE/chemistry_struct.h\ chemistry/EAGLE/chemistry_iact.h \ + entropy_floor/none/entropy_floor.h \ + entropy_floor/EAGLE/entropy_floor.h \ tracers/none/tracers.h tracers/none/tracers_struct.h \ tracers/none/tracers_io.h \ tracers/EAGLE/tracers.h tracers/EAGLE/tracers_struct.h \ - tracers/EAGLE/tracers_io.h + tracers/EAGLE/tracers_io.h # Sources and flags for regular library diff --git a/src/chemistry/EAGLE/chemistry.h b/src/chemistry/EAGLE/chemistry.h index f095c8bcef65ff67c134baa03181f043b0e533c5..7cb61d11fc5578da4cf545448c7fdc2e6b0b12ed 100644 --- a/src/chemistry/EAGLE/chemistry.h +++ b/src/chemistry/EAGLE/chemistry.h @@ -92,7 +92,7 @@ __attribute__((always_inline)) INLINE static void chemistry_end_density( const float h = p->h; const float h_inv = 1.0f / h; /* 1/h */ const float factor = pow_dimension(h_inv) / p->rho; /* 1 / h^d * rho */ - const float m = p->mass; + const float m = hydro_get_mass(p); struct chemistry_part_data* cpd = &p->chemistry_data; diff --git a/src/chemistry/EAGLE/chemistry_iact.h b/src/chemistry/EAGLE/chemistry_iact.h index 07891b28bb0f41688886da7ddedf147f6c16a6ba..573291637d66e39a973e662edec084d3a4687050 100644 --- a/src/chemistry/EAGLE/chemistry_iact.h +++ b/src/chemistry/EAGLE/chemistry_iact.h @@ -48,8 +48,8 @@ __attribute__((always_inline)) INLINE static void runner_iact_chemistry( float wj; /* Get the masses. */ - const float mi = pi->mass; - const float mj = pj->mass; + const float mi = hydro_get_mass(pi); + const float mj = hydro_get_mass(pj); /* Get r */ const float r = sqrtf(r2); @@ -106,7 +106,7 @@ __attribute__((always_inline)) INLINE static void runner_iact_nonsym_chemistry( float wi; /* Get the masses. */ - const float mj = pj->mass; + const float mj = hydro_get_mass(pj); /* Get r */ const float r = sqrtf(r2); diff --git a/src/chemistry/EAGLE/chemistry_io.h b/src/chemistry/EAGLE/chemistry_io.h index de33324fa34cc288ab1689275b004d2cbb1ebbb7..62de85d47329a588d658cc61db72510337988638 100644 --- a/src/chemistry/EAGLE/chemistry_io.h +++ b/src/chemistry/EAGLE/chemistry_io.h @@ -106,6 +106,66 @@ INLINE static int chemistry_write_particles(const struct part* parts, return 12; } +/** + * @brief Specifies which star particle fields to write to a dataset + * + * @param sparts The star particle array. + * @param list The list of i/o properties to write. + * + * @return Returns the number of fields to write. + */ +INLINE static int chemistry_write_sparticles(const struct spart* sparts, + struct io_props* list) { + + /* List what we want to write */ + list[0] = io_make_output_field("ElementAbundance", FLOAT, + chemistry_element_count, UNIT_CONV_NO_UNITS, + sparts, chemistry_data.metal_mass_fraction); + + list[1] = io_make_output_field( + "SmoothedElementAbundance", FLOAT, chemistry_element_count, + UNIT_CONV_NO_UNITS, sparts, chemistry_data.smoothed_metal_mass_fraction); + + list[2] = + io_make_output_field("Metallicity", FLOAT, 1, UNIT_CONV_NO_UNITS, sparts, + chemistry_data.metal_mass_fraction_total); + + list[3] = io_make_output_field( + "SmoothedMetallicity", FLOAT, 1, UNIT_CONV_NO_UNITS, sparts, + chemistry_data.smoothed_metal_mass_fraction_total); + + list[4] = io_make_output_field("TotalMassFromSNIa", FLOAT, 1, UNIT_CONV_MASS, + sparts, chemistry_data.mass_from_SNIa); + + list[5] = io_make_output_field("MetalMassFracFromSNIa", FLOAT, 1, + UNIT_CONV_NO_UNITS, sparts, + chemistry_data.metal_mass_fraction_from_SNIa); + + list[6] = io_make_output_field("TotalMassFromAGB", FLOAT, 1, UNIT_CONV_MASS, + sparts, chemistry_data.mass_from_AGB); + + list[7] = + io_make_output_field("MetalMassFracFromAGB", FLOAT, 1, UNIT_CONV_NO_UNITS, + sparts, chemistry_data.metal_mass_fraction_from_AGB); + + list[8] = io_make_output_field("TotalMassFromSNII", FLOAT, 1, UNIT_CONV_MASS, + sparts, chemistry_data.mass_from_SNII); + + list[9] = io_make_output_field("MetalMassFracFromSNII", FLOAT, 1, + UNIT_CONV_NO_UNITS, sparts, + chemistry_data.metal_mass_fraction_from_SNII); + + list[10] = + io_make_output_field("IronMassFracFromSNIa", FLOAT, 1, UNIT_CONV_NO_UNITS, + sparts, chemistry_data.iron_mass_fraction_from_SNIa); + + list[11] = io_make_output_field( + "SmoothedIronMassFracFromSNIa", FLOAT, 1, UNIT_CONV_NO_UNITS, sparts, + chemistry_data.smoothed_iron_mass_fraction_from_SNIa); + + return 12; +} + #ifdef HAVE_HDF5 /** diff --git a/src/chemistry/GEAR/chemistry_io.h b/src/chemistry/GEAR/chemistry_io.h index 2a0847bebfb8c1734f21bda2f6ad55b354a7aec9..b29f7db65d3ab7dce4b0dcafed06c97a9e621bfe 100644 --- a/src/chemistry/GEAR/chemistry_io.h +++ b/src/chemistry/GEAR/chemistry_io.h @@ -87,6 +87,32 @@ INLINE static int chemistry_write_particles(const struct part* parts, return 3; } +/** + * @brief Specifies which sparticle fields to write to a dataset + * + * @param sparts The sparticle array. + * @param list The list of i/o properties to write. + * + * @return Returns the number of fields to write. + */ +INLINE static int chemistry_write_sparticles(const struct spart* sparts, + struct io_props* list) { + + /* List what we want to write */ + list[0] = io_make_output_field( + "SmoothedElementAbundance", FLOAT, chemistry_element_count, + UNIT_CONV_NO_UNITS, sparts, chemistry_data.smoothed_metal_mass_fraction); + + list[1] = io_make_output_field("Z", FLOAT, 1, UNIT_CONV_NO_UNITS, sparts, + chemistry_data.Z); + + list[2] = io_make_output_field("ElementAbundance", FLOAT, + chemistry_element_count, UNIT_CONV_NO_UNITS, + sparts, chemistry_data.metal_mass_fraction); + + return 3; +} + #ifdef HAVE_HDF5 /** diff --git a/src/chemistry/none/chemistry_io.h b/src/chemistry/none/chemistry_io.h index ef7e0d8d87dfeab5978f0e86bbf6279f7901d10a..c6e5b7b769cec667fee8c3fc674f3b4aa35929c1 100644 --- a/src/chemistry/none/chemistry_io.h +++ b/src/chemistry/none/chemistry_io.h @@ -55,10 +55,27 @@ INLINE static int chemistry_write_particles(const struct part* parts, return 0; } +/** + * @brief Specifies which sparticle fields to write to a dataset + * + * @param sparts The sparticle array. + * @param list The list of i/o properties to write. + * + * @return Returns the number of fields to write. + */ +INLINE static int chemistry_write_sparticles(const struct spart* sparts, + struct io_props* list) { + + /* update list according to hydro_io */ + + /* Return the number of fields to write */ + return 0; +} + #ifdef HAVE_HDF5 /** - * @brief Writes the current model of SPH to the file + * @brief Writes the current model of chemistry to the file * @param h_grp The HDF5 group in which to write */ INLINE static void chemistry_write_flavour(hid_t h_grp) { diff --git a/src/cooling/EAGLE/cooling.c b/src/cooling/EAGLE/cooling.c index 49d2186aa552cd60d914fa2b6e9106b70ff54ffc..d657beeaa4f36d1efd3c5cc407f8c1d689037693 100644 --- a/src/cooling/EAGLE/cooling.c +++ b/src/cooling/EAGLE/cooling.c @@ -769,7 +769,7 @@ void cooling_init_backend(struct swift_params *parameter_file, cooling->He_reion_z_sigma = parser_get_param_float(parameter_file, "EAGLECooling:He_reion_z_sigma"); cooling->He_reion_heat_cgs = - parser_get_param_float(parameter_file, "EAGLECooling:He_reion_ev_p_H"); + parser_get_param_float(parameter_file, "EAGLECooling:He_reion_eV_p_H"); /* Optional parameters to correct the abundances */ cooling->Ca_over_Si_ratio_in_solar = parser_get_opt_param_float( diff --git a/src/engine.c b/src/engine.c index eb936f61b296c94d933855de874cc3949dce89bc..f32bc0dbe7e2346f9d15984575f1128a0b589d21 100644 --- a/src/engine.c +++ b/src/engine.c @@ -62,6 +62,7 @@ #include "cosmology.h" #include "cycle.h" #include "debug.h" +#include "entropy_floor.h" #include "equation_of_state.h" #include "error.h" #include "gravity.h" @@ -83,6 +84,7 @@ #include "serial_io.h" #include "single_io.h" #include "sort_part.h" +#include "star_formation.h" #include "stars_io.h" #include "statistics.h" #include "timers.h" @@ -2681,6 +2683,7 @@ void engine_skip_force_and_kick(struct engine *e) { t->type == task_type_end_force || t->type == task_type_grav_long_range || t->type == task_type_grav_mm || t->type == task_type_grav_down || t->type == task_type_cooling || + t->type == task_type_star_formation || t->type == task_type_extra_ghost || t->subtype == task_subtype_gradient) t->skip = 1; } @@ -4071,11 +4074,13 @@ void engine_unpin(void) { * @param physical_constants The #phys_const used for this run. * @param cosmo The #cosmology used for this run. * @param hydro The #hydro_props used for this run. + * @param entropy_floor The #entropy_floor_properties for this run. * @param gravity The #gravity_props used for this run. * @param stars The #stars_props used for this run. * @param mesh The #pm_mesh used for the long-range periodic forces. * @param potential The properties of the external potential. * @param cooling_func The properties of the cooling function. + * @param starform The #star_formation model of this run. * @param chemistry The chemistry information. */ void engine_init(struct engine *e, struct space *s, struct swift_params *params, @@ -4084,10 +4089,12 @@ void engine_init(struct engine *e, struct space *s, struct swift_params *params, const struct unit_system *internal_units, const struct phys_const *physical_constants, struct cosmology *cosmo, const struct hydro_props *hydro, + const struct entropy_floor_properties *entropy_floor, struct gravity_props *gravity, const struct stars_props *stars, struct pm_mesh *mesh, const struct external_potential *potential, struct cooling_function_data *cooling_func, + const struct star_formation *starform, const struct chemistry_global_data *chemistry) { /* Clean-up everything */ @@ -4148,11 +4155,13 @@ void engine_init(struct engine *e, struct space *s, struct swift_params *params, e->physical_constants = physical_constants; e->cosmology = cosmo; e->hydro_properties = hydro; + e->entropy_floor = entropy_floor; e->gravity_properties = gravity; e->stars_properties = stars; e->mesh = mesh; e->external_potential = potential; e->cooling_func = cooling_func; + e->star_formation = starform; e->chemistry = chemistry; e->parameter_file = params; #ifdef WITH_MPI @@ -4469,8 +4478,10 @@ void engine_config(int restart, struct engine *e, struct swift_params *params, engine_print_policy(e); /* Print information about the hydro scheme */ - if (e->policy & engine_policy_hydro) + if (e->policy & engine_policy_hydro) { if (e->nodeID == 0) hydro_props_print(e->hydro_properties); + if (e->nodeID == 0) entropy_floor_print(e->entropy_floor); + } /* Print information about the gravity scheme */ if (e->policy & engine_policy_self_gravity) @@ -5264,11 +5275,13 @@ void engine_struct_dump(struct engine *e, FILE *stream) { phys_const_struct_dump(e->physical_constants, stream); hydro_props_struct_dump(e->hydro_properties, stream); + entropy_floor_struct_dump(e->entropy_floor, stream); gravity_props_struct_dump(e->gravity_properties, stream); stars_props_struct_dump(e->stars_properties, stream); pm_mesh_struct_dump(e->mesh, stream); potential_struct_dump(e->external_potential, stream); cooling_struct_dump(e->cooling_func, stream); + starformation_struct_dump(e->star_formation, stream); chemistry_struct_dump(e->chemistry, stream); parser_struct_dump(e->parameter_file, stream); if (e->output_list_snapshots) @@ -5335,6 +5348,12 @@ void engine_struct_restore(struct engine *e, FILE *stream) { hydro_props_struct_restore(hydro_properties, stream); e->hydro_properties = hydro_properties; + struct entropy_floor_properties *entropy_floor = + (struct entropy_floor_properties *)malloc( + sizeof(struct entropy_floor_properties)); + entropy_floor_struct_restore(entropy_floor, stream); + e->entropy_floor = entropy_floor; + struct gravity_props *gravity_properties = (struct gravity_props *)malloc(sizeof(struct gravity_props)); gravity_props_struct_restore(gravity_properties, stream); @@ -5360,6 +5379,11 @@ void engine_struct_restore(struct engine *e, FILE *stream) { cooling_struct_restore(cooling_func, stream, e->cosmology); e->cooling_func = cooling_func; + struct star_formation *star_formation = + (struct star_formation *)malloc(sizeof(struct star_formation)); + starformation_struct_restore(star_formation, stream); + e->star_formation = star_formation; + struct chemistry_global_data *chemistry = (struct chemistry_global_data *)malloc( sizeof(struct chemistry_global_data)); diff --git a/src/engine.h b/src/engine.h index 13754097e9e3460eaa7d20a4dfdb6f7dd18bb9bc..5a9959a6a024b7e0d2ae85f63ce87302ebe9e0a7 100644 --- a/src/engine.h +++ b/src/engine.h @@ -345,6 +345,9 @@ struct engine { /* Properties of the hydro scheme */ const struct hydro_props *hydro_properties; + /* Properties of the entropy floor */ + const struct entropy_floor_properties *entropy_floor; + /* Properties of the star model */ const struct stars_props *stars_properties; @@ -360,6 +363,9 @@ struct engine { /* Properties of the cooling scheme */ struct cooling_function_data *cooling_func; + /* Properties of the starformation law */ + const struct star_formation *star_formation; + /* Properties of the chemistry model */ const struct chemistry_global_data *chemistry; @@ -414,10 +420,12 @@ void engine_init(struct engine *e, struct space *s, struct swift_params *params, const struct unit_system *internal_units, const struct phys_const *physical_constants, struct cosmology *cosmo, const struct hydro_props *hydro, + const struct entropy_floor_properties *entropy_floor, struct gravity_props *gravity, const struct stars_props *stars, struct pm_mesh *mesh, const struct external_potential *potential, struct cooling_function_data *cooling_func, + const struct star_formation *starform, const struct chemistry_global_data *chemistry); void engine_config(int restart, struct engine *e, struct swift_params *params, int nr_nodes, int nodeID, int nr_threads, int with_aff, diff --git a/src/engine_maketasks.c b/src/engine_maketasks.c index 2175595cd149d9d5da5a3aa5f5341ff181fd58d6..d1d3be6c12ee47e22da42b41456c822394ed2ba4 100644 --- a/src/engine_maketasks.c +++ b/src/engine_maketasks.c @@ -1327,8 +1327,10 @@ void engine_link_gravity_tasks(struct engine *e) { * @param density The density task to link. * @param gradient The gradient task to link. * @param force The force task to link. + * @param limiter The limiter task to link. * @param c The cell. * @param with_cooling Do we have a cooling task ? + * @param with_limiter Do we have a time-step limiter ? */ static inline void engine_make_hydro_loops_dependencies( struct scheduler *sched, struct task *density, struct task *gradient, diff --git a/src/entropy_floor.h b/src/entropy_floor.h new file mode 100644 index 0000000000000000000000000000000000000000..e65d55b2ab51047748403ee690edd7cb361eda1d --- /dev/null +++ b/src/entropy_floor.h @@ -0,0 +1,37 @@ +/******************************************************************************* + * This file is part of SWIFT. + * Copyright (c) 2019 Matthieu Schaller (schaller@strw.leidenuniv.nl) + * + * 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_ENTROPY_FLOOR_H +#define SWIFT_ENTROPY_FLOOR_H + +/** + * @file src/entropy_floor.h + * @brief Branches between the different entropy floor models + */ + +/* Config parameters. */ +#include "../config.h" + +/* Import the right entropy floor definition */ +#if defined(ENTROPY_FLOOR_NONE) +#include "./entropy_floor/none/entropy_floor.h" +#elif defined(ENTROPY_FLOOR_EAGLE) +#include "./entropy_floor/EAGLE/entropy_floor.h" +#endif + +#endif /* SWIFT_ENTROPY_FLOOR_H */ diff --git a/src/entropy_floor/EAGLE/entropy_floor.h b/src/entropy_floor/EAGLE/entropy_floor.h new file mode 100644 index 0000000000000000000000000000000000000000..8ea1e8631c4a9c5c14d7c0221a02f7178a3209d5 --- /dev/null +++ b/src/entropy_floor/EAGLE/entropy_floor.h @@ -0,0 +1,267 @@ +/******************************************************************************* + * This file is part of SWIFT. + * Copyright (c) 2019 Matthieu Schaller (schaller@strw.leidenuniv.nl) + * + * 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_ENTROPY_FLOOR_EAGLE_H +#define SWIFT_ENTROPY_FLOOR_EAGLE_H + +#include "adiabatic_index.h" +#include "cosmology.h" +#include "hydro_properties.h" +#include "parser.h" +#include "units.h" + +/** + * @file src/entropy_floor/EAGLE/entropy_floor.h + * @brief Entropy floor used in the EAGLE model + */ + +/** + * @brief Properties of the entropy floor in the EAGLE model. + */ +struct entropy_floor_properties { + + /*! Density threshold for the Jeans floor in Hydrogen atoms per cubic cm */ + float Jeans_density_threshold_H_p_cm3; + + /*! Density threshold for the Jeans floor in internal units */ + float Jeans_density_threshold; + + /*! Inverse of the density threshold for the Jeans floor in internal units */ + float Jeans_density_threshold_inv; + + /*! Over-density threshold for the Jeans floor */ + float Jeans_over_density_threshold; + + /*! Slope of the Jeans floor power-law */ + float Jeans_gamma_effective; + + /*! Temperature of the Jeans floor at the density threshold in Kelvin */ + float Jeans_temperature_norm_K; + + /*! Temperature of the Jeans floor at the density thresh. in internal units */ + float Jeans_temperature_norm; + + /*! Pressure of the Jeans floor at the density thresh. in internal units */ + float Jeans_pressure_norm; + + /*! Density threshold for the Cool floor in Hydrogen atoms per cubic cm */ + float Cool_density_threshold_H_p_cm3; + + /*! Density threshold for the Cool floor in internal units */ + float Cool_density_threshold; + + /*! Inverse of the density threshold for the Cool floor in internal units */ + float Cool_density_threshold_inv; + + /*! Over-density threshold for the Cool floor */ + float Cool_over_density_threshold; + + /*! Slope of the Cool floor power-law */ + float Cool_gamma_effective; + + /*! Temperature of the Cool floor at the density threshold in Kelvin */ + float Cool_temperature_norm_K; + + /*! Temperature of the Cool floor at the density thresh. in internal units */ + float Cool_temperature_norm; + + /*! Pressure of the Cool floor at the density thresh. in internal units */ + float Cool_pressure_norm; +}; + +/** + * @brief Compute the entropy floor of a given #part. + * + * Note that the particle is not updated!! + * + * @param p The #part. + * @param cosmo The cosmological model. + * @param props The properties of the entropy floor. + */ +static INLINE float entropy_floor( + const struct part *p, const struct cosmology *cosmo, + const struct entropy_floor_properties *props) { + + /* Physical density in internal units */ + const float rho = hydro_get_physical_density(p, cosmo); + + /* Critical density at this redshift. + * Recall that this is 0 in a non-cosmological run */ + const float rho_crit = cosmo->critical_density; + + float pressure = 0.; + + /* Are we in the regime of the Jeans equation of state? */ + if ((rho >= rho_crit * props->Jeans_over_density_threshold) && + (rho >= props->Jeans_density_threshold)) { + + const float pressure_Jeans = props->Jeans_pressure_norm * + powf(rho * props->Jeans_density_threshold_inv, + props->Jeans_gamma_effective); + + pressure = max(pressure, pressure_Jeans); + } + + /* Are we in the regime of the Cool equation of state? */ + if ((rho >= rho_crit * props->Cool_over_density_threshold) && + (rho >= props->Cool_density_threshold)) { + + const float pressure_Cool = props->Cool_pressure_norm * + powf(rho * props->Cool_density_threshold_inv, + props->Cool_gamma_effective); + + pressure = max(pressure, pressure_Cool); + } + + /* Convert to an entropy. + * (Recall that the entropy is the same in co-moving and phycial frames) */ + return gas_entropy_from_pressure(rho, pressure); +} + +/** + * @brief Initialise the entropy floor by reading the parameters and converting + * to internal units. + * + * @param params The YAML parameter file. + * @param us The system of units used internally. + * @param phys_const The physical constants. + * @param hydro_props The propoerties of the hydro scheme. + * @param props The entropy floor properties to fill. + */ +static INLINE void entropy_floor_init(struct entropy_floor_properties *props, + const struct phys_const *phys_const, + const struct unit_system *us, + const struct hydro_props *hydro_props, + struct swift_params *params) { + + /* Read the parameters in the units they are set */ + props->Jeans_density_threshold_H_p_cm3 = parser_get_param_float( + params, "EAGLEEntropyFloor:Jeans_density_threshold_H_p_cm3"); + props->Jeans_over_density_threshold = parser_get_param_float( + params, "EAGLEEntropyFloor:Jeans_over_density_threshold"); + props->Jeans_temperature_norm_K = parser_get_param_float( + params, "EAGLEEntropyFloor:Jeans_temperature_norm_K"); + props->Jeans_gamma_effective = + parser_get_param_float(params, "EAGLEEntropyFloor:Jeans_gamma_effective"); + + props->Cool_density_threshold_H_p_cm3 = parser_get_param_float( + params, "EAGLEEntropyFloor:Cool_density_threshold_H_p_cm3"); + props->Cool_over_density_threshold = parser_get_param_float( + params, "EAGLEEntropyFloor:Cool_over_density_threshold"); + props->Cool_temperature_norm_K = parser_get_param_float( + params, "EAGLEEntropyFloor:Cool_temperature_norm_K"); + props->Cool_gamma_effective = + parser_get_param_float(params, "EAGLEEntropyFloor:Cool_gamma_effective"); + + /* Initial Hydrogen abundance (mass fraction) */ + const double X_H = hydro_props->hydrogen_mass_fraction; + + /* Now convert to internal units */ + props->Jeans_temperature_norm = + props->Jeans_temperature_norm_K / + units_cgs_conversion_factor(us, UNIT_CONV_TEMPERATURE); + props->Jeans_density_threshold = + props->Jeans_density_threshold_H_p_cm3 / + units_cgs_conversion_factor(us, UNIT_CONV_NUMBER_DENSITY) * + phys_const->const_proton_mass / X_H; + + props->Cool_temperature_norm = + props->Cool_temperature_norm_K / + units_cgs_conversion_factor(us, UNIT_CONV_TEMPERATURE); + props->Cool_density_threshold = + props->Cool_density_threshold_H_p_cm3 / + units_cgs_conversion_factor(us, UNIT_CONV_NUMBER_DENSITY) * + phys_const->const_proton_mass / X_H; + + /* We assume neutral gas */ + const float mean_molecular_weight = hydro_props->mu_neutral; + + /* Get the common terms */ + props->Jeans_density_threshold_inv = 1.f / props->Jeans_density_threshold; + props->Cool_density_threshold_inv = 1.f / props->Cool_density_threshold; + + /* P_norm = (k_B * T) / (m_p * mu) * rho_threshold */ + props->Jeans_pressure_norm = + (phys_const->const_boltzmann_k * props->Jeans_temperature_norm) / + (phys_const->const_proton_mass * mean_molecular_weight) * + props->Jeans_density_threshold; + + props->Cool_pressure_norm = + (phys_const->const_boltzmann_k * props->Cool_temperature_norm) / + (phys_const->const_proton_mass * mean_molecular_weight) * + props->Cool_density_threshold; +} + +/** + * @brief Print the properties of the entropy floor to stdout. + * + * @param props The entropy floor properties. + */ +static INLINE void entropy_floor_print( + const struct entropy_floor_properties *props) { + + message("Entropy floor is 'EAGLE' with:"); + message("Jeans limiter with slope n=%.3f at rho=%e (%e H/cm^3) and T=%.1f K", + props->Jeans_gamma_effective, props->Jeans_density_threshold, + props->Jeans_density_threshold_H_p_cm3, + props->Jeans_temperature_norm); + message(" Cool limiter with slope n=%.3f at rho=%e (%e H/cm^3) and T=%.1f K", + props->Cool_gamma_effective, props->Cool_density_threshold, + props->Cool_density_threshold_H_p_cm3, props->Cool_temperature_norm); +} + +#ifdef HAVE_HDF5 + +/** + * @brief Writes the current model of entropy floor to the file + * @param h_grp The HDF5 group in which to write + */ +INLINE static void entropy_floor_write_flavour(hid_t h_grp) { + + io_write_attribute_s(h_grp, "Entropy floor", "EAGLE"); +} +#endif + +/** + * @brief Write an entropy floor struct to the given FILE as a stream of bytes. + * + * @param props the struct + * @param stream the file stream + */ +static INLINE void entropy_floor_struct_dump( + const struct entropy_floor_properties *props, FILE *stream) { + + restart_write_blocks((void *)props, sizeof(struct entropy_floor_properties), + 1, stream, "entropy floor", "entropy floor properties"); +} + +/** + * @brief Restore a entropy floor struct from the given FILE as a stream of + * bytes. + * + * @param props the struct + * @param stream the file stream + */ +static INLINE void entropy_floor_struct_restore( + struct entropy_floor_properties *props, FILE *stream) { + + restart_read_blocks((void *)props, sizeof(struct entropy_floor_properties), 1, + stream, NULL, "entropy floor properties"); +} + +#endif /* SWIFT_ENTROPY_FLOOR_EAGLE_H */ diff --git a/src/entropy_floor/none/entropy_floor.h b/src/entropy_floor/none/entropy_floor.h new file mode 100644 index 0000000000000000000000000000000000000000..1ffae096f84f77b4a49083cb60b28bc2530a5a98 --- /dev/null +++ b/src/entropy_floor/none/entropy_floor.h @@ -0,0 +1,114 @@ +/******************************************************************************* + * This file is part of SWIFT. + * Copyright (c) 2019 Matthieu Schaller (schaller@strw.leidenuniv.nl) + * + * 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_ENTROPY_FLOOR_NONE_H +#define SWIFT_ENTROPY_FLOOR_NONE_H + +/** + * @file src/entropy_floor/none/entropy_floor.h + * @brief Empty functions used for simulations without entropy + * floors. + */ + +/** + * @brief Properties of the entropy floor. + * + * Nothing here. + */ +struct entropy_floor_properties {}; + +/** + * @brief Compute the entropy floor of a given #part. + * + * Simply return 0 (no floor). + * + * @param p The #part. + * @param cosmo The cosmological model. + * @param props The properties of the entropy floor. + */ +static INLINE float entropy_floor( + const struct part *p, const struct cosmology *cosmo, + const struct entropy_floor_properties *props) { + + return 0.f; +} + +/** + * @brief Initialise the entropy floor by reading the parameters and converting + * to internal units. + * + * Nothing to do here. + * + * @param params The YAML parameter file. + * @param us The system of units used internally. + * @param phys_cont The physical constants. + * @param props The entropy floor properties to fill. + */ +static INLINE void entropy_floor_init(struct entropy_floor_properties *props, + const struct phys_const *phys_const, + const struct unit_system *us, + const struct hydro_props *hydro_props, + struct swift_params *params) {} + +/** + * @brief Print the properties of the entropy floor to stdout. + * + * @param props The entropy floor properties. + */ +static INLINE void entropy_floor_print( + const struct entropy_floor_properties *props) { + + message("Entropy floor is 'no entropy floor'."); +} + +#ifdef HAVE_HDF5 + +/** + * @brief Writes the current model of entropy floor to the file + * @param h_grp The HDF5 group in which to write + */ +INLINE static void entropy_floor_write_flavour(hid_t h_grp) { + + io_write_attribute_s(h_grp, "Entropy floor", "None"); +} +#endif + +/** + * @brief Write an entropy floor struct to the given FILE as a stream of bytes. + * + * Nothing to do here. + * + * @param props the struct + * @param stream the file stream + */ +static INLINE void entropy_floor_struct_dump( + const struct entropy_floor_properties *props, FILE *stream) {} + +/** + * @brief Restore a entropy floor struct from the given FILE as a stream of + * bytes. + * + * Nothing to do here. + * + * @param props the struct + * @param stream the file stream + */ +static INLINE void entropy_floor_struct_restore( + struct entropy_floor_properties *props, FILE *stream) {} + +#endif /* SWIFT_ENTROPY_FLOOR_NONE_H */ diff --git a/src/hydro/AnarchyPU/hydro.h b/src/hydro/AnarchyPU/hydro.h index 27501944c8afd6cd316717158057086a8f6ffd4e..9bb53f290acb16b4f9efc44e430a78a6d1f5c5ff 100644 --- a/src/hydro/AnarchyPU/hydro.h +++ b/src/hydro/AnarchyPU/hydro.h @@ -362,6 +362,23 @@ hydro_set_physical_internal_energy_dt(struct part *restrict p, p->u_dt = du_dt / cosmo->a_factor_internal_energy; } +/** + * @brief Sets the physical entropy of a particle + * + * @param p The particle of interest. + * @param xp The extended particle data. + * @param cosmo Cosmology data structure + * @param entropy The physical entropy + */ +__attribute__((always_inline)) INLINE static void hydro_set_physical_entropy( + struct part *p, struct xpart *xp, const struct cosmology *cosmo, + const float entropy) { + + /* Note there is no conversion from physical to comoving entropy */ + const float comoving_entropy = entropy; + xp->u_full = gas_internal_energy_from_entropy(p->rho, comoving_entropy); +} + /** * @brief Computes the hydro time-step of a given particle * diff --git a/src/hydro/AnarchyPU/hydro_part.h b/src/hydro/AnarchyPU/hydro_part.h index e25ca4426376576157390e7da6d5bb69b22c9418..ae42e00e03a3bca621fc4b7a61ae2aa8b2f3c922 100644 --- a/src/hydro/AnarchyPU/hydro_part.h +++ b/src/hydro/AnarchyPU/hydro_part.h @@ -33,6 +33,8 @@ #include "chemistry_struct.h" #include "cooling_struct.h" +#include "star_formation_struct.h" +#include "tracers_struct.h" /** * @brief Particle fields not needed during the SPH loops over neighbours. @@ -61,6 +63,12 @@ struct xpart { /*! Additional data used to record cooling information */ struct cooling_xpart_data cooling_data; + /* Additional data used by the tracers */ + struct tracers_xpart_data tracers_data; + + /* Additional data used by the tracers */ + struct star_formation_xpart_data sf_data; + } SWIFT_STRUCT_ALIGN; /** diff --git a/src/hydro/Gadget2/hydro.h b/src/hydro/Gadget2/hydro.h index e28091815426e01d36ac0902340cd637969a91d9..9994be7dc6051b033c052d32a4ebf3d7b59f1a84 100644 --- a/src/hydro/Gadget2/hydro.h +++ b/src/hydro/Gadget2/hydro.h @@ -306,10 +306,11 @@ hydro_get_physical_internal_energy_dt(const struct part *restrict p, * We assume a constant density for the conversion to entropy. * * @param p The particle of interest. - * @param du_dt The new time derivative of the internal energy. + * @param du_dt The new time derivative of the comoving internal energy. */ __attribute__((always_inline)) INLINE static void -hydro_set_comoving_internal_energy_dt(struct part *restrict p, float du_dt) { +hydro_set_comoving_internal_energy_dt(struct part *restrict p, + const float du_dt) { p->entropy_dt = gas_entropy_from_internal_energy(p->rho, du_dt); } @@ -321,15 +322,30 @@ hydro_set_comoving_internal_energy_dt(struct part *restrict p, float du_dt) { * * @param p The particle of interest. * @param cosmo Cosmology data structure - * @param du_dt The time derivative of the internal energy. + * @param du_dt The time derivative of the physical internal energy. */ __attribute__((always_inline)) INLINE static void hydro_set_physical_internal_energy_dt(struct part *restrict p, const struct cosmology *restrict cosmo, - float du_dt) { + const float du_dt) { p->entropy_dt = gas_entropy_from_internal_energy(p->rho * cosmo->a3_inv, du_dt); } +/** + * @brief Sets the physical entropy of a particle + * + * @param p The particle of interest. + * @param xp The extended particle data. + * @param cosmo Cosmology data structure + * @param entropy The physical entropy + */ +__attribute__((always_inline)) INLINE static void hydro_set_physical_entropy( + struct part *p, struct xpart *xp, const struct cosmology *cosmo, + const float entropy) { + + /* Note there is no conversion from physical to comoving entropy */ + xp->entropy_full = entropy; +} /** * @brief Computes the hydro time-step of a given particle diff --git a/src/hydro/Gadget2/hydro_part.h b/src/hydro/Gadget2/hydro_part.h index 099f3b769d1ffa946c5e83f7190f325c5a42074c..6b028b0497584ca65bd236c4a507b55356e7c260 100644 --- a/src/hydro/Gadget2/hydro_part.h +++ b/src/hydro/Gadget2/hydro_part.h @@ -34,6 +34,7 @@ #include "chemistry_struct.h" #include "cooling_struct.h" #include "logger.h" +#include "star_formation_struct.h" #include "tracers_struct.h" /* Extra particle data not needed during the SPH loops over neighbours. */ @@ -60,6 +61,9 @@ struct xpart { /* Additional data used by the tracers */ struct tracers_xpart_data tracers_data; + /* Additional data used by the star formation */ + struct star_formation_xpart_data sf_data; + #ifdef WITH_LOGGER /* Additional data for the particle logger */ struct logger_part_data logger_data; diff --git a/src/hydro/GizmoMFM/hydro_part.h b/src/hydro/GizmoMFM/hydro_part.h index a05cae18aaf18feb80f7a4ec383434eadece8a41..c4884ebc40a18de765aed193a028c92465ad63ad 100644 --- a/src/hydro/GizmoMFM/hydro_part.h +++ b/src/hydro/GizmoMFM/hydro_part.h @@ -21,6 +21,7 @@ #include "chemistry_struct.h" #include "cooling_struct.h" +#include "star_formation_struct.h" #include "tracers_struct.h" /* Extra particle data not needed during the computation. */ @@ -44,6 +45,9 @@ struct xpart { /* Additional data used by the tracers */ struct tracers_xpart_data tracers_data; + /* Additional data used by the star formation */ + struct star_formation_xpart_data sf_data; + } SWIFT_STRUCT_ALIGN; /* Data of a single particle. */ diff --git a/src/hydro/GizmoMFV/hydro_part.h b/src/hydro/GizmoMFV/hydro_part.h index 8794b597712963e962cc23c796e9769efd4ea620..c6bbaeb1c8e256081f7300c041dfa3cd996fbf18 100644 --- a/src/hydro/GizmoMFV/hydro_part.h +++ b/src/hydro/GizmoMFV/hydro_part.h @@ -21,6 +21,7 @@ #include "chemistry_struct.h" #include "cooling_struct.h" +#include "star_formation_struct.h" #include "tracers_struct.h" /* Extra particle data not needed during the computation. */ @@ -44,6 +45,9 @@ struct xpart { /* Additional data used by the tracers */ struct tracers_xpart_data tracers_data; + /* Additional data used by the star formation */ + struct star_formation_xpart_data sf_data; + } SWIFT_STRUCT_ALIGN; /* Data of a single particle. */ diff --git a/src/hydro/Minimal/hydro.h b/src/hydro/Minimal/hydro.h index 2af6eb47e8de091f391dc758e7842cc5cada702a..a5808468300da234a91a86feb897a9398e14db90 100644 --- a/src/hydro/Minimal/hydro.h +++ b/src/hydro/Minimal/hydro.h @@ -337,6 +337,23 @@ hydro_set_physical_internal_energy_dt(struct part *restrict p, p->u_dt = du_dt / cosmo->a_factor_internal_energy; } +/** + * @brief Sets the physical entropy of a particle + * + * @param p The particle of interest. + * @param xp The extended particle data. + * @param cosmo Cosmology data structure + * @param entropy The physical entropy + */ +__attribute__((always_inline)) INLINE static void hydro_set_physical_entropy( + struct part *p, struct xpart *xp, const struct cosmology *cosmo, + const float entropy) { + + /* Note there is no conversion from physical to comoving entropy */ + const float comoving_entropy = entropy; + xp->u_full = gas_internal_energy_from_entropy(p->rho, comoving_entropy); +} + /** * @brief Computes the hydro time-step of a given particle * diff --git a/src/hydro/Minimal/hydro_part.h b/src/hydro/Minimal/hydro_part.h index 80e472194e6a008859fa7e7fde9c79df6611142b..2068c08b01fcbe57f6a2439770ca85e6e0e06b3a 100644 --- a/src/hydro/Minimal/hydro_part.h +++ b/src/hydro/Minimal/hydro_part.h @@ -34,6 +34,7 @@ #include "chemistry_struct.h" #include "cooling_struct.h" +#include "star_formation_struct.h" #include "tracers_struct.h" /** @@ -66,6 +67,9 @@ struct xpart { /* Additional data used by the tracers */ struct tracers_xpart_data tracers_data; + /* Additional data used by the tracers */ + struct star_formation_xpart_data sf_data; + } SWIFT_STRUCT_ALIGN; /** diff --git a/src/hydro/Planetary/hydro.h b/src/hydro/Planetary/hydro.h index 68dfa3eb825b7dd984eb6fd52336ee97b0c4f93e..fbe0b6c8b9a8844cab3e38e485923fc7543ec528 100644 --- a/src/hydro/Planetary/hydro.h +++ b/src/hydro/Planetary/hydro.h @@ -360,6 +360,24 @@ hydro_set_physical_internal_energy_dt(struct part *restrict p, p->u_dt = du_dt / cosmo->a_factor_internal_energy; } +/** + * @brief Sets the physical entropy of a particle + * + * @param p The particle of interest. + * @param xp The extended particle data. + * @param cosmo Cosmology data structure + * @param entropy The physical entropy + */ +__attribute__((always_inline)) INLINE static void hydro_set_physical_entropy( + struct part *p, struct xpart *xp, const struct cosmology *cosmo, + const float entropy) { + + /* Note there is no conversion from physical to comoving entropy */ + const float comoving_entropy = entropy; + xp->u_full = + gas_internal_energy_from_entropy(p->rho, comoving_entropy, p->mat_id); +} + /** * @brief Computes the hydro time-step of a given particle * diff --git a/src/hydro/Planetary/hydro_part.h b/src/hydro/Planetary/hydro_part.h index 1955366da7265c4c40922d1e7290bc9128641600..383d803fd9baebbaba702d788239cc8d684254bc 100644 --- a/src/hydro/Planetary/hydro_part.h +++ b/src/hydro/Planetary/hydro_part.h @@ -36,6 +36,7 @@ #include "chemistry_struct.h" #include "cooling_struct.h" #include "equation_of_state.h" // For enum material_id +#include "star_formation_struct.h" #include "tracers_struct.h" /** @@ -65,9 +66,12 @@ struct xpart { /*! Additional data used to record cooling information */ struct cooling_xpart_data cooling_data; - /* Additional data used by the tracers */ + /*! Additional data used by the tracers */ struct tracers_xpart_data tracers_data; + /* Additional data used by the star formation */ + struct star_formation_xpart_data sf_data; + } SWIFT_STRUCT_ALIGN; /** diff --git a/src/hydro/PressureEnergy/hydro.h b/src/hydro/PressureEnergy/hydro.h index 7b6c302fb7f8001cb96d595eb35fb6ef08222bec..4af00f7a657d61871dc0a82affb04d411e13e047 100644 --- a/src/hydro/PressureEnergy/hydro.h +++ b/src/hydro/PressureEnergy/hydro.h @@ -362,6 +362,23 @@ hydro_set_physical_internal_energy_dt(struct part *restrict p, p->u_dt = du_dt / cosmo->a_factor_internal_energy; } +/** + * @brief Sets the physical entropy of a particle + * + * @param p The particle of interest. + * @param xp The extended particle data. + * @param cosmo Cosmology data structure + * @param entropy The physical entropy + */ +__attribute__((always_inline)) INLINE static void hydro_set_physical_entropy( + struct part *p, struct xpart *xp, const struct cosmology *cosmo, + const float entropy) { + + /* Note there is no conversion from physical to comoving entropy */ + const float comoving_entropy = entropy; + xp->u_full = gas_internal_energy_from_entropy(p->rho, comoving_entropy); +} + /** * @brief Computes the hydro time-step of a given particle * diff --git a/src/hydro/PressureEnergy/hydro_part.h b/src/hydro/PressureEnergy/hydro_part.h index 218fbf5dc17559b07974b68e42f69f4e7a0e8e3b..6a2d890049bef5fe7040e7908a48df304beddb64 100644 --- a/src/hydro/PressureEnergy/hydro_part.h +++ b/src/hydro/PressureEnergy/hydro_part.h @@ -33,6 +33,7 @@ #include "chemistry_struct.h" #include "cooling_struct.h" +#include "star_formation_struct.h" #include "tracers_struct.h" /** @@ -62,9 +63,12 @@ struct xpart { /*! Additional data used to record cooling information */ struct cooling_xpart_data cooling_data; - /* Additional data used by the tracers */ + /*! Additional data used by the tracers */ struct tracers_xpart_data tracers_data; + /*! Additional data used by the star formation */ + struct star_formation_xpart_data sf_data; + } SWIFT_STRUCT_ALIGN; /** diff --git a/src/hydro/PressureEnergyMorrisMonaghanAV/hydro.h b/src/hydro/PressureEnergyMorrisMonaghanAV/hydro.h index 9767a165d3f9243c9dd9b72bdc9131fe338e52b4..b50ca4e2543af94573ff34954c26a23200b78a1d 100644 --- a/src/hydro/PressureEnergyMorrisMonaghanAV/hydro.h +++ b/src/hydro/PressureEnergyMorrisMonaghanAV/hydro.h @@ -143,11 +143,12 @@ __attribute__((always_inline)) INLINE static float hydro_get_comoving_entropy( * @param cosmo The cosmological model. */ __attribute__((always_inline)) INLINE static float hydro_get_physical_entropy( - const struct part *restrict p, const struct cosmology *cosmo) { + const struct part *restrict p, const struct xpart *restrict xp, + const struct cosmology *cosmo) { /* Note: no cosmological conversion required here with our choice of * coordinates. */ - return gas_entropy_from_internal_energy(p->rho, p->u); + return gas_entropy_from_internal_energy(p->rho, xp->u_full); } /** @@ -306,12 +307,27 @@ __attribute__((always_inline)) INLINE static void hydro_get_drifted_velocities( * * @param p The particle of interest */ -__attribute__((always_inline)) INLINE static float hydro_get_internal_energy_dt( - const struct part *restrict p) { +__attribute__((always_inline)) INLINE static float +hydro_get_comoving_internal_energy_dt(const struct part *restrict p) { return p->u_dt; } +/** + * @brief Returns the time derivative of internal energy of a particle + * + * We assume a constant density. + * + * @param p The particle of interest + * @param cosmo Cosmology data structure + */ +__attribute__((always_inline)) INLINE static float +hydro_get_physical_internal_energy_dt(const struct part *restrict p, + const struct cosmology *cosmo) { + + return p->u_dt * cosmo->a_factor_internal_energy; +} + /** * @brief Sets the time derivative of internal energy of a particle * @@ -320,12 +336,46 @@ __attribute__((always_inline)) INLINE static float hydro_get_internal_energy_dt( * @param p The particle of interest. * @param du_dt The new time derivative of the internal energy. */ -__attribute__((always_inline)) INLINE static void hydro_set_internal_energy_dt( - struct part *restrict p, float du_dt) { +__attribute__((always_inline)) INLINE static void +hydro_set_comoving_internal_energy_dt(struct part *restrict p, float du_dt) { p->u_dt = du_dt; } +/** + * @brief Returns the time derivative of internal energy of a particle + * + * We assume a constant density. + * + * @param p The particle of interest. + * @param cosmo Cosmology data structure + * @param du_dt The new time derivative of the internal energy. + */ +__attribute__((always_inline)) INLINE static void +hydro_set_physical_internal_energy_dt(struct part *restrict p, + const struct cosmology *cosmo, + float du_dt) { + + p->u_dt = du_dt / cosmo->a_factor_internal_energy; +} + +/** + * @brief Sets the physical entropy of a particle + * + * @param p The particle of interest. + * @param xp The extended particle data. + * @param cosmo Cosmology data structure + * @param entropy The physical entropy + */ +__attribute__((always_inline)) INLINE static void hydro_set_physical_entropy( + struct part *p, struct xpart *xp, const struct cosmology *cosmo, + const float entropy) { + + /* Note there is no conversion from physical to comoving entropy */ + const float comoving_entropy = entropy; + xp->u_full = gas_internal_energy_from_entropy(p->rho, comoving_entropy); +} + /** * @brief Computes the hydro time-step of a given particle * diff --git a/src/hydro/PressureEnergyMorrisMonaghanAV/hydro_part.h b/src/hydro/PressureEnergyMorrisMonaghanAV/hydro_part.h index d66249ea179a830cedbd3c3f165ca5012fd18862..b75313b58e01260fa267d4b5bab29815a7329ce7 100644 --- a/src/hydro/PressureEnergyMorrisMonaghanAV/hydro_part.h +++ b/src/hydro/PressureEnergyMorrisMonaghanAV/hydro_part.h @@ -34,6 +34,7 @@ #include "chemistry_struct.h" #include "cooling_struct.h" +#include "star_formation_struct.h" #include "tracers_struct.h" /** @@ -63,9 +64,12 @@ struct xpart { /*! Additional data used to record cooling information */ struct cooling_xpart_data cooling_data; - /* Additional data used by the tracers */ + /*! Additional data used by the tracers */ struct tracers_xpart_data tracers_data; + /*! Additional data used by the star formation */ + struct star_formation_xpart_data sf_data; + } SWIFT_STRUCT_ALIGN; /** diff --git a/src/hydro/PressureEntropy/hydro.h b/src/hydro/PressureEntropy/hydro.h index 2e8d2d5db615f239bf5c3567e7beb155eab5cb38..40b3f42eaed7cbff3c6503caa0fc8801d65ac8e3 100644 --- a/src/hydro/PressureEntropy/hydro.h +++ b/src/hydro/PressureEntropy/hydro.h @@ -327,6 +327,21 @@ hydro_set_physical_internal_energy_dt(struct part *restrict p, p->entropy_dt = gas_entropy_from_internal_energy(p->rho_bar * cosmo->a3_inv, du_dt); } +/** + * @brief Sets the physical entropy of a particle + * + * @param p The particle of interest. + * @param xp The extended particle data. + * @param cosmo Cosmology data structure + * @param entropy The physical entropy + */ +__attribute__((always_inline)) INLINE static void hydro_set_physical_entropy( + struct part *p, struct xpart *xp, const struct cosmology *cosmo, + const float entropy) { + + /* Note there is no conversion from physical to comoving entropy */ + xp->entropy_full = entropy; +} /** * @brief Computes the hydro time-step of a given particle diff --git a/src/hydro/PressureEntropy/hydro_part.h b/src/hydro/PressureEntropy/hydro_part.h index a404a897b06ddc0777a493e2ecfd28b68e15defe..992ed4654e63fe42e1f45c04ed8bfe876cb89e45 100644 --- a/src/hydro/PressureEntropy/hydro_part.h +++ b/src/hydro/PressureEntropy/hydro_part.h @@ -32,6 +32,7 @@ #include "chemistry_struct.h" #include "cooling_struct.h" +#include "star_formation_struct.h" #include "tracers_struct.h" /* Extra particle data not needed during the SPH loops over neighbours. */ @@ -55,9 +56,12 @@ struct xpart { /*! Additional data used to record cooling information */ struct cooling_xpart_data cooling_data; - /* Additional data used by the tracers */ + /*! Additional data used by the tracers */ struct tracers_xpart_data tracers_data; + /*! Additional data used by the star formation */ + struct star_formation_xpart_data sf_data; + } SWIFT_STRUCT_ALIGN; /* Data of a single particle. */ diff --git a/src/kick.h b/src/kick.h index 7fb2afc1fa251dff30e81c5b0093b6313d8c4b7c..f2085bf1f427cf5f15ed0e8791ad1923f0b22bed 100644 --- a/src/kick.h +++ b/src/kick.h @@ -70,7 +70,8 @@ __attribute__((always_inline)) INLINE static void kick_gpart( * @param dt_kick_therm The kick time-step for changes in thermal state. * @param dt_kick_corr The kick time-step for the gizmo-mfv gravity correction. * @param cosmo The cosmological model. - * @param hydro_props The constants used in the scheme + * @param hydro_props The constants used in the scheme. + * @param entropy_floor_props Properties of the entropy floor. * @param ti_start The starting (integer) time of the kick (for debugging * checks). * @param ti_end The ending (integer) time of the kick (for debugging checks). @@ -79,6 +80,7 @@ __attribute__((always_inline)) INLINE static void kick_part( struct part *restrict p, struct xpart *restrict xp, double dt_kick_hydro, double dt_kick_grav, double dt_kick_therm, double dt_kick_corr, const struct cosmology *cosmo, const struct hydro_props *hydro_props, + const struct entropy_floor_properties *entropy_floor_props, integertime_t ti_start, integertime_t ti_end) { #ifdef SWIFT_DEBUG_CHECKS @@ -114,6 +116,13 @@ __attribute__((always_inline)) INLINE static void kick_part( hydro_kick_extra(p, xp, dt_kick_therm, dt_kick_grav, dt_kick_hydro, dt_kick_corr, cosmo, hydro_props); if (p->gpart != NULL) gravity_kick_extra(p->gpart, dt_kick_grav); + + /* Verify that the particle is not below the entropy floor */ + const float floor = entropy_floor(p, cosmo, entropy_floor_props); + if (hydro_get_physical_entropy(p, xp, cosmo) < floor) { + hydro_set_physical_entropy(p, xp, cosmo, floor); + hydro_set_physical_internal_energy_dt(p, cosmo, 0.f); + } } /** diff --git a/src/parallel_io.c b/src/parallel_io.c index ec761d3bf9a2540fb21ed8485e9ec8a83f6e204e..b598d944dfe7c90510b036e7f9d85619ea103c59 100644 --- a/src/parallel_io.c +++ b/src/parallel_io.c @@ -42,6 +42,7 @@ #include "cooling_io.h" #include "dimension.h" #include "engine.h" +#include "entropy_floor.h" #include "error.h" #include "gravity_io.h" #include "gravity_properties.h" @@ -51,6 +52,7 @@ #include "kernel_hydro.h" #include "part.h" #include "part_type.h" +#include "star_formation_io.h" #include "stars_io.h" #include "tracers_io.h" #include "units.h" @@ -1063,6 +1065,7 @@ void prepare_file(struct engine* e, const char* baseName, long long N_total[6], h_grp = H5Gcreate(h_file, "/SubgridScheme", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); if (h_grp < 0) error("Error while creating subgrid group"); + entropy_floor_write_flavour(h_grp); cooling_write_flavour(h_grp, e->cooling_func); chemistry_write_flavour(h_grp); tracers_write_flavour(h_grp); @@ -1152,6 +1155,8 @@ void prepare_file(struct engine* e, const char* baseName, long long N_total[6], } num_fields += tracers_write_particles(parts, xparts, list + num_fields, with_cosmology); + num_fields += + star_formation_write_particles(parts, xparts, list + num_fields); if (with_stf) { num_fields += velociraptor_write_parts(parts, xparts, list + num_fields); @@ -1168,6 +1173,9 @@ void prepare_file(struct engine* e, const char* baseName, long long N_total[6], case swift_type_stars: stars_write_particles(sparts, list, &num_fields); + num_fields += chemistry_write_sparticles(sparts, list + num_fields); + num_fields += + tracers_write_sparticles(sparts, list + num_fields, with_cosmology); if (with_stf) { num_fields += velociraptor_write_sparts(sparts, list + num_fields); } @@ -1470,6 +1478,8 @@ void write_output_parallel(struct engine* e, const char* baseName, } num_fields += tracers_write_particles( parts, xparts, list + num_fields, with_cosmology); + num_fields += + star_formation_write_particles(parts, xparts, list + num_fields); } else { @@ -1504,6 +1514,8 @@ void write_output_parallel(struct engine* e, const char* baseName, } num_fields += tracers_write_particles( parts_written, xparts_written, list + num_fields, with_cosmology); + num_fields += star_formation_write_particles( + parts_written, xparts_written, list + num_fields); } } break; @@ -1558,6 +1570,9 @@ void write_output_parallel(struct engine* e, const char* baseName, /* No inhibted particles: easy case */ Nparticles = Nstars; stars_write_particles(sparts, list, &num_fields); + num_fields += chemistry_write_sparticles(sparts, list + num_fields); + num_fields += tracers_write_sparticles(sparts, list + num_fields, + with_cosmology); if (with_stf) { num_fields += velociraptor_write_sparts(sparts, list + num_fields); } @@ -1577,6 +1592,9 @@ void write_output_parallel(struct engine* e, const char* baseName, /* Select the fields to write */ stars_write_particles(sparts_written, list, &num_fields); + num_fields += chemistry_write_sparticles(sparts, list + num_fields); + num_fields += tracers_write_sparticles(sparts, list + num_fields, + with_cosmology); if (with_stf) { num_fields += velociraptor_write_sparts(sparts_written, list + num_fields); diff --git a/src/part.h b/src/part.h index a0a09457039daa9ba59b7378638db12b5debafe2..069a5075c1a8aa1037f37df2f1ce0168e1130a5f 100644 --- a/src/part.h +++ b/src/part.h @@ -93,7 +93,15 @@ #endif /* Import the right star particle definition */ +#if defined(STARS_NONE) #include "./stars/Default/stars_part.h" +#elif defined(STARS_EAGLE) +#include "./stars/EAGLE/stars_part.h" +#elif defined(STARS_GEAR) +#include "./stars/GEAR/stars_part.h" +#else +#error "Invalid choice of star particle" +#endif void part_relink_gparts_to_parts(struct part *parts, size_t N, ptrdiff_t offset); diff --git a/src/random.h b/src/random.h new file mode 100644 index 0000000000000000000000000000000000000000..826ac75fb24e50df68d9bb43906d008cd3380bc6 --- /dev/null +++ b/src/random.h @@ -0,0 +1,76 @@ +/******************************************************************************* + * This file is part of SWIFT. + * Copyright (c) 2018 Matthieu Schaller (schaller@strw.leidenuniv.nl) + * + * 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_RANDOM_H +#define SWIFT_RANDOM_H + +/* COde configuration */ +#include "../config.h" + +/* Standard header */ +#include <stdlib.h> + +/** + * @brief The categories of random number generated. + * + * The values of the fields are carefully chose prime + * numbers. Only change them if you know what you are + * doing! + */ +enum random_number_type { + random_number_star_formation = 7, + random_number_stellar_feedback = 53, + random_number_stellar_enrichment = 197, + random_number_BH_feedback = 491 +}; + +/** + * @brief Returns a pseudo-random number in the range [0, 1[. + * + * We generate numbers that are always reproducible for a given particle ID and + * simulation time (on the integer time-line). If more than one number per + * time-step per particle is needed, additional randomness can be obtained by + * using the type argument. + * + * @param id The ID of the particle for which to generate a number. + * @param ti_current The time (on the time-line) for which to generate a number. + * @param type The #random_number_type to generate. + * @return a random number in the interval [0, 1.[. + */ +INLINE static double random_unit_interval(const long long int id, + const integertime_t ti_current, + const enum random_number_type type) { + + /* Range used for the seeds. Best if prime */ + static const long long seed_range = RAND_MAX; + static const double RAND_MAX_inv = 1. / ((double)RAND_MAX); + + /* Calculate the seed */ + /* WARNING: Only change the math if you really know what you are doing! + The numbers are carefully chosen prime numbers that prevent correlation + with either the current integer time or the particle IDs. + The calculation overflows on purpose. */ + unsigned int seed = ((937LL * id + 1109LL) % 2147987LL + + (ti_current - 1) % 1514917LL + (long long)type) % + seed_range; + + /* Generate a random number between 0 and 1. */ + return rand_r(&seed) * RAND_MAX_inv; +} + +#endif /* SWIFT_RANDOM_H */ diff --git a/src/runner.c b/src/runner.c index ffef12c0e8153d4f6396a494208aa5b845fd878d..df8a52e2cae3f06fb4e59b1cfbce3cf20160f947 100644 --- a/src/runner.c +++ b/src/runner.c @@ -48,6 +48,7 @@ #include "debug.h" #include "drift.h" #include "engine.h" +#include "entropy_floor.h" #include "error.h" #include "gravity.h" #include "hydro.h" @@ -60,6 +61,7 @@ #include "sort_part.h" #include "space.h" #include "space_getsid.h" +#include "star_formation.h" #include "stars.h" #include "task.h" #include "timers.h" @@ -473,9 +475,17 @@ void runner_do_star_formation(struct runner *r, struct cell *c, int timer) { struct engine *e = r->e; const struct cosmology *cosmo = e->cosmology; + const struct star_formation *sf_props = e->star_formation; + const struct phys_const *phys_const = e->physical_constants; const int count = c->hydro.count; struct part *restrict parts = c->hydro.parts; struct xpart *restrict xparts = c->hydro.xparts; + const int with_cosmology = (e->policy & engine_policy_cosmology); + const struct hydro_props *restrict hydro_props = e->hydro_properties; + const struct unit_system *restrict us = e->internal_units; + struct cooling_function_data *restrict cooling = e->cooling_func; + const double time_base = e->time_base; + const integertime_t ti_current = e->ti_current; TIMER_TIC; @@ -495,25 +505,52 @@ void runner_do_star_formation(struct runner *r, struct cell *c, int timer) { struct part *restrict p = &parts[k]; struct xpart *restrict xp = &xparts[k]; + /* Only work on active particles */ if (part_is_active(p, e)) { - const float rho = hydro_get_physical_density(p, cosmo); + /* Is this particle star forming? */ + if (star_formation_is_star_forming(p, xp, sf_props, phys_const, cosmo, + hydro_props, us, cooling)) { - // MATTHIEU: Temporary star-formation law - // Do not use this at home. - if (rho > 1.7e7 && e->step > 2) { - message("Removing particle id=%lld rho=%e", p->id, rho); + /* Time-step size for this particle */ + double dt_star; + if (with_cosmology) { + const integertime_t ti_step = get_integer_timestep(p->time_bin); + const integertime_t ti_begin = + get_integer_time_begin(ti_current - 1, p->time_bin); - struct spart *sp = cell_convert_part_to_spart(e, c, p, xp); + dt_star = + cosmology_get_delta_time(cosmo, ti_begin, ti_begin + ti_step); - /* Did we run out of fresh particles? */ - if (sp == NULL) continue; + } else { + dt_star = get_timestep(p->time_bin, time_base); + } - /* Set everything to a valid state */ - stars_init_spart(sp); - } - } - } + /* Compute the SF rate of the particle */ + star_formation_compute_SFR(p, xp, sf_props, phys_const, cosmo, + dt_star); + + /* Are we forming a star particle from this SF rate? */ + if (star_formation_should_convert_to_star(p, xp, sf_props, e, + dt_star)) { + + /* Convert the gas particle to a star particle */ + struct spart *sp = cell_convert_part_to_spart(e, c, p, xp); + + /* Copy the properties of the gas particle to the star particle */ + star_formation_copy_properties(p, xp, sp, e, sf_props, cosmo, + with_cosmology); + } + + } else { /* Are we not star-forming? */ + + /* Update the particle to flag it as not star-forming */ + star_formation_update_part_not_SFR(p, xp, e, sf_props, + with_cosmology); + + } /* Not Star-forming? */ + } /* is active? */ + } /* Loop over particles */ } if (timer) TIMER_TOC(timer_do_star_formation); @@ -1381,7 +1418,7 @@ void runner_do_ghost(struct runner *r, struct cell *c, int timer) { } /* Check whether the particle has an inappropriate smoothing length */ - if (fabsf(h_new - h_old) > eps * h_init) { + if (fabsf(h_new - h_old) > eps * h_old) { /* Ok, correct then */ @@ -1707,6 +1744,7 @@ void runner_do_kick1(struct runner *r, struct cell *c, int timer) { const struct engine *e = r->e; const struct cosmology *cosmo = e->cosmology; const struct hydro_props *hydro_props = e->hydro_properties; + const struct entropy_floor_properties *entropy_floor = e->entropy_floor; const int with_cosmology = (e->policy & engine_policy_cosmology); struct part *restrict parts = c->hydro.parts; struct xpart *restrict xparts = c->hydro.xparts; @@ -1781,7 +1819,7 @@ void runner_do_kick1(struct runner *r, struct cell *c, int timer) { /* do the kick */ kick_part(p, xp, dt_kick_hydro, dt_kick_grav, dt_kick_therm, - dt_kick_corr, cosmo, hydro_props, ti_begin, + dt_kick_corr, cosmo, hydro_props, entropy_floor, ti_begin, ti_begin + ti_step / 2); /* Update the accelerations to be used in the drift for hydro */ @@ -1888,6 +1926,7 @@ void runner_do_kick2(struct runner *r, struct cell *c, int timer) { const struct engine *e = r->e; const struct cosmology *cosmo = e->cosmology; const struct hydro_props *hydro_props = e->hydro_properties; + const struct entropy_floor_properties *entropy_floor = e->entropy_floor; const int with_cosmology = (e->policy & engine_policy_cosmology); const int count = c->hydro.count; const int gcount = c->grav.count; @@ -1972,8 +2011,8 @@ void runner_do_kick2(struct runner *r, struct cell *c, int timer) { /* Finish the time-step with a second half-kick */ kick_part(p, xp, dt_kick_hydro, dt_kick_grav, dt_kick_therm, - dt_kick_corr, cosmo, hydro_props, ti_begin + ti_step / 2, - ti_end); + dt_kick_corr, cosmo, hydro_props, entropy_floor, + ti_begin + ti_step / 2, ti_end); #ifdef SWIFT_DEBUG_CHECKS /* Check that kick and the drift are synchronized */ diff --git a/src/serial_io.c b/src/serial_io.c index 3d9ae4ee0b5a7f4641650f03aac03d5968ee92a2..b55f4780814fe45544a5680e95e67f55194fc5e8 100644 --- a/src/serial_io.c +++ b/src/serial_io.c @@ -42,6 +42,7 @@ #include "cooling_io.h" #include "dimension.h" #include "engine.h" +#include "entropy_floor.h" #include "error.h" #include "gravity_io.h" #include "gravity_properties.h" @@ -51,6 +52,7 @@ #include "kernel_hydro.h" #include "part.h" #include "part_type.h" +#include "star_formation_io.h" #include "stars_io.h" #include "tracers_io.h" #include "units.h" @@ -925,6 +927,7 @@ void write_output_serial(struct engine* e, const char* baseName, h_grp = H5Gcreate(h_file, "/SubgridScheme", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); if (h_grp < 0) error("Error while creating subgrid group"); + entropy_floor_write_flavour(h_grp); cooling_write_flavour(h_grp, e->cooling_func); chemistry_write_flavour(h_grp); tracers_write_flavour(h_grp); @@ -1120,6 +1123,8 @@ void write_output_serial(struct engine* e, const char* baseName, } num_fields += tracers_write_particles( parts, xparts, list + num_fields, with_cosmology); + num_fields += star_formation_write_particles(parts, xparts, + list + num_fields); } else { @@ -1155,6 +1160,8 @@ void write_output_serial(struct engine* e, const char* baseName, num_fields += tracers_write_particles(parts_written, xparts_written, list + num_fields, with_cosmology); + num_fields += star_formation_write_particles( + parts_written, xparts_written, list + num_fields); } } break; @@ -1208,6 +1215,10 @@ void write_output_serial(struct engine* e, const char* baseName, /* No inhibted particles: easy case */ Nparticles = Nstars; stars_write_particles(sparts, list, &num_fields); + num_fields += + chemistry_write_sparticles(sparts, list + num_fields); + num_fields += tracers_write_sparticles(sparts, list + num_fields, + with_cosmology); if (with_stf) { num_fields += velociraptor_write_sparts(sparts, list + num_fields); @@ -1228,6 +1239,10 @@ void write_output_serial(struct engine* e, const char* baseName, /* Select the fields to write */ stars_write_particles(sparts_written, list, &num_fields); + num_fields += + chemistry_write_sparticles(sparts, list + num_fields); + num_fields += tracers_write_sparticles(sparts, list + num_fields, + with_cosmology); if (with_stf) { num_fields += velociraptor_write_sparts(sparts_written, list + num_fields); diff --git a/src/single_io.c b/src/single_io.c index 0522174dee3882674239983bc182125e893419c5..4b23310ee02f3b485eff1a0358de850f497a3478 100644 --- a/src/single_io.c +++ b/src/single_io.c @@ -41,6 +41,7 @@ #include "cooling_io.h" #include "dimension.h" #include "engine.h" +#include "entropy_floor.h" #include "error.h" #include "gravity_io.h" #include "gravity_properties.h" @@ -50,6 +51,7 @@ #include "kernel_hydro.h" #include "part.h" #include "part_type.h" +#include "star_formation_io.h" #include "stars_io.h" #include "tracers_io.h" #include "units.h" @@ -777,6 +779,7 @@ void write_output_single(struct engine* e, const char* baseName, h_grp = H5Gcreate(h_file, "/SubgridScheme", H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); if (h_grp < 0) error("Error while creating subgrid group"); + entropy_floor_write_flavour(h_grp); cooling_write_flavour(h_grp, e->cooling_func); chemistry_write_flavour(h_grp); tracers_write_flavour(h_grp); @@ -923,6 +926,8 @@ void write_output_single(struct engine* e, const char* baseName, } num_fields += tracers_write_particles( parts, xparts, list + num_fields, with_cosmology); + num_fields += + star_formation_write_particles(parts, xparts, list + num_fields); } else { @@ -957,6 +962,8 @@ void write_output_single(struct engine* e, const char* baseName, } num_fields += tracers_write_particles( parts_written, xparts_written, list + num_fields, with_cosmology); + num_fields += star_formation_write_particles( + parts_written, xparts_written, list + num_fields); } } break; @@ -1009,6 +1016,9 @@ void write_output_single(struct engine* e, const char* baseName, /* No inhibted particles: easy case */ N = Nstars; stars_write_particles(sparts, list, &num_fields); + num_fields += chemistry_write_sparticles(sparts, list + num_fields); + num_fields += tracers_write_sparticles(sparts, list + num_fields, + with_cosmology); if (with_stf) { num_fields += velociraptor_write_sparts(sparts, list + num_fields); } @@ -1028,6 +1038,10 @@ void write_output_single(struct engine* e, const char* baseName, /* Select the fields to write */ stars_write_particles(sparts_written, list, &num_fields); + num_fields += + chemistry_write_sparticles(sparts_written, list + num_fields); + num_fields += tracers_write_sparticles( + sparts_written, list + num_fields, with_cosmology); if (with_stf) { num_fields += velociraptor_write_sparts(sparts_written, list + num_fields); diff --git a/src/star_formation.c b/src/star_formation.c new file mode 100644 index 0000000000000000000000000000000000000000..698a64cc636dd79f00feac3f6cc88bf519fe09c1 --- /dev/null +++ b/src/star_formation.c @@ -0,0 +1,83 @@ +/******************************************************************************* + * This file is part of SWIFT. + * Copyright (c) 2018 Folkert Nobels (nobels@strw.leidenuniv.nl) + * + * 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/>. + * + ******************************************************************************/ + +/* Config parameters. */ +#include "../config.h" + +/* This object's header. */ +#include "part.h" +#include "restart.h" +#include "star_formation.h" +#include "units.h" + +/** + * @brief Initialises the star formation law properties in the internal + * unit system. + * + * @param parameter_file The parsed parameter file + * @param phys_const Physical constants in internal units + * @param us the current internal system of units + * @param hydro_props The propoerties of the hydro scheme. + * @param starform the properties of the star formation law + */ +void starformation_init(struct swift_params* parameter_file, + const struct phys_const* phys_const, + const struct unit_system* us, + const struct hydro_props* hydro_props, + struct star_formation* starform) { + + starformation_init_backend(parameter_file, phys_const, us, hydro_props, + starform); +} + +/** + * @brief Print the properties of the star fromation law + * + * @param starform the star formation properties. + */ +void starformation_print(const struct star_formation* starform) { + + starformation_print_backend(starform); +} + +/** + * @brief Write an star_formation struct to the given FILE as a stream of + * bytes. + * + * @param starform the star formation struct + * @param stream the file stream + */ +void starformation_struct_dump(const struct star_formation* starform, + FILE* stream) { + restart_write_blocks((void*)starform, sizeof(struct star_formation), 1, + stream, "starformation", "star formation"); +} + +/** + * @brief Restore a star_formation struct from the given FILE as a stream of + * bytes. + * + * @param starform the star formation struct + * @param stream the file stream + */ +void starformation_struct_restore(const struct star_formation* starform, + FILE* stream) { + restart_read_blocks((void*)starform, sizeof(struct star_formation), 1, stream, + NULL, "star formation"); +} diff --git a/src/star_formation.h b/src/star_formation.h new file mode 100644 index 0000000000000000000000000000000000000000..78b9e018bf5f6cabc8a2b34dc5c4915f12806f68 --- /dev/null +++ b/src/star_formation.h @@ -0,0 +1,55 @@ +/******************************************************************************* + * This file is part of SWIFT. + * Copyright (c) 2018 Folkert Nobels (nobels@strw.leidenuniv.nl) + * + * 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_STAR_FORMATION_H +#define SWIFT_STAR_FORMATION_H + +/** + * @file src/star_formation.h + * @brief Branches between the different star formation recipies. + */ + +/* Config parameters. */ +#include "../config.h" + +/* Import the right star formation law definition */ +#if defined(STAR_FORMATION_NONE) +#include "./star_formation/none/star_formation.h" +#elif defined(STAR_FORMATION_EAGLE) +#include "./star_formation/EAGLE/star_formation.h" +#else +#error "Invalid choice of star formation law" +#endif + +/* General functions defined in the source file */ +void starformation_init(struct swift_params* parameter_file, + const struct phys_const* phys_const, + const struct unit_system* us, + const struct hydro_props* hydro_props, + struct star_formation* starform); + +void starformation_print(const struct star_formation* starform); + +/* Dump store */ +void starformation_struct_dump(const struct star_formation* starform, + FILE* stream); + +void starformation_struct_restore(const struct star_formation* starform, + FILE* stream); + +#endif /* SWIFT_STAR_FORMATION_H */ diff --git a/src/star_formation/EAGLE/star_formation.h b/src/star_formation/EAGLE/star_formation.h new file mode 100644 index 0000000000000000000000000000000000000000..511b8073354b20fd573ae5586c2302bad833b06f --- /dev/null +++ b/src/star_formation/EAGLE/star_formation.h @@ -0,0 +1,630 @@ +/******************************************************************************* + * This file is part of SWIFT. + * Copyright (c) 2018 Folkert Nobels (nobels@strw.leidenuniv.nl) + * + * 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_EAGLE_STAR_FORMATION_H +#define SWIFT_EAGLE_STAR_FORMATION_H + +/* Local includes */ +#include "adiabatic_index.h" +#include "cooling.h" +#include "cosmology.h" +#include "engine.h" +#include "equation_of_state.h" +#include "hydro.h" +#include "parser.h" +#include "part.h" +#include "physical_constants.h" +#include "random.h" +#include "stars.h" +#include "units.h" + +/** + * @file src/star_formation/EAGLE/star_formation.h + * @brief Star formation model used in the EAGLE model + */ + +/** + * @brief Properties of the EAGLE star formation model. + */ +struct star_formation { + + /*! Normalization of the KS star formation law (internal units) */ + double KS_normalization; + + /*! Normalization of the KS star formation law (Msun / kpc^2 / yr) */ + double KS_normalization_MSUNpYRpKPC2; + + /*! Slope of the KS law */ + double KS_power_law; + + /*! Slope of the high density KS law */ + double KS_high_den_power_law; + + /*! KS law High density threshold (internal units) */ + double KS_high_den_thresh; + + /*! KS high density normalization (internal units) */ + double KS_high_den_normalization; + + /*! KS high density normalization (H atoms per cm^3) */ + double KS_high_den_thresh_HpCM3; + + /*! Critical overdensity */ + double min_over_den; + + /*! Dalla Vecchia & Schaye temperature criteria */ + double temperature_margin_threshold_dex; + + /*! 10^Tdex of Dalla Vecchia & SChaye temperature criteria */ + double ten_to_temperature_margin_threshold_dex; + + /*! gas fraction */ + double fgas; + + /*! Star formation law slope */ + double SF_power_law; + + /*! star formation normalization (internal units) */ + double SF_normalization; + + /*! star formation high density slope */ + double SF_high_den_power_law; + + /*! Star formation high density normalization (internal units) */ + double SF_high_den_normalization; + + /*! Density threshold to form stars (internal units) */ + double density_threshold; + + /*! Density threshold to form stars in user units */ + double density_threshold_HpCM3; + + /*! Maximum density threshold to form stars (internal units) */ + double density_threshold_max; + + /*! Maximum density threshold to form stars (H atoms per cm^3) */ + double density_threshold_max_HpCM3; + + /*! Reference metallicity for metal-dependant threshold */ + double Z0; + + /*! Inverse of reference metallicity */ + double Z0_inv; + + /*! critical density Metallicity power law (internal units) */ + double n_Z0; + + /*! Polytropic index */ + double EOS_polytropic_index; + + /*! EOS density norm (H atoms per cm^3) */ + double EOS_density_norm_HpCM3; + + /*! EOS Temperature norm (Kelvin) */ + double EOS_temperature_norm_K; + + /*! EOS pressure norm, eq. 13 of Schaye & Dalla Vecchia 2008 (internal units) + */ + double EOS_pressure_c; + + /*! EOS Temperarure norm, eq. 13 of Schaye & Dalla Vecchia 2008 (internal + * units) */ + double EOS_temperature_c; + + /*! EOS density norm, eq. 13 of Schaye & Dalla Vecchia 2008 (internal units) + */ + double EOS_density_c; + + /*! Inverse of EOS density norm (internal units) */ + double EOS_density_c_inv; + + /*! Max physical density (H atoms per cm^3)*/ + double max_gas_density_HpCM3; + + /*! Max physical density (internal units) */ + double max_gas_density; +}; + +/** + * @brief Computes the density threshold for star-formation fo a given total + * metallicity. + * + * Follows Schaye (2004) eq. 19 and 24 (see also Schaye et al. 2015, eq. 2). + * + * @param Z The metallicity (metal mass fraction). + * @param starform The properties of the star formation model. + * @param phys_const The physical constants. + * @return The physical density threshold for star formation in internal units. + */ +INLINE static double star_formation_threshold( + const double Z, const struct star_formation* starform, + const struct phys_const* phys_const) { + + double density_threshold; + + /* Schaye (2004), eq. 19 and 24 */ + if (Z > 0.) { + density_threshold = starform->density_threshold * + powf(Z * starform->Z0_inv, starform->n_Z0); + density_threshold = min(density_threshold, starform->density_threshold_max); + } else { + density_threshold = starform->density_threshold_max; + } + + /* Convert to mass density */ + return density_threshold * phys_const->const_proton_mass; +} + +/** + * @brief Compute the pressure on the polytropic equation of state for a given + * Hydrogen number density. + * + * Schaye & Dalla Vecchia 2008, eq. 13. + * + * @param n_H The Hydrogen number density in internal units. + * @param starform The properties of the star formation model. + * @return The pressure on the equation of state in internal units. + */ +INLINE static double EOS_pressure(const double n_H, + const struct star_formation* starform) { + + return starform->EOS_pressure_c * + pow(n_H * starform->EOS_density_c_inv, starform->EOS_polytropic_index); +} + +/** + * @brief Compute the temperarue on the polytropic equation of state for a given + * Hydrogen number density. + * + * Schaye & Dalla Vecchia 2008, eq. 13 rewritten for temperature + * + * @param n_H The Hydrogen number density in internal units. + * @param starform The properties of the star formation model. + * @return The temperature on the equation of state in internal units. + */ +INLINE static double EOS_temperature(const double n_H, + const struct star_formation* starform) { + + return starform->EOS_temperature_c * + pow(n_H, starform->EOS_polytropic_index - 1.); +} + +/** + * @brief Calculate if the gas has the potential of becoming + * a star. + * + * @param starform the star formation law properties to use. + * @param p the gas particles. + * @param xp the additional properties of the gas particles. + * @param phys_const the physical constants in internal units. + * @param cosmo the cosmological parameters and properties. + * @param hydro_props The properties of the hydro scheme. + * @param us The internal system of units. + * @param cooling The cooling data struct. + * + */ +INLINE static int star_formation_is_star_forming( + const struct part* restrict p, const struct xpart* restrict xp, + const struct star_formation* starform, const struct phys_const* phys_const, + const struct cosmology* cosmo, + const struct hydro_props* restrict hydro_props, + const struct unit_system* restrict us, + const struct cooling_function_data* restrict cooling) { + + /* Minimal density (converted from critical density) for star formation */ + const double rho_crit_times_min_over_den = + cosmo->critical_density * starform->min_over_den; + + /* Physical density of the particle */ + const double physical_density = hydro_get_physical_density(p, cosmo); + + /* Deside whether we should form stars or not, + * first we deterime if we have the correct over density + * if that is true we calculate if either the maximum density + * threshold is reached or if the metallicity dependent + * threshold is reached, after this we calculate if the + * temperature is appropriate */ + if (physical_density < rho_crit_times_min_over_den) return 0; + + /* In this case there are actually multiple possibilities + * because we also need to check if the physical density exceeded + * the appropriate limit */ + + const double Z = p->chemistry_data.smoothed_metal_mass_fraction_total; + const double X_H = p->chemistry_data.smoothed_metal_mass_fraction[0]; + const double n_H = physical_density * X_H; + + /* Get the density threshold */ + const double density_threshold = + star_formation_threshold(Z, starform, phys_const); + + /* Check if it exceeded the minimum density */ + if (n_H < density_threshold) return 0; + + /* Calculate the temperature */ + const double temperature = cooling_get_temperature(phys_const, hydro_props, + us, cosmo, cooling, p, xp); + + /* Temperature on the equation of state */ + const double temperature_eos = EOS_temperature(n_H, starform); + + /* Check the Scahye & Dalla Vecchia 2012 EOS-based temperature critrion */ + return (temperature < + temperature_eos * starform->ten_to_temperature_margin_threshold_dex); +} + +/** + * @brief Compute the star-formation rate of a given particle and store + * it into the #xpart. + * + * @param p #part. + * @param xp the #xpart. + * @param starform the star formation law properties to use + * @param phys_const the physical constants in internal units. + * @param cosmo the cosmological parameters and properties. + * @param dt_star The time-step of this particle. + */ +INLINE static void star_formation_compute_SFR( + const struct part* restrict p, struct xpart* restrict xp, + const struct star_formation* starform, const struct phys_const* phys_const, + const struct cosmology* cosmo, const double dt_star) { + + /* Abort early if time-step size is 0 */ + if (dt_star == 0.) { + + xp->sf_data.SFR = 0.f; + return; + } + + /* Hydrogen number density of this particle */ + const double physical_density = hydro_get_physical_density(p, cosmo); + const double X_H = p->chemistry_data.smoothed_metal_mass_fraction[0]; + const double n_H = physical_density * X_H / phys_const->const_proton_mass; + + /* Are we above the threshold for automatic star formation? */ + if (physical_density > + starform->max_gas_density * phys_const->const_proton_mass) { + + xp->sf_data.SFR = hydro_get_mass(p) / dt_star; + return; + } + + /* Pressure on the effective EOS for this particle */ + const double pressure = EOS_pressure(n_H, starform); + + /* Calculate the specific star formation rate */ + double SFRpergasmass; + if (hydro_get_physical_density(p, cosmo) < + starform->KS_high_den_thresh * phys_const->const_proton_mass) { + + SFRpergasmass = + starform->SF_normalization * pow(pressure, starform->SF_power_law); + + } else { + + SFRpergasmass = starform->SF_high_den_normalization * + pow(pressure, starform->SF_high_den_power_law); + } + + /* Store the SFR */ + xp->sf_data.SFR = SFRpergasmass * hydro_get_mass(p); +} + +/** + * @brief Decides whether a particle should be converted into a + * star or not. + * + * Equation 21 of Schaye & Dalla Vecchia 2008. + * + * @param p The #part. + * @param xp The #xpart. + * @param starform The properties of the star formation model. + * @param e The #engine (for random numbers). + * @param dt_star The time-step of this particle + * @return 1 if a conversion should be done, 0 otherwise. + */ +INLINE static int star_formation_should_convert_to_star( + const struct part* p, const struct xpart* xp, + const struct star_formation* starform, const struct engine* e, + const double dt_star) { + + /* Calculate the propability of forming a star */ + const double prob = xp->sf_data.SFR * dt_star / hydro_get_mass(p); + + /* Get a unique random number between 0 and 1 for star formation */ + const double random_number = + random_unit_interval(p->id, e->ti_current, random_number_star_formation); + + /* Have we been lucky and need to form a star? */ + return (prob > random_number); +} + +/** + * @brief Update the SF properties of a particle that is not star forming. + * + * @param p The #part. + * @param xp The #xpart. + * @param e The #engine. + * @param starform The properties of the star formation model. + * @param with_cosmology Are we running with cosmology switched on? + */ +INLINE static void star_formation_update_part_not_SFR( + struct part* p, struct xpart* xp, const struct engine* e, + const struct star_formation* starform, const int with_cosmology) { + + /* Check if it is the first time steps after star formation */ + if (xp->sf_data.SFR > 0.f) { + + /* Record the current time as an indicator of when this particle was last + star-forming. */ + if (with_cosmology) { + xp->sf_data.SFR = -e->cosmology->a; + } else { + xp->sf_data.SFR = -e->time; + } + } +} + +/** + * @brief Copies the properties of the gas particle over to the + * star particle + * + * @param e The #engine + * @param p the gas particles. + * @param xp the additional properties of the gas particles. + * @param sp the new created star particle with its properties. + * @param starform the star formation law properties to use. + * @param phys_const the physical constants in internal units. + * @param cosmo the cosmological parameters and properties. + * @param with_cosmology if we run with cosmology. + */ +INLINE static void star_formation_copy_properties( + const struct part* p, const struct xpart* xp, struct spart* sp, + const struct engine* e, const struct star_formation* starform, + const struct cosmology* cosmo, const int with_cosmology) { + + /* Store the current mass */ + sp->mass = hydro_get_mass(p); + + /* Store the current mass as the initial mass */ + sp->mass_init = hydro_get_mass(p); + + /* Store either the birth_scale_factor or birth_time depending */ + if (with_cosmology) { + sp->birth_scale_factor = cosmo->a; + } else { + sp->birth_time = e->time; + } + + /* Store the chemistry struct in the star particle */ + sp->chemistry_data = p->chemistry_data; + + /* Store the tracers data */ + sp->tracers_data = xp->tracers_data; + + /* Store the birth density in the star particle */ + sp->birth_density = hydro_get_physical_density(p, cosmo); +} + +/** + * @brief initialization of the star formation law + * + * @param parameter_file The parsed parameter file + * @param phys_const Physical constants in internal units + * @param us The current internal system of units. + * @param hydro_props The propertis of the hydro model. + * @param starform the star formation law properties to initialize + */ +INLINE static void starformation_init_backend( + struct swift_params* parameter_file, const struct phys_const* phys_const, + const struct unit_system* us, const struct hydro_props* hydro_props, + struct star_formation* starform) { + + /* Get the Gravitational constant */ + const double G_newton = phys_const->const_newton_G; + + /* Initial Hydrogen abundance (mass fraction) */ + const double X_H = hydro_props->hydrogen_mass_fraction; + + /* Mean molecular weight assuming neutral gas */ + const double mean_molecular_weight = hydro_props->mu_neutral; + + /* Get the surface density unit Msun / pc^2 in internal units */ + const double Msun_per_pc2 = + phys_const->const_solar_mass / + (phys_const->const_parsec * phys_const->const_parsec); + + /* Get the SF surface density unit Msun / kpc^2 / yr in internal units */ + const double kpc = 1000. * phys_const->const_parsec; + const double Msun_per_kpc2_per_year = + phys_const->const_solar_mass / (kpc * kpc) / phys_const->const_year; + + /* Conversion of number density from cgs */ + const double number_density_from_cgs = + 1. / units_cgs_conversion_factor(us, UNIT_CONV_NUMBER_DENSITY); + + /* Quantities that have to do with the Normal Kennicutt- + * Schmidt law will be read in this part of the code*/ + + /* Load the equation of state for this model */ + starform->EOS_polytropic_index = parser_get_param_double( + parameter_file, "EAGLEStarFormation:EOS_gamma_effective"); + starform->EOS_temperature_norm_K = parser_get_param_double( + parameter_file, "EAGLEStarFormation:EOS_temperature_norm_K"); + starform->EOS_density_norm_HpCM3 = parser_get_param_double( + parameter_file, "EAGLEStarFormation:EOS_density_norm_H_p_cm3"); + starform->EOS_density_c = + starform->EOS_density_norm_HpCM3 * number_density_from_cgs; + starform->EOS_density_c_inv = 1. / starform->EOS_density_c; + + /* Calculate the EOS pressure normalization */ + starform->EOS_pressure_c = + starform->EOS_density_c * starform->EOS_temperature_norm_K * + phys_const->const_boltzmann_k / mean_molecular_weight / X_H; + + /* Normalisation of the temperature in the EOS calculatio */ + starform->EOS_temperature_c = + starform->EOS_pressure_c / phys_const->const_boltzmann_k; + starform->EOS_temperature_c *= + pow(starform->EOS_density_c, starform->EOS_polytropic_index); + + /* Read the critical density contrast from the parameter file*/ + starform->min_over_den = parser_get_param_double( + parameter_file, "EAGLEStarFormation:KS_min_over_density"); + + /* Read the gas fraction from the file */ + starform->fgas = parser_get_opt_param_double( + parameter_file, "EAGLEStarFormation:gas_fraction", 1.); + + /* Read the Kennicutt-Schmidt power law exponent */ + starform->KS_power_law = + parser_get_param_double(parameter_file, "EAGLEStarFormation:KS_exponent"); + + /* Calculate the power law of the corresponding star formation Schmidt law */ + starform->SF_power_law = (starform->KS_power_law - 1.) / 2.; + + /* Read the normalization of the KS law in KS law units */ + starform->KS_normalization_MSUNpYRpKPC2 = parser_get_param_double( + parameter_file, "EAGLEStarFormation:KS_normalisation"); + + /* Convert to internal units */ + starform->KS_normalization = + starform->KS_normalization_MSUNpYRpKPC2 * Msun_per_kpc2_per_year; + + /* Calculate the starformation pre-factor (eq. 12 of Schaye & Dalla Vecchia + * 2008) */ + starform->SF_normalization = + starform->KS_normalization * pow(Msun_per_pc2, -starform->KS_power_law) * + pow(hydro_gamma * starform->fgas / G_newton, starform->SF_power_law); + + /* Read the high density Kennicutt-Schmidt power law exponent */ + starform->KS_high_den_power_law = parser_get_param_double( + parameter_file, "EAGLEStarFormation:KS_high_density_exponent"); + + /* Calculate the SF high density power law */ + starform->SF_high_den_power_law = (starform->KS_high_den_power_law - 1.) / 2.; + + /* Read the high density criteria for the KS law in number density per cm^3 */ + starform->KS_high_den_thresh_HpCM3 = parser_get_param_double( + parameter_file, "EAGLEStarFormation:KS_high_density_threshold_H_p_cm3"); + + /* Transform the KS high density criteria to simulation units */ + starform->KS_high_den_thresh = + starform->KS_high_den_thresh_HpCM3 * number_density_from_cgs; + + /* Pressure at the high-density threshold */ + const double EOS_high_den_pressure = + EOS_pressure(starform->KS_high_den_thresh, starform); + + /* Calculate the KS high density normalization + * We want the SF law to be continous so the normalisation of the second + * power-law is the value of the first power-law at the high-density threshold + */ + starform->KS_high_den_normalization = + starform->KS_normalization * + pow(Msun_per_pc2, + starform->KS_high_den_power_law - starform->KS_power_law) * + pow(hydro_gamma * EOS_high_den_pressure * starform->fgas / G_newton, + (starform->KS_power_law - starform->KS_high_den_power_law) * 0.5f); + + /* Calculate the SF high density normalization */ + starform->SF_high_den_normalization = + starform->KS_high_den_normalization * + pow(Msun_per_pc2, -starform->KS_high_den_power_law) * + pow(hydro_gamma * starform->fgas / G_newton, + starform->SF_high_den_power_law); + + /* Get the maximum physical density for SF */ + starform->max_gas_density_HpCM3 = parser_get_opt_param_double( + parameter_file, "EAGLEStarFormation:KS_max_density_threshold_H_p_cm3", + FLT_MAX); + + /* Convert the maximum physical density to internal units */ + starform->max_gas_density = + starform->max_gas_density_HpCM3 * number_density_from_cgs; + + starform->temperature_margin_threshold_dex = parser_get_opt_param_double( + parameter_file, "EAGLEStarFormation:KS_temperature_margin_dex", FLT_MAX); + + starform->ten_to_temperature_margin_threshold_dex = + exp10(starform->temperature_margin_threshold_dex); + + /* Read the normalization of the metallicity dependent critical + * density*/ + starform->density_threshold_HpCM3 = parser_get_param_double( + parameter_file, "EAGLEStarFormation:threshold_norm_H_p_cm3"); + + /* Convert to internal units */ + starform->density_threshold = + starform->density_threshold_HpCM3 * number_density_from_cgs; + + /* Read the scale metallicity Z0 */ + starform->Z0 = parser_get_param_double(parameter_file, + "EAGLEStarFormation:threshold_Z0"); + starform->Z0_inv = 1. / starform->Z0; + + /* Read the power law of the critical density scaling */ + starform->n_Z0 = parser_get_param_double( + parameter_file, "EAGLEStarFormation:threshold_slope"); + + /* Read the maximum allowed density for star formation */ + starform->density_threshold_max_HpCM3 = parser_get_param_double( + parameter_file, "EAGLEStarFormation:threshold_max_density_H_p_cm3"); + + /* Convert to internal units */ + starform->density_threshold_max = + starform->density_threshold_max_HpCM3 * number_density_from_cgs; +} + +/** + * @brief Prints the used parameters of the star formation law + * + * @param starform the star formation law properties. + * */ +INLINE static void starformation_print_backend( + const struct star_formation* starform) { + + message("Star formation law is EAGLE (Schaye & Dalla Vecchia 2008)"); + message( + "With properties: normalization = %e Msun/kpc^2/yr, slope of the" + "Kennicutt-Schmidt law = %e and gas fraction = %e ", + starform->KS_normalization_MSUNpYRpKPC2, starform->KS_power_law, + starform->fgas); + message("At densities of %e H/cm^3 the slope changes to %e.", + starform->KS_high_den_thresh_HpCM3, starform->KS_high_den_power_law); + message( + "The effective equation of state is given by: polytropic " + "index = %e , normalization density = %e #/cm^3 and normalization " + "temperature = %e K", + starform->EOS_polytropic_index, starform->EOS_density_norm_HpCM3, + starform->EOS_temperature_norm_K); + message("Density threshold follows Schaye (2004)"); + message( + "the normalization of the density threshold is given by" + " %e #/cm^3, with metallicity slope of %e, and metallicity normalization" + " of %e, the maximum density threshold is given by %e #/cm^3", + starform->density_threshold_HpCM3, starform->n_Z0, starform->Z0, + starform->density_threshold_max_HpCM3); + message("Temperature threshold is given by Dalla Vecchia and Schaye (2012)"); + message("The temperature threshold offset from the EOS is given by: %e dex", + starform->temperature_margin_threshold_dex); + message("Running with a maximum gas density given by: %e #/cm^3", + starform->max_gas_density_HpCM3); +} + +#endif /* SWIFT_EAGLE_STAR_FORMATION_H */ diff --git a/src/star_formation/EAGLE/star_formation_io.h b/src/star_formation/EAGLE/star_formation_io.h new file mode 100644 index 0000000000000000000000000000000000000000..cee96326e458d0581af6e62e452ac433dcf407bd --- /dev/null +++ b/src/star_formation/EAGLE/star_formation_io.h @@ -0,0 +1,47 @@ +/******************************************************************************* + * This file is part of SWIFT. + * Copyright (c) 2018 Folkert Nobels (nobels@strw.leidenuniv.nl) + * + * 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_STAR_FORMATION_EAGLE_IO_H +#define SWIFT_STAR_FORMATION_EAGLE_IO_H + +/* Config parameters. */ +#include "../config.h" + +/* Local includes */ +#include "io_properties.h" + +/** + * @brief Specifies which particle fields to write to a dataset + * + * @param parts The particle array. + * @param xparts The extended data particle array. + * @param list The list of i/o properties to write. + * + * @return Returns the number of fields to write. + */ +__attribute__((always_inline)) INLINE static int star_formation_write_particles( + const struct part* parts, const struct xpart* xparts, + struct io_props* list) { + + list[0] = + io_make_output_field("SFR", FLOAT, 1, UNIT_CONV_SFR, xparts, sf_data.SFR); + + return 1; +} + +#endif /* SWIFT_STAR_FORMATION_EAGLE_IO_H */ diff --git a/src/star_formation/EAGLE/star_formation_struct.h b/src/star_formation/EAGLE/star_formation_struct.h new file mode 100644 index 0000000000000000000000000000000000000000..41247e160a3eddbc9184c59b67cfa2a1d7259a05 --- /dev/null +++ b/src/star_formation/EAGLE/star_formation_struct.h @@ -0,0 +1,32 @@ +/******************************************************************************* + * This file is part of SWIFT. + * Copyright (c) 2018 Folkert Nobels (nobels@strw.leidenuniv.nl) + * + * 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_EAGLE_STAR_FORMATION_STRUCT_H +#define SWIFT_EAGLE_STAR_FORMATION_STRUCT_H + +/** + * @brief Star-formation-related properties stored in the extended particle + * data. + */ +struct star_formation_xpart_data { + + /*! Star formation rate */ + float SFR; +}; + +#endif /* SWIFT_EAGLE_STAR_FORMATION_STRUCT_H */ diff --git a/src/star_formation/none/star_formation.h b/src/star_formation/none/star_formation.h new file mode 100644 index 0000000000000000000000000000000000000000..093c4118601ec79c4f55646975f0505b8357afa6 --- /dev/null +++ b/src/star_formation/none/star_formation.h @@ -0,0 +1,160 @@ +/******************************************************************************* + * This file is part of SWIFT. + * Copyright (c) 2018 Folkert Nobels (nobels@strw.leidenuniv.nl) + * + * 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_NONE_STAR_FORMATION_H +#define SWIFT_NONE_STAR_FORMATION_H + +/* Local includes */ +#include "cosmology.h" +#include "error.h" +#include "hydro_properties.h" +#include "parser.h" +#include "part.h" +#include "physical_constants.h" +#include "units.h" + +/* Starformation struct */ +struct star_formation {}; + +/** + * @brief Calculate if the gas has the potential of becoming + * a star. + * + * No star formation should occur, so return 0. + * + * @param starform the star formation law properties to use. + * @param p the gas particles. + * @param xp the additional properties of the gas particles. + * @param phys_const the physical constants in internal units. + * @param cosmo the cosmological parameters and properties. + * @param hydro_props The properties of the hydro scheme. + * @param us The internal system of units. + * @param cooling The cooling data struct. + * + */ +INLINE static int star_formation_is_star_forming( + const struct part* restrict p, const struct xpart* restrict xp, + const struct star_formation* starform, const struct phys_const* phys_const, + const struct cosmology* cosmo, + const struct hydro_props* restrict hydro_props, + const struct unit_system* restrict us, + const struct cooling_function_data* restrict cooling) { + + return 0; +} + +/** + * @brief Compute the star-formation rate of a given particle and store + * it into the #xpart. + * + * Nothing to do here. + * + * @param p #part. + * @param xp the #xpart. + * @param starform the star formation law properties to use + * @param phys_const the physical constants in internal units. + * @param cosmo the cosmological parameters and properties. + * @param dt_star The time-step of this particle. + */ +INLINE static void star_formation_compute_SFR( + const struct part* restrict p, struct xpart* restrict xp, + const struct star_formation* starform, const struct phys_const* phys_const, + const struct cosmology* cosmo, const double dt_star) {} + +/** + * @brief Decides whether a particle should be converted into a + * star or not. + * + * No SF should occur, so return 0. + * + * @param p The #part. + * @param xp The #xpart. + * @param starform The properties of the star formation model. + * @param e The #engine (for random numbers). + * @param dt_star The time-step of this particle + * @return 1 if a conversion should be done, 0 otherwise. + */ +INLINE static int star_formation_should_convert_to_star( + const struct part* p, const struct xpart* xp, + const struct star_formation* starform, const struct engine* e, + const double dt_star) { + + return 0; +} + +/** + * @brief Update the SF properties of a particle that is not star forming. + * + * Nothing to do here. + * + * @param p The #part. + * @param xp The #xpart. + * @param e The #engine. + * @param starform The properties of the star formation model. + * @param with_cosmology Are we running with cosmology switched on? + */ +INLINE static void star_formation_update_part_not_SFR( + struct part* p, struct xpart* xp, const struct engine* e, + const struct star_formation* starform, const int with_cosmology) {} + +/** + * @brief Copies the properties of the gas particle over to the + * star particle. + * + * Nothing to do here. + * + * @param e The #engine + * @param p the gas particles. + * @param xp the additional properties of the gas particles. + * @param sp the new created star particle with its properties. + * @param starform the star formation law properties to use. + * @param phys_const the physical constants in internal units. + * @param cosmo the cosmological parameters and properties. + * @param with_cosmology if we run with cosmology. + */ +INLINE static void star_formation_copy_properties( + const struct part* p, const struct xpart* xp, struct spart* sp, + const struct engine* e, const struct star_formation* starform, + const struct cosmology* cosmo, const int with_cosmology) {} + +/** + * @brief initialization of the star formation law + * + * @param parameter_file The parsed parameter file + * @param phys_const Physical constants in internal units + * @param us The current internal system of units + * @param starform the star formation law properties to initialize + * + */ +INLINE static void starformation_init_backend( + struct swift_params* parameter_file, const struct phys_const* phys_const, + const struct unit_system* us, const struct hydro_props* hydro_props, + const struct star_formation* starform) {} + +/** + * @brief Prints the used parameters of the star formation law + * + * @param starform the star formation law properties. + */ +INLINE static void starformation_print_backend( + const struct star_formation* starform) { + + message("Star formation law is 'No Star Formation'"); +} + +#endif /* SWIFT_NONE_STAR_FORMATION_H */ diff --git a/src/star_formation/none/star_formation_io.h b/src/star_formation/none/star_formation_io.h new file mode 100644 index 0000000000000000000000000000000000000000..b271926f915279b681aac8348a0e375083901deb --- /dev/null +++ b/src/star_formation/none/star_formation_io.h @@ -0,0 +1,44 @@ +/******************************************************************************* + * This file is part of SWIFT. + * Copyright (c) 2018 Folkert Nobels (nobels@strw.leidenuniv.nl) + * + * 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_STAR_FORMATION_NONE_IO_H +#define SWIFT_STAR_FORMATION_NONE_IO_H + +/* Config parameters. */ +#include "../config.h" + +/* Local includes */ +#include "io_properties.h" + +/** + * @brief Specifies which particle fields to write to a dataset + * + * @param parts The particle array. + * @param xparts The extended data particle array. + * @param list The list of i/o properties to write. + * + * @return Returns the number of fields to write. + */ +__attribute__((always_inline)) INLINE static int star_formation_write_particles( + const struct part* parts, const struct xpart* xparts, + struct io_props* list) { + + return 0; +} + +#endif /* SWIFT_STAR_FORMATION_NONE_IO_H */ diff --git a/src/star_formation/none/star_formation_struct.h b/src/star_formation/none/star_formation_struct.h new file mode 100644 index 0000000000000000000000000000000000000000..27a2adaf83d0a02a0d08e7eef8b45bea630689e4 --- /dev/null +++ b/src/star_formation/none/star_formation_struct.h @@ -0,0 +1,28 @@ +/******************************************************************************* + * This file is part of SWIFT. + * Copyright (c) 2018 Folkert Nobels (nobels@strw.leidenuniv.nl) + * + * 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_NONE_STAR_FORMATION_STRUCT_H +#define SWIFT_NONE_STAR_FORMATION_STRUCT_H + +/** + * @brief Star-formation-related properties stored in the extended particle + * data. + */ +struct star_formation_xpart_data {}; + +#endif /* SWIFT_NONE_STAR_FORMATION_STRUCT_H */ diff --git a/src/star_formation_io.h b/src/star_formation_io.h new file mode 100644 index 0000000000000000000000000000000000000000..248866c513e405b80f974d4932f02d3c707785ee --- /dev/null +++ b/src/star_formation_io.h @@ -0,0 +1,39 @@ +/******************************************************************************* + * This file is part of SWIFT. + * Copyright (c) 2018 Folkert Nobels (nobels@strw.leidenuniv.nl) + * + * 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_STAR_FORMATION_IO_H +#define SWIFT_STAR_FORMATION_IO_H + +/** + * @file src/star_formation_io.h + * @brief Branches between the i/o routines for the SF code. + */ + +/* Config parameters. */ +#include "../config.h" + +/* Import the right cooling definition */ +#if defined(STAR_FORMATION_NONE) +#include "./star_formation/none/star_formation_io.h" +#elif defined(STAR_FORMATION_EAGLE) +#include "./star_formation/EAGLE/star_formation_io.h" +#else +#error "Invalid choice of star formation model." +#endif + +#endif /* SWIFT_STAR_FORMATION_IO_H */ diff --git a/src/star_formation_struct.h b/src/star_formation_struct.h new file mode 100644 index 0000000000000000000000000000000000000000..3e9859cfb650ddd370c6acce282084b7eba6bf82 --- /dev/null +++ b/src/star_formation_struct.h @@ -0,0 +1,39 @@ +/******************************************************************************* + * This file is part of SWIFT. + * Copyright (c) 2019 Folkert Nobels (nobels@strw.leidenuniv.nl) + * + * 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_STAR_FORMATION_STRUCT_H +#define SWIFT_STAR_FORMATION_STRUCT_H + +/** + * @file src/star_formation_struct.h + * @brief Branches between the different particle data SF tracers + */ + +/* Config parameters. */ +#include "../config.h" + +/* Import the right cooling definition */ +#if defined(STAR_FORMATION_NONE) +#include "./star_formation/none/star_formation_struct.h" +#elif defined(STAR_FORMATION_EAGLE) +#include "./star_formation/EAGLE/star_formation_struct.h" +#else +#error "Invalid choice of star formation structure." +#endif + +#endif /* SWIFT_STAR_FORMATION_STRUCT_H */ diff --git a/src/stars.h b/src/stars.h index 3e921239a29d862aba998c138623eb1cb81a37b9..fc7ee74d3a2cae91ee209c4008eee4d5dd0f375e 100644 --- a/src/stars.h +++ b/src/stars.h @@ -22,9 +22,18 @@ /* Config parameters. */ #include "../config.h" -/* So far only one model here */ -/* Straight-forward import */ +/* Select the correct star model */ +#if defined(STARS_NONE) #include "./stars/Default/stars.h" #include "./stars/Default/stars_iact.h" +#elif defined(STARS_EAGLE) +#include "./stars/EAGLE/stars.h" +#include "./stars/EAGLE/stars_iact.h" +#elif defined(STARS_GEAR) +#include "./stars/GEAR/stars.h" +#include "./stars/GEAR/stars_iact.h" +#else +#error "Invalid choice of star model" +#endif #endif diff --git a/src/stars/EAGLE/stars.h b/src/stars/EAGLE/stars.h new file mode 100644 index 0000000000000000000000000000000000000000..4acfef360cedf8993702d27a748a364288052410 --- /dev/null +++ b/src/stars/EAGLE/stars.h @@ -0,0 +1,151 @@ +/******************************************************************************* + * 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_EAGLE_STARS_H +#define SWIFT_EAGLE_STARS_H + +#include <float.h> +#include "minmax.h" + +/** + * @brief Computes the gravity time-step of a given star particle. + * + * @param sp Pointer to the s-particle data. + */ +__attribute__((always_inline)) INLINE static float stars_compute_timestep( + const struct spart* const sp) { + + return FLT_MAX; +} + +/** + * @brief Initialises the s-particles for the first time + * + * This function is called only once just after the ICs have been + * read in to do some conversions. + * + * @param sp The particle to act upon + */ +__attribute__((always_inline)) INLINE static void stars_first_init_spart( + struct spart* sp) { + + sp->time_bin = 0; + sp->birth_density = -1.f; +} + +/** + * @brief Prepares a s-particle for its interactions + * + * @param sp The particle to act upon + */ +__attribute__((always_inline)) INLINE static void stars_init_spart( + struct spart* sp) { + +#ifdef DEBUG_INTERACTIONS_STARS + for (int i = 0; i < MAX_NUM_OF_NEIGHBOURS_STARS; ++i) + sp->ids_ngbs_density[i] = -1; + sp->num_ngb_density = 0; +#endif + + sp->density.wcount = 0.f; + sp->density.wcount_dh = 0.f; +} + +/** + * @brief Sets the values to be predicted in the drifts to their values at a + * kick time + * + * @param sp The particle. + */ +__attribute__((always_inline)) INLINE static void stars_reset_predicted_values( + struct spart* restrict sp) {} + +/** + * @brief Finishes the calculation of (non-gravity) forces acting on stars + * + * Multiplies the forces and accelerations by the appropiate constants + * + * @param sp The particle to act upon + */ +__attribute__((always_inline)) INLINE static void stars_end_force( + struct spart* sp) {} + +/** + * @brief Kick the additional variables + * + * @param sp The particle to act upon + * @param dt The time-step for this kick + */ +__attribute__((always_inline)) INLINE static void stars_kick_extra( + struct spart* sp, float dt) {} + +/** + * @brief Finishes the calculation of density on stars + * + * @param sp The particle to act upon + * @param cosmo The current cosmological model. + */ +__attribute__((always_inline)) INLINE static void stars_end_density( + struct spart* sp, const struct cosmology* cosmo) { + + /* Some smoothing length multiples. */ + const float h = sp->h; + const float h_inv = 1.0f / h; /* 1/h */ + const float h_inv_dim = pow_dimension(h_inv); /* 1/h^d */ + const float h_inv_dim_plus_one = h_inv_dim * h_inv; /* 1/h^(d+1) */ + + /* Finish the calculation by inserting the missing h-factors */ + sp->density.wcount *= h_inv_dim; + sp->density.wcount_dh *= h_inv_dim_plus_one; +} + +/** + * @brief Sets all particle fields to sensible values when the #spart has 0 + * ngbs. + * + * @param sp The particle to act upon + * @param cosmo The current cosmological model. + */ +__attribute__((always_inline)) INLINE static void stars_spart_has_no_neighbours( + struct spart* restrict sp, const struct cosmology* cosmo) { + + /* Some smoothing length multiples. */ + const float h = sp->h; + const float h_inv = 1.0f / h; /* 1/h */ + const float h_inv_dim = pow_dimension(h_inv); /* 1/h^d */ + + /* Re-set problematic values */ + sp->density.wcount = kernel_root * h_inv_dim; + sp->density.wcount_dh = 0.f; +} + +/** + * @brief Evolve the stellar properties of a #spart. + * + * This function allows for example to compute the SN rate before sending + * this information to a different MPI rank. + * + * @param sp The particle to act upon + * @param cosmo The current cosmological model. + * @param stars_properties The #stars_props + */ +__attribute__((always_inline)) INLINE static void stars_evolve_spart( + struct spart* restrict sp, const struct stars_props* stars_properties, + const struct cosmology* cosmo) {} + +#endif /* SWIFT_EAGLE_STARS_H */ diff --git a/src/stars/EAGLE/stars_debug.h b/src/stars/EAGLE/stars_debug.h new file mode 100644 index 0000000000000000000000000000000000000000..6bdba45e3b090ccd2eb207bf92a374ce531ee3e0 --- /dev/null +++ b/src/stars/EAGLE/stars_debug.h @@ -0,0 +1,31 @@ +/******************************************************************************* + * 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_EAGLE_STARS_DEBUG_H +#define SWIFT_EAGLE_STARS_DEBUG_H + +__attribute__((always_inline)) INLINE static void stars_debug_particle( + const struct spart* p) { + printf( + "x=[%.3e,%.3e,%.3e], " + "v_full=[%.3e,%.3e,%.3e] p->mass=%.3e \n t_begin=%d, t_end=%d\n", + p->x[0], p->x[1], p->x[2], p->v_full[0], p->v_full[1], p->v_full[2], + p->mass, p->ti_begin, p->ti_end); +} + +#endif /* SWIFT_EAGLE_STARS_DEBUG_H */ diff --git a/src/stars/EAGLE/stars_iact.h b/src/stars/EAGLE/stars_iact.h new file mode 100644 index 0000000000000000000000000000000000000000..9e27f86028245a230cfd777dfc46da7b7d2f3915 --- /dev/null +++ b/src/stars/EAGLE/stars_iact.h @@ -0,0 +1,57 @@ +/** + * @brief Density interaction between two particles (non-symmetric). + * + * @param r2 Comoving square distance between the two particles. + * @param dx Comoving vector separating both particles (pi - pj). + * @param hi Comoving smoothing-length of particle i. + * @param hj Comoving smoothing-length of particle j. + * @param si First sparticle. + * @param pj Second particle (not updated). + * @param a Current scale factor. + * @param H Current Hubble parameter. + */ +__attribute__((always_inline)) INLINE static void +runner_iact_nonsym_stars_density(float r2, const float *dx, float hi, float hj, + struct spart *restrict si, + const struct part *restrict pj, float a, + float H) { + + float wi, wi_dx; + + /* Get r and 1/r. */ + const float r_inv = 1.0f / sqrtf(r2); + const float r = r2 * r_inv; + + /* Compute the kernel function */ + const float hi_inv = 1.0f / hi; + const float ui = r * hi_inv; + kernel_deval(ui, &wi, &wi_dx); + + /* Compute contribution to the number of neighbours */ + si->density.wcount += wi; + si->density.wcount_dh -= (hydro_dimension * wi + ui * wi_dx); + +#ifdef DEBUG_INTERACTIONS_STARS + /* Update ngb counters */ + if (si->num_ngb_density < MAX_NUM_OF_NEIGHBOURS_STARS) + si->ids_ngbs_density[si->num_ngb_density] = pj->id; + ++si->num_ngb_density; +#endif +} + +/** + * @brief Feedback interaction between two particles (non-symmetric). + * + * @param r2 Comoving square distance between the two particles. + * @param dx Comoving vector separating both particles (pi - pj). + * @param hi Comoving smoothing-length of particle i. + * @param hj Comoving smoothing-length of particle j. + * @param si First sparticle. + * @param pj Second particle (not updated). + * @param a Current scale factor. + * @param H Current Hubble parameter. + */ +__attribute__((always_inline)) INLINE static void +runner_iact_nonsym_stars_feedback(float r2, const float *dx, float hi, float hj, + struct spart *restrict si, + struct part *restrict pj, float a, float H) {} diff --git a/src/stars/EAGLE/stars_io.h b/src/stars/EAGLE/stars_io.h new file mode 100644 index 0000000000000000000000000000000000000000..64fde1a779966cc072a750fab89c74c5329bc03b --- /dev/null +++ b/src/stars/EAGLE/stars_io.h @@ -0,0 +1,209 @@ +/******************************************************************************* + * This file is part of SWIFT. + * Coypright (c) 2016 Matthieu Schaller (matthieu.schaller@durham.ac.uk) + * 2018 Folkert Nobels (nobels@strw.leidenuniv.nl) + * + * 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_EAGLE_STARS_IO_H +#define SWIFT_EAGLE_STARS_IO_H + +#include "io_properties.h" +#include "stars_part.h" + +/** + * @brief Specifies which s-particle fields to read from a dataset + * + * @param sparts The s-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 stars_read_particles(struct spart *sparts, + struct io_props *list, + int *num_fields) { + + /* Say how much we want to read */ + *num_fields = 5; + + /* List what we want to read */ + list[0] = io_make_input_field("Coordinates", DOUBLE, 3, COMPULSORY, + UNIT_CONV_LENGTH, sparts, x); + list[1] = io_make_input_field("Velocities", FLOAT, 3, COMPULSORY, + UNIT_CONV_SPEED, sparts, v); + list[2] = io_make_input_field("Masses", FLOAT, 1, COMPULSORY, UNIT_CONV_MASS, + sparts, mass); + list[3] = io_make_input_field("ParticleIDs", LONGLONG, 1, COMPULSORY, + UNIT_CONV_NO_UNITS, sparts, id); + list[4] = io_make_input_field("SmoothingLength", FLOAT, 1, OPTIONAL, + UNIT_CONV_LENGTH, sparts, h); +} + +/** + * @brief Specifies which s-particle fields to write to a dataset + * + * @param sparts The s-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 stars_write_particles(const struct spart *sparts, + struct io_props *list, + int *num_fields) { + + /* Say how much we want to write */ + *num_fields = 8; + + /* List what we want to write */ + list[0] = io_make_output_field("Coordinates", DOUBLE, 3, UNIT_CONV_LENGTH, + sparts, x); + list[1] = + io_make_output_field("Velocities", FLOAT, 3, UNIT_CONV_SPEED, sparts, v); + list[2] = + io_make_output_field("Masses", FLOAT, 1, UNIT_CONV_MASS, sparts, mass); + list[3] = io_make_output_field("ParticleIDs", LONGLONG, 1, UNIT_CONV_NO_UNITS, + sparts, id); + list[4] = io_make_output_field("SmoothingLength", FLOAT, 1, UNIT_CONV_LENGTH, + sparts, h); + list[5] = io_make_output_field("BirthDensity", FLOAT, 1, UNIT_CONV_DENSITY, + sparts, birth_density); + list[6] = io_make_output_field("Initial_Masses", FLOAT, 1, UNIT_CONV_MASS, + sparts, mass_init); + list[7] = io_make_output_field("Birth_time", FLOAT, 1, UNIT_CONV_TIME, sparts, + birth_time); +} + +/** + * @brief Initialize the global properties of the stars scheme. + * + * By default, takes the values provided by the hydro. + * + * @param sp The #stars_props. + * @param phys_const The physical constants in the internal unit system. + * @param us The internal unit system. + * @param params The parsed parameters. + * @param p The already read-in properties of the hydro scheme. + */ +INLINE static void stars_props_init(struct stars_props *sp, + const struct phys_const *phys_const, + const struct unit_system *us, + struct swift_params *params, + const struct hydro_props *p) { + + /* Kernel properties */ + sp->eta_neighbours = parser_get_opt_param_float( + params, "Stars:resolution_eta", p->eta_neighbours); + + /* Tolerance for the smoothing length Newton-Raphson scheme */ + sp->h_tolerance = + parser_get_opt_param_float(params, "Stars:h_tolerance", p->h_tolerance); + + /* Get derived properties */ + sp->target_neighbours = pow_dimension(sp->eta_neighbours) * kernel_norm; + const float delta_eta = sp->eta_neighbours * (1.f + sp->h_tolerance); + sp->delta_neighbours = + (pow_dimension(delta_eta) - pow_dimension(sp->eta_neighbours)) * + kernel_norm; + + /* Maximal smoothing length */ + sp->h_max = parser_get_opt_param_float(params, "Stars:h_max", p->h_max); + + /* Number of iterations to converge h */ + sp->max_smoothing_iterations = parser_get_opt_param_int( + params, "Stars:max_ghost_iterations", p->max_smoothing_iterations); + + /* Initialize with solar abundance */ + // sp->chemistry_data.smoothed_metal_mass_fraction_total = + + /* Time integration properties */ + const float max_volume_change = + parser_get_opt_param_float(params, "Stars:max_volume_change", -1); + if (max_volume_change == -1) + sp->log_max_h_change = p->log_max_h_change; + else + sp->log_max_h_change = logf(powf(max_volume_change, hydro_dimension_inv)); +} + +/** + * @brief Print the global properties of the stars scheme. + * + * @param sp The #stars_props. + */ +INLINE static void stars_props_print(const struct stars_props *sp) { + + /* Now stars */ + message("Stars kernel: %s with eta=%f (%.2f neighbours).", kernel_name, + sp->eta_neighbours, sp->target_neighbours); + + message("Stars relative tolerance in h: %.5f (+/- %.4f neighbours).", + sp->h_tolerance, sp->delta_neighbours); + + message( + "Stars integration: Max change of volume: %.2f " + "(max|dlog(h)/dt|=%f).", + pow_dimension(expf(sp->log_max_h_change)), sp->log_max_h_change); + + if (sp->h_max != FLT_MAX) + message("Maximal smoothing length allowed: %.4f", sp->h_max); + + message("Maximal iterations in ghost task set to %d", + sp->max_smoothing_iterations); +} + +#if defined(HAVE_HDF5) +INLINE static void stars_props_print_snapshot(hid_t h_grpstars, + const struct stars_props *sp) { + + io_write_attribute_s(h_grpstars, "Kernel function", kernel_name); + io_write_attribute_f(h_grpstars, "Kernel target N_ngb", + sp->target_neighbours); + io_write_attribute_f(h_grpstars, "Kernel delta N_ngb", sp->delta_neighbours); + io_write_attribute_f(h_grpstars, "Kernel eta", sp->eta_neighbours); + io_write_attribute_f(h_grpstars, "Smoothing length tolerance", + sp->h_tolerance); + io_write_attribute_f(h_grpstars, "Maximal smoothing length", sp->h_max); + io_write_attribute_f(h_grpstars, "Volume log(max(delta h))", + sp->log_max_h_change); + io_write_attribute_f(h_grpstars, "Volume max change time-step", + pow_dimension(expf(sp->log_max_h_change))); + io_write_attribute_i(h_grpstars, "Max ghost iterations", + sp->max_smoothing_iterations); +} +#endif + +/** + * @brief Write a #stars_props struct to the given FILE as a stream of bytes. + * + * @param p the struct + * @param stream the file stream + */ +INLINE static void stars_props_struct_dump(const struct stars_props *p, + FILE *stream) { + restart_write_blocks((void *)p, sizeof(struct stars_props), 1, stream, + "starsprops", "stars props"); +} + +/** + * @brief Restore a stars_props struct from the given FILE as a stream of + * bytes. + * + * @param p the struct + * @param stream the file stream + */ +INLINE static void stars_props_struct_restore(const struct stars_props *p, + FILE *stream) { + restart_read_blocks((void *)p, sizeof(struct stars_props), 1, stream, NULL, + "stars props"); +} + +#endif /* SWIFT_EAGLE_STAR_IO_H */ diff --git a/src/stars/EAGLE/stars_part.h b/src/stars/EAGLE/stars_part.h new file mode 100644 index 0000000000000000000000000000000000000000..3bf02f244b00e1fbb0420e13310b64713d3f60e0 --- /dev/null +++ b/src/stars/EAGLE/stars_part.h @@ -0,0 +1,141 @@ +/******************************************************************************* + * This file is part of SWIFT. + * Copyright (c) 2016 Matthieu Schaller (matthieu.schaller@durham.ac.uk) + * 2018 Folkert Nobels (nobels@strw.leidenuniv.nl) + * + * 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_EAGLE_STAR_PART_H +#define SWIFT_EAGLE_STAR_PART_H + +/* Some standard headers. */ +#include <stdlib.h> + +/* Read chemistry */ +#include "chemistry_struct.h" +#include "tracers_struct.h" + +/** + * @brief Particle fields for the star particles. + * + * All quantities related to gravity are stored in the associate #gpart. + */ +struct spart { + + /*! Particle ID. */ + long long id; + + /*! Pointer to corresponding gravity part. */ + struct gpart* gpart; + + /*! Particle position. */ + double x[3]; + + /* Offset between current position and position at last tree rebuild. */ + float x_diff[3]; + + /* Offset between current position and position at last tree rebuild. */ + float x_diff_sort[3]; + + /*! Particle velocity. */ + float v[3]; + + /*! Star mass */ + float mass; + + /*! Initial star mass */ + float mass_init; + + /*! Union for the birth time and birht scale factor */ + union { + /*! Birth time */ + float birth_time; + + /*! Birth scale factor */ + float birth_scale_factor; + }; + + /*! Birth density */ + float birth_density; + + /*! Tracer structure */ + struct tracers_xpart_data tracers_data; + + /* Particle cutoff radius. */ + float h; + + /*! Particle time bin */ + timebin_t time_bin; + + struct { + /* Number of neighbours. */ + float wcount; + + /* Number of neighbours spatial derivative. */ + float wcount_dh; + + } density; + + /*! Chemistry structure */ + struct chemistry_part_data chemistry_data; + +#ifdef SWIFT_DEBUG_CHECKS + + /* Time of the last drift */ + integertime_t ti_drift; + + /* Time of the last kick */ + integertime_t ti_kick; + +#endif + +#ifdef DEBUG_INTERACTIONS_STARS + /*! List of interacting particles in the density SELF and PAIR */ + long long ids_ngbs_density[MAX_NUM_OF_NEIGHBOURS_STARS]; + + /*! Number of interactions in the density SELF and PAIR */ + int num_ngb_density; +#endif + +} SWIFT_STRUCT_ALIGN; + +/** + * @brief Contains all the constants and parameters of the stars scheme + */ +struct stars_props { + + /*! Resolution parameter */ + float eta_neighbours; + + /*! Target weightd number of neighbours (for info only)*/ + float target_neighbours; + + /*! Smoothing length tolerance */ + float h_tolerance; + + /*! Tolerance on neighbour number (for info only)*/ + float delta_neighbours; + + /*! Maximal smoothing length */ + float h_max; + + /*! Maximal number of iterations to converge h */ + int max_smoothing_iterations; + + /*! Maximal change of h over one time-step */ + float log_max_h_change; +}; + +#endif /* SWIFT_EAGLE_STAR_PART_H */ diff --git a/src/stars_io.h b/src/stars_io.h index 046e90ee7570430ea25632539bc2cd642d4b52c0..c2a095c47c8d491fe6cf97d22c367d1e9d4a7fd6 100644 --- a/src/stars_io.h +++ b/src/stars_io.h @@ -19,8 +19,18 @@ #ifndef SWIFT_STARS_IO_H #define SWIFT_STARS_IO_H +#include "../config.h" #include "./const.h" +/* Load the correct star type */ +#if defined(STARS_NONE) #include "./stars/Default/stars_io.h" +#elif defined(STARS_EAGLE) +#include "./stars/EAGLE/stars_io.h" +#elif defined(STARS_GEAR) +#include "./stars/GEAR/stars_io.h" +#else +#error "Invalid choice of star model" +#endif #endif /* SWIFT_STARS_IO_H */ diff --git a/src/swift.h b/src/swift.h index 7279fc58b3b4ac0227c11b8a835c829df2ceb49c..ee27dacb41e573eb79e18825e26cc52bbb79f823 100644 --- a/src/swift.h +++ b/src/swift.h @@ -38,6 +38,7 @@ #include "debug.h" #include "dump.h" #include "engine.h" +#include "entropy_floor.h" #include "error.h" #include "gravity.h" #include "gravity_derivatives.h" @@ -66,6 +67,7 @@ #include "serial_io.h" #include "single_io.h" #include "space.h" +#include "star_formation.h" #include "stars.h" #include "stars_io.h" #include "task.h" diff --git a/src/timestep_limiter.h b/src/timestep_limiter.h index cfadc2e62a872a2d2a8a578fe6bb48fd24c5ba29..db5e044132370c273f66aefd8e2d116642b28a73 100644 --- a/src/timestep_limiter.h +++ b/src/timestep_limiter.h @@ -108,8 +108,8 @@ __attribute__((always_inline)) INLINE static integertime_t timestep_limit_part( dt_kick_corr = -(old_dti / 2) * time_base; } kick_part(p, xp, dt_kick_hydro, dt_kick_grav, dt_kick_therm, dt_kick_corr, - e->cosmology, e->hydro_properties, old_ti_beg + old_dti / 2, - old_ti_beg); + e->cosmology, e->hydro_properties, e->entropy_floor, + old_ti_beg + old_dti / 2, old_ti_beg); /* ...and apply the new one (dt is positiive) */ if (with_cosmology) { @@ -128,7 +128,7 @@ __attribute__((always_inline)) INLINE static integertime_t timestep_limit_part( dt_kick_corr = (new_dti / 2) * time_base; } kick_part(p, xp, dt_kick_hydro, dt_kick_grav, dt_kick_therm, dt_kick_corr, - e->cosmology, e->hydro_properties, new_ti_beg, + e->cosmology, e->hydro_properties, e->entropy_floor, new_ti_beg, new_ti_beg + new_dti / 2); /* Remember the old time-bin */ diff --git a/src/tracers/EAGLE/tracers_io.h b/src/tracers/EAGLE/tracers_io.h index 77824f0c374f01336b047f015539caf85fd62bff..0b0e372ffc35ec5729affd4f6a86e358c914ca6d 100644 --- a/src/tracers/EAGLE/tracers_io.h +++ b/src/tracers/EAGLE/tracers_io.h @@ -73,4 +73,26 @@ __attribute__((always_inline)) INLINE static int tracers_write_particles( return 2; } +__attribute__((always_inline)) INLINE static int tracers_write_sparticles( + const struct spart* sparts, struct io_props* list, + const int with_cosmology) { + + list[0] = io_make_output_field("Maximal Temperature", FLOAT, 1, + UNIT_CONV_TEMPERATURE, sparts, + tracers_data.maximum_temperature); + + if (with_cosmology) { + list[1] = io_make_output_field( + "Maximal Temperature scale-factor", FLOAT, 1, UNIT_CONV_NO_UNITS, + sparts, tracers_data.maximum_temperature_scale_factor); + + } else { + + list[1] = io_make_output_field("MaxTemperature time", FLOAT, 1, + UNIT_CONV_NO_UNITS, sparts, + tracers_data.maximum_temperature_time); + } + + return 2; +} #endif /* SWIFT_TRACERS_EAGLE_IO_H */ diff --git a/src/tracers/none/tracers_io.h b/src/tracers/none/tracers_io.h index 1f312ee903db3b56f0b293271e008575723598bd..b58e5f74aea211214b45c07668c03b461c088a99 100644 --- a/src/tracers/none/tracers_io.h +++ b/src/tracers/none/tracers_io.h @@ -16,8 +16,8 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. * ******************************************************************************/ -#ifndef SWIFT_TRACERS_EAGLE_IO_H -#define SWIFT_TRACERS_EAGLE_IO_H +#ifndef SWIFT_TRACERS_NONE_IO_H +#define SWIFT_TRACERS_NONE_IO_H /* Config parameters. */ #include "../config.h" @@ -57,4 +57,10 @@ __attribute__((always_inline)) INLINE static int tracers_write_particles( return 0; } -#endif /* SWIFT_TRACERS_EAGLE_IO_H */ +__attribute__((always_inline)) INLINE static int tracers_write_sparticles( + const struct spart* sparts, struct io_props* list, + const int with_cosmology) { + + return 0; +} +#endif /* SWIFT_TRACERS_NONE_IO_H */ diff --git a/src/units.c b/src/units.c index 066e524da0765840130065b626db63de2793c330..1194735aafd80d51897e4c4cb3e4b0976478145a 100644 --- a/src/units.c +++ b/src/units.c @@ -244,6 +244,7 @@ void units_get_base_unit_exponants_array(float baseUnitsExp[5], break; case UNIT_CONV_FREQUENCY: + case UNIT_CONV_SSFR: baseUnitsExp[UNIT_TIME] = -1.f; break; @@ -375,6 +376,11 @@ void units_get_base_unit_exponants_array(float baseUnitsExp[5], baseUnitsExp[UNIT_LENGTH] = -3.f; break; + case UNIT_CONV_SFR: + baseUnitsExp[UNIT_MASS] = 1.f; + baseUnitsExp[UNIT_TIME] = -1.f; + break; + default: error("Invalid choice of pre-defined units"); break; diff --git a/src/units.h b/src/units.h index 259cf73e1024c8ca605ced136e27a82cbb8a7a5e..62669425e52c4e39800330a4150259856d8fc0bb 100644 --- a/src/units.h +++ b/src/units.h @@ -94,7 +94,9 @@ enum unit_conversion_factor { UNIT_CONV_MAGNETIC_INDUCTANCE, UNIT_CONV_TEMPERATURE, UNIT_CONV_VOLUME, - UNIT_CONV_INV_VOLUME + UNIT_CONV_INV_VOLUME, + UNIT_CONV_SFR, + UNIT_CONV_SSFR }; void units_init_cgs(struct unit_system*); diff --git a/theory/Star_Formation/bibliography.bib b/theory/Star_Formation/bibliography.bib new file mode 100644 index 0000000000000000000000000000000000000000..95a3678d868a3229075bb98db1f1f6db3d9b05c3 --- /dev/null +++ b/theory/Star_Formation/bibliography.bib @@ -0,0 +1,86 @@ +@ARTICLE{schaye2008, + author = {{Schaye}, J. and {Dalla Vecchia}, C.}, + title = "{On the relation between the Schmidt and Kennicutt-Schmidt star formation laws and its implications for numerical simulations}", + journal = {\mnras}, +archivePrefix = "arXiv", + eprint = {0709.0292}, + keywords = {stars: formation , galaxies: evolution , galaxies: formation , galaxies: ISM}, + year = 2008, + month = jan, + volume = 383, + pages = {1210-1222}, + doi = {10.1111/j.1365-2966.2007.12639.x}, + adsurl = {http://adsabs.harvard.edu/abs/2008MNRAS.383.1210S}, + adsnote = {Provided by the SAO/NASA Astrophysics Data System} +} + +@ARTICLE{schaye2004, + author = {{Schaye}, J.}, + title = "{Star Formation Thresholds and Galaxy Edges: Why and Where}", + journal = {\apj}, + eprint = {astro-ph/0205125}, + keywords = {Galaxies: Evolution, Galaxies: Formation, Galaxies: ISM, ISM: Clouds, Stars: Formation}, + year = 2004, + month = jul, + volume = 609, + pages = {667-682}, + doi = {10.1086/421232}, + adsurl = {http://adsabs.harvard.edu/abs/2004ApJ...609..667S}, + adsnote = {Provided by the SAO/NASA Astrophysics Data System} +} + +@ARTICLE{kennicutt1998, + author = {{Kennicutt}, Jr., R.~C.}, + title = "{The Global Schmidt Law in Star-forming Galaxies}", + journal = {\apj}, + eprint = {astro-ph/9712213}, + keywords = {GALAXIES: EVOLUTION, GALAXIES: ISM, GALAXIES: SPIRAL, GALAXIES: STELLAR CONTENT, GALAXIES: STARBURST, STARS: FORMATION, Galaxies: Evolution, Galaxies: ISM, Galaxies: Spiral, Galaxies: Starburst, Galaxies: Stellar Content, Stars: Formation}, + year = 1998, + month = may, + volume = 498, + pages = {541-552}, + doi = {10.1086/305588}, + adsurl = {http://adsabs.harvard.edu/abs/1998ApJ...498..541K}, + adsnote = {Provided by the SAO/NASA Astrophysics Data System} +} + +@ARTICLE{dallavecchia2012, + author = {{Dalla Vecchia}, C. and {Schaye}, J.}, + title = "{Simulating galactic outflows with thermal supernova feedback}", + journal = {\mnras}, +archivePrefix = "arXiv", + eprint = {1203.5667}, + keywords = {methods: numerical, ISM: bubbles, ISM: jets and outflows, galaxies: evolution, galaxies: formation, galaxies: ISM }, + year = 2012, + month = oct, + volume = 426, + pages = {140-158}, + doi = {10.1111/j.1365-2966.2012.21704.x}, + adsurl = {http://adsabs.harvard.edu/abs/2012MNRAS.426..140D}, + adsnote = {Provided by the SAO/NASA Astrophysics Data System} +} + + +@ARTICLE{schaye2015, + author = {{Schaye}, J. and {Crain}, R.~A. and {Bower}, R.~G. and {Furlong}, M. and + {Schaller}, M. and {Theuns}, T. and {Dalla Vecchia}, C. and + {Frenk}, C.~S. and {McCarthy}, I.~G. and {Helly}, J.~C. and + {Jenkins}, A. and {Rosas-Guevara}, Y.~M. and {White}, S.~D.~M. and + {Baes}, M. and {Booth}, C.~M. and {Camps}, P. and {Navarro}, J.~F. and + {Qu}, Y. and {Rahmati}, A. and {Sawala}, T. and {Thomas}, P.~A. and + {Trayford}, J.}, + title = "{The EAGLE project: simulating the evolution and assembly of galaxies and their environments}", + journal = {\mnras}, +archivePrefix = "arXiv", + eprint = {1407.7040}, + keywords = {methods: numerical, galaxies: evolution, galaxies: formation, cosmology: theory}, + year = 2015, + month = jan, + volume = 446, + pages = {521-554}, + doi = {10.1093/mnras/stu2058}, + adsurl = {http://adsabs.harvard.edu/abs/2015MNRAS.446..521S}, + adsnote = {Provided by the SAO/NASA Astrophysics Data System} +} + + diff --git a/theory/Star_Formation/run.sh b/theory/Star_Formation/run.sh new file mode 100755 index 0000000000000000000000000000000000000000..7608ef7cb7e5ecc07a38a773e550cb42beec6fb7 --- /dev/null +++ b/theory/Star_Formation/run.sh @@ -0,0 +1,6 @@ +#!/bin/bash +echo "Generating PDF..." +pdflatex -jobname=starform starformation_standalone.tex +bibtex starform.aux +pdflatex -jobname=starform starformation_standalone.tex +pdflatex -jobname=starform starformation_standalone.tex diff --git a/theory/Star_Formation/starformation.tex b/theory/Star_Formation/starformation.tex new file mode 100644 index 0000000000000000000000000000000000000000..c1b8d511ce2f3cded2850a9b30a696dd76b8b47f --- /dev/null +++ b/theory/Star_Formation/starformation.tex @@ -0,0 +1,122 @@ +\section{Star Formation in EAGLE} + +In this section we will shortly explain how the star formation in EAGLE works. +The implemented star formation is based on the \citet{schaye2008}, instead of +the constant density threshold used by \citet{schaye2008}, a metallicity +dependent density threshold is used, following \citet{schaye2004}. An important +property of the implemented star formation law is the explicit reproducability +of the Kennicutt-Schmidt star formation law \citep{kennicutt1998}: +\begin{align} + \dot{\Sigma}_\star &= A \left( \frac{\Sigma}{1 ~\text{M}_\odot ~\text{pc}^{-2}} \right) +\end{align} + +\noindent In which $A$ is the normalization of the Kennicutt-Schmidt, $\dot{\Sigma}_\star$ +is the surface density of newly formed stars, $\Sigma$ is the gas surface +density and $n$ is the power law index. In the case of the star formation +implementation of \citet{schaye2008}, the star formation law is given by +a pressure law: + +\begin{align} +\dot{m}_\star &= m_g A ( 1~\text{M}_\odot~\text{pc}^{-2})^{-n} \left( +\frac{\gamma}{G} f_g P \right)^{(n-1)/2}. +\end{align} + +\noindent In which $m_g$ is the gas particle mass, $\gamma$ is the ratio of specific heats, +$G$ is the gravitational constant, $f_g$ is the mass fraction of gas (unity in +EAGLE), and $P$ is the total pressure of the gas particle. In this equation +$A$ and $n$ are directly constrainted from the observations of the Kennicutt- +Schmidt law so both variables do not require tuning. Further there are +two constrains on the over density which should be $\Delta > 57.7$ (why this +specific number? \citet{schaye2008} says $\Delta \approx 60$), and the +temperature of the gas should be atleast $T_\text{crit}<10^5 ~\text{K}$ + +Besides this it is required that there is an effective equation of state. +Specifically we could take this to be equal to: +\begin{align} + P &= P_\text{eos} (\rho) = P_\text{tot,c}\left( \frac{\rho_\text{g}}{\rho_\text{g,c}} \right)^{\gamma_\text{eff}}. +\end{align} +\noindent In which $\gamma_\text{eff}$ is the polytropic index. But the EAGLE +code just uses the EOS of the gas? + +\noindent Using this it is possible to calculate the propability that a gas particle is +converted to a star particle: +\begin{align} + \text{Prob.} = \text{min} \left( \frac{\dot{m}_\star \Delta t}{m_g}, 1 \right) + = \text{min} \left( A \left( 1 ~\text{M}_\odot ~\text{pc}^{-2} \right)^{-n} \left( \frac{\gamma}{G} f_g P_\text{tot} \right)^{(n-1)/2}, 1 \right). +\end{align} + +\noindent In general we use $A=1.515 \cdot 10^{-4}~\text{M}_\odot ~\text{yr}^{-1} ~\text{kpc}^{-2}$ +and $n=1.4$. In the case of high densities ($n_\text{H,thresh} > 10^3 ~\text{cm}^{-3}$), +the power law will be steaper and have a value of $n=2$ \citep{schaye2015}. This will also adjust +the normalization of the star formation law, both need to be equal at the +pressure with a corresponding density. This means we have: +\begin{align} +\begin{split} + A \left( 1 ~\text{M}_\odot ~\text{pc}^{-2} \right)^{-n} \left( \frac{\gamma}{G} f_g P_\text{tot} \right)^{(n-1)/2} \\ + = A_\text{high} \left( 1 ~\text{M}_\odot ~\text{pc}^{-2} \right)^{-n_\text{high}} \left( \frac{\gamma}{G} f_g P_\text{tot} \right)^{(n_\text{high}-1)/2}. +\end{split} +\end{align} +\begin{align} +A_\text{high} = A \left( 1 ~\text{M}_\odot ~\text{pc}^{-2} \right)^{n_\text{high}-n} \left( \frac{\gamma}{G} f_g P_\text{tot}(\rho_{hd}) \right)^{(n-n_\text{high})/2}. +\end{align} +In which $\rho_{hd}$ is the density at which both laws are equal. + +This is differently from the EAGLE code ($f_g=1$) which uses: +\begin{align} +A_\text{high} = A \left( \frac{\gamma}{G} P_\text{tot} (\rho_{hd}) \right)^{(n-n_\text{high})/2} . +\end{align} + +Besides this we also use the metallicity dependent density threshold given by \citep{schaye2004}: +\begin{align} +n^*_\text{H} (Z) &= n_\text{H,norm} \left( \frac{Z}{Z_0} \right)^{n_z}. +\end{align} +In which $n_\text{H,norm}$ is the normalization of the metallicity dependent +star formation law, $Z$ the metallicity, $Z_0$ the normalization metallicity, +and $n_Z$ the power law of the metallicity dependence on density. standard +values we take for the EAGLE are $n_\text{H,norm} = 0.1 ~\text{cm}^{-3}$, +$n_Z=-0.64$ and $Z_0 = 0.002$. Also we impose that the density threshold cannot +exceed the maximum value of $n_\text{H,max,norm}$ \citep{schaye2015}. + +For the initial pressure determination the EAGLE code uses (Explanation needed): +\begin{align} + P_\text{cgs} &= (\gamma -1) \frac{n_\text{EOS, norm} \cdot m_H}{X} T_{EOS,jeans} \cdot \frac{k_B}{1.22 \cdot (\gamma -1) m_H } \left( \frac{n_\text{highden}}{n_\text{norm,EOS}} \right)^{\gamma_\text{eff}}. +\end{align} + +To determine the pressure for the star formation law the EAGLE code uses the +physical pressure? Is this the effective EOS or the real EOS of the gas? + +Compared to the EAGLE code we can calculate a fraction of the calculations already +in the struct which are not depending on time, this may save some calculations. + +Besides this we also use the more extended temperature criteria proposed by +\citet{dallavecchia2012} that uses a temperature floor given by: +\begin{align} + \log_{10} T < \log_{10} T_\text{eos} + 0.5. +\end{align} + +\begin{table} +\begin{tabular}{l|l|l|l} +Variable & Parameter file name & Default value & unit \\ \hline +$A$ & SchmidtLawCoeff\_MSUNpYRpKPC2 & $1.515\cdot10^{-4}$ & $M_\odot ~yr^{-1} ~kpc^{-2}$ \\ +$n$ & SchmidtLawExponent & $1.4$ & none \\ +$\gamma$ & gamma & $\frac{5}{3}$ & none \\ +$G$ & No, in constants & - & - \\ +$f_g$ & fg & $1.$ & none \\ +$n_{high}$ & SchmidtLawHighDensExponent & $2.0$ & none \\ +$n_{H,thresh}$ & SchmidtLawHighDens\_thresh\_HpCM3 & $10^3$ & $cm^{-3}$ \\ +$n_{H,norm}$ & thresh\_norm\_HpCM3 & $.1$ & $cm^{-3}$ \\ +$Z_0$ & MetDep\_Z0 & $0.002$ & none \\ +$n_Z$ & MetDep\_SFthresh\_Slope & $-0.64$ & none \\ +$\Delta$ & thresh\_MinOverDens & $57.7$ & none \\ +$T_{crit}$ & thresh\_temp & $10^5$ & $K$ \\ +$n_{H,max,norm}$ & thresh\_max\_norm\_HpCM3 & 10.0 & $cm^{-3}$ +\end{tabular} +\end{table} + +Questions: +Is rho in part mass density or number density?? +Why is the cooling\_get\_temperature() depending on so many variables? +I would expect $P_\text{tot,c} = n k_B T$, but which $n$ and $T$? +Is Seed in the function or declared outside of function? +Correct Unit conversion? + diff --git a/theory/Star_Formation/starformation_standalone.tex b/theory/Star_Formation/starformation_standalone.tex new file mode 100644 index 0000000000000000000000000000000000000000..518179a393f7c35ce56091e6b74eaccb133c65de --- /dev/null +++ b/theory/Star_Formation/starformation_standalone.tex @@ -0,0 +1,43 @@ +\documentclass[fleqn, usenatbib, useAMS, a4paper]{mnras} +\usepackage{graphicx} +\usepackage{amsmath,paralist,xcolor,xspace,amssymb} +\usepackage{times} +\usepackage{comment} +\usepackage[super]{nth} + +\newcommand{\todo}[1]{{\textcolor{red}{#1}}} +\newcommand{\gadget}{{\sc Gadget}\xspace} +\newcommand{\swift}{{\sc Swift}\xspace} +\newcommand{\nbody}{$N$-body\xspace} +\newcommand{\Lag}{\mathcal{L}} + +%opening +\title{Star formation equations in SWIFT} +\author{Folkert Nobels} +\begin{document} + +\date{\today} + +\pagerange{\pageref{firstpage}--\pageref{lastpage}} \pubyear{2018} + +\maketitle + +\label{firstpage} + +\begin{abstract} +Making stars all over again. +\end{abstract} + +\begin{keywords} +\end{keywords} + +\input{starformation} + + + +\bibliographystyle{mnras} +\bibliography{./bibliography.bib} + +\label{lastpage} + +\end{document}