diff --git a/.circleci/config.yml b/.circleci/config.yml
index ddcb89c2e..6dfb38da1 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -215,13 +215,6 @@ commands:
export PYTEST_CODE_LINK_CHOICE="" # we skip test_code_examples.py
fi
- # configure variables for generating test answers
- if [ << parameters.generate >> == 'true' ]; then
- export GENERATE_PYGRACKLE_TEST_RESULTS=1
- else
- export GENERATE_PYGRACKLE_TEST_RESULTS=0
- fi
-
# actually execute the tests
if [ << parameters.omp >> == 'true' ]; then
export OMP_NUM_THREADS=4
@@ -229,8 +222,26 @@ commands:
make cxx_omp_example
./cxx_omp_example
make clean
- else
+ elif [ ! -f ./python/tests/conftest.py ]; then
+ # this is the old way to control the answer-test mode
+ # - We can stop supporting this case once the most recent gold
+ # standard tags a repository version containing conftest.py
+ if [ << parameters.generate >> == 'true' ]; then
+ export GENERATE_PYGRACKLE_TEST_RESULTS=1
+ else
+ export GENERATE_PYGRACKLE_TEST_RESULTS=0
+ fi
py.test python/tests
+ else
+ # ANSWER_DIR was picked to ensure that it matches up with the old
+ # hardcoded location (we can change it once the most recent gold
+ # standard tags a repository version containing conftest.py)
+ ANSWER_DIR=./python/tests/test_answers
+ if [ << parameters.generate >> == 'true' ]; then
+ py.test --answer-dir=${ANSWER_DIR} --answer-store python/tests
+ else
+ py.test --answer-dir=${ANSWER_DIR} python/tests
+ fi
fi
build-docs:
@@ -281,14 +292,14 @@ jobs:
build_kind: 'classic'
generate: 'true'
- - install-grackle:
- omp: 'true'
- classic_build: 'true'
- tag: $CIRCLE_BRANCH
+ # - install-grackle:
+ # omp: 'true'
+ # classic_build: 'true'
+ # tag: $CIRCLE_BRANCH
- - run-tests:
- omp: 'true'
- build_kind: 'classic'
+ # - run-tests:
+ # omp: 'true'
+ # build_kind: 'classic'
- install-grackle:
omp: 'false'
diff --git a/.readthedocs.yml b/.readthedocs.yml
index 6a44cb5d5..84e24dcf3 100644
--- a/.readthedocs.yml
+++ b/.readthedocs.yml
@@ -8,3 +8,7 @@ build:
python:
install:
- requirements: doc/source/requirements.txt
+
+sphinx:
+ # Path to your Sphinx configuration file.
+ configuration: doc/source/conf.py
diff --git a/doc/source/Python.rst b/doc/source/Python.rst
index 3f1938f28..81de6c997 100644
--- a/doc/source/Python.rst
+++ b/doc/source/Python.rst
@@ -185,8 +185,8 @@ a parcel of gas at constant density or in a free-fall model. Each example
will produce a figure as well as a dataset that can be loaded and analyzed
with `yt `__.
-Configuring the path to Grackle input data
-++++++++++++++++++++++++++++++++++++++++++
+Editable Install Requirement
+++++++++++++++++++++++++++++
All of the example scripts discussed below use the following line to
make a guess at where the Grackle input files are located.
@@ -195,19 +195,15 @@ make a guess at where the Grackle input files are located.
from pygrackle.utilities.data_path import grackle_data_dir
-This will typically work for any 'editable' Pygrackle installation
+This currently **ONLY** works for an 'editable' Pygrackle installation
(i.e., one installed with ``pip install -e .`` as directed
above). In this case, it will be assumed that the data files can be
found in a directory called ``input`` in the top level of the source
-repository. However, this will not work with non-editable
-installations. In this case you can use the ``GRACKLE_DATA_DIR``
-environment variable to set the path to the data. This will be picked
-up by the Python code above and the ``grackle_data_dir`` variable will
-contain the proper path.
+repository.
-.. code-block:: shell-session
+.. note::
- export GRACKLE_DATA_DIR=/path/to/data
+ `GitHub PR #235 `__ is a pending pull request that seeks to add functionality to make this work in a regular Pygrackle installation (i.e. a non-'editable' install).
Cooling Rate Figure Example
+++++++++++++++++++++++++++
diff --git a/doc/source/Testing.rst b/doc/source/Testing.rst
index f1c6302ae..ebce99067 100644
--- a/doc/source/Testing.rst
+++ b/doc/source/Testing.rst
@@ -26,8 +26,9 @@ the following:
Answer tests are those whose correct answers must be generated from a
prior, trusted version of Grackle (i.e., the "gold standard"). The
tests are first run using this trusted version to generate the
-results, then run again on the latest version to compate. These tests
-include:
+results (in *store-mode*), then run again on the latest version to
+compare (in *compare-mode*).
+These tests include:
- all code examples build, run, and return correct results
@@ -37,40 +38,51 @@ include:
- all grackle 'calculate' functions return correct results for sets
of random field values
-Tests Without Answer Verification
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+We refer to the location where the results of answer-tests are stored as the "answer-directory." This is an arbitrary user-specified location.
-If you only want to quickly verify that everything runs, you can skip
-generating the answer test results using the latest gold standard. To
-run this way, first set the ``GENERATE_PYGRACKLE_TEST_RESULTS``
-environment variable to 1.
+Quick Primer on the Test Runner's CLI
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-.. code-block:: shell-session
+By default, the pytest test-runner always runs all available test cases.
- ~ $ export GENERATE_PYGRACKLE_TEST_RESULTS=1
+ - The unit tests are **ALWAYS** available.
-This will tell the test suite to simply generate new answers and not
-compare with previously existing ones.
+ - By default, **all** answer-tests are fully disabled.
+ Command-line options make them available in *store-mode* or *compare-mode*.
+ The ``--answer-dir=`` flag is required for both modes; it specifies the path to the user's chosen "answer-directory" (where answer-tests results are stored/read-from).
+ The ``--answer-store`` flag enables *store-mode*, while its absence enables *compare-mode*.
-Once you have installed :ref:`pygrackle and the development
-dependencies `, the tests can be run from the **src**
-directory by typing ``make test``:
+*For contributors:* you may find pytest's `build-in command-line interface `__ useful during debugging (e.g. you can instruct pytest to only run a subset of all available tests).
-.. code-block:: shell-session
+.. _test_without_answer_verification:
- ~ $ cd grackle/src
- ~/grackle/src $ make test
+Tests Without Answer Verification
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+If you only want to quickly verify that everything runs, you can skip
+generating the answer test results using the latest gold standard.
-or from the **src/python** directory by typing ``py.test``:
+Once you have installed :ref:`pygrackle and the development dependencies `, this is relatively straight-forward.
+
+Simply invoke ``py.test`` from the **src/python** directory with the ``--answer-dir=`` option **and** the ``--answer-store`` option.
+For the former You can specify an arbitrary path where the test-answers will be recorded.
+A concrete example of what this looks like is shown down below.
.. code-block:: shell-session
~ $ cd grackle/src/python
- ~/grackle/src $ py.test
+ ~/grackle/src/python $ py.test --answer-dir=./my_test_answers --answer-store
+
+The above snippet instructs each answer-test to store the test result in the directory called **./my_test_answers**; an answer-test reports that it has "passed" as long as it is able to successfully store the result.
+After you run the test-suite, you can delete the **./my_test_answers** directory (since we don't actually care about the test results).
+
+When you launch the tests, the output will look like the following:
+
+.. code-block:: shell-session
==================================== test session starts ====================================
platform darwin -- Python 3.11.9, pytest-8.2.1, pluggy-1.5.0
- rootdir: /Users/britton/Documents/work/research/simulation/grackle/grackle-git/src
+ rootdir: /Users/britton/Documents/work/research/simulation/grackle/grackle-git/src/python
plugins: cov-5.0.0
collected 65 items
@@ -112,11 +124,18 @@ steps:
#. Re-compile the Grackle library and :ref:`re-install pygrackle
`.
-#. Set the ``GENERATE_PYGRACKLE_TEST_RESULTS`` environment variable to
- 1.
+#. Execute the test suite using command-line flags to instruct the test-runner to run answer tests in *store-mode*.
+ This was already illustrated :ref:`above `, we repeat the instructions here:
+
+ - Execute ``py.test`` from the **src/python** directory while specifing the path to the *answer-directory* with ``--answer-dir=`` **and** specifying the ``--answer-store`` option.
+
+ - Be aware, this will directly overwrite any files that were previously stored in the answer-dir.
+
+ - If we wanted to store the test-answers in **./my-test-answers**, we would invoke:
-#. Run the test suite as described above. This will create test result
- files in the directory **src/python/tests/test_answers**.
+ .. code-block:: shell-session
+
+ ~/grackle/src/python $ py.test --answer-dir=./my_test_answers --answer-store
#. Return to the branch of the repository you started with. If you just
cloned the main repository, this will be called 'main', in which
@@ -125,8 +144,16 @@ steps:
#. Re-compile the Grackle library and :ref:`re-install pygrackle
`.
-#. Set the ``GENERATE_PYGRACKLE_TEST_RESULTS`` environment variable to
- 0.
+#. Run the test suite again using a command-line flag to instruct the test runner to evaluate the answer-tests in *compare-mode*:
+
+ - you just need to specify the *answer-directory* path with ``--answer-dir=``.
+
+ - Do **NOT** pass the ``--answer-store`` flag.
+ The absence of this flag is how the test-runner knows to use *compare-mode*.
+ (If the flag were present, then the answer-tests would overwrite the answers)
+
+ - To compare against the results previously written to **./my-test-answers**, you would invoke:
+
+ .. code-block:: shell-session
-#. Run the test suite again. This time, the answer tests will be
- compared with the previously generated results.
+ ~/grackle/src/python $ py.test --answer-dir=./my_test_answers --answer-store
diff --git a/src/clib/CMakeLists.txt b/src/clib/CMakeLists.txt
index 669f50dde..880d2f01d 100644
--- a/src/clib/CMakeLists.txt
+++ b/src/clib/CMakeLists.txt
@@ -105,6 +105,7 @@ add_library(Grackle_Grackle
${CMAKE_CURRENT_BINARY_DIR}/auto_general.c
# Fortran Source Files
+ calc_all_tdust_gasgr_1d_g.F
calc_tdust_1d_g.F
calc_tdust_3d_g.F
calc_temp1d_cloudy_g.F
diff --git a/src/clib/Make.config.objects b/src/clib/Make.config.objects
index 78bb7eb68..1da4b50bb 100644
--- a/src/clib/Make.config.objects
+++ b/src/clib/Make.config.objects
@@ -40,6 +40,7 @@ OBJS_CONFIG_LIB = \
solve_rate_cool_g.lo \
update_UVbackground_rates.lo \
lookup_cool_rates0d.lo \
+ calc_all_tdust_gasgr_1d_g.lo \
calc_tdust_1d_g.lo \
calc_tdust_3d_g.lo \
calc_grain_size_increment_1d.lo \
diff --git a/src/clib/c_wrappers/wrap_interpolators_g.c b/src/clib/c_wrappers/wrap_interpolators_g.c
deleted file mode 100644
index 9509fd055..000000000
--- a/src/clib/c_wrappers/wrap_interpolators_g.c
+++ /dev/null
@@ -1,60 +0,0 @@
-#include "grackle_macros.h"
-
-// TODO: FORTRAN_NAME not needed for unit tests
-extern void FORTRAN_NAME(interpolate_1d_g)(double *input1,
- long long *gridDim,
- double *gridPar1, double *dgridPar1,
- long long *dataSize, double *dataField,
- double *value);
-
-extern void FORTRAN_NAME(interpolate_2d_g)(double *input1, double *input2,
- long long *gridDim,
- double *gridPar1, double *dgridPar1,
- double *gridPar2, double *dgridPar2,
- long long *dataSize, double *dataField,
- double *value);
-
-extern void FORTRAN_NAME(interpolate_3d_g)(double *input1, double *input2, double *input3,
- long long *gridDim,
- double *gridPar1, double *dgridPar1,
- double *gridPar2, double *dgridPar2,
- double *gridPar3, double *dgridPar3,
- long long *dataSize, double *dataField,
- double *value);
-
-extern void FORTRAN_NAME(interpolate_3dz_g)(double *input1, double *input2, double *input3,
- long long *gridDim,
- double *gridPar1, double *dgridPar1,
- double *gridPar2, long long *index2,
- double *gridPar3, double *dgridPar3,
- long long *dataSize, double *dataField,
- int *end_int,
- double *value);
-
-extern void FORTRAN_NAME(interpolate_2df3d_g)(double *input1, double *input3,
- long long *gridDim,
- double *gridPar1, double *dgridPar1,
- long long *index2,
- double *gridPar3, double *dgridPar3,
- long long *dataSize, double *dataField,
- double *value);
-
-extern void FORTRAN_NAME(interpolate_4d_g)(double *input1, double *input2, double *input3, double *input4,
- long long *gridDim,
- double *gridPar1, double *dgridPar1,
- double *gridPar2, double *dgridPar2,
- double *gridPar3, double *dgridPar3,
- double *gridPar4, double *dgridPar4,
- long long *dataSize, double *dataField,
- double *value);
-
-extern void FORTRAN_NAME(interpolate_5d_g)(double *input1, double *input2, double *input3, double *input4, double *input5,
- long long *gridDim,
- double *gridPar1, double *dgridPar1,
- double *gridPar2, double *dgridPar2,
- double *gridPar3, double *dgridPar3,
- double *gridPar4, double *dgridPar4,
- double *gridPar5, double *dgridPar5,
- long long *dataSize, double *dataField,
- double *value);
-
diff --git a/src/clib/calc_all_tdust_gasgr_1d_g.F b/src/clib/calc_all_tdust_gasgr_1d_g.F
new file mode 100644
index 000000000..7e5c10c75
--- /dev/null
+++ b/src/clib/calc_all_tdust_gasgr_1d_g.F
@@ -0,0 +1,353 @@
+ subroutine calc_all_tdust_gasgr_1d_g(in, jn, kn, nratec,
+ & idustfield, is, ie, j, k, fgr, gamma_isrfa,
+ & trad, gasgra, indixe, tdef, tgas, tdust,
+ & metallicity, dust2gas, nh, gasgr_tdust,
+ & itmask_metal,
+ & idspecies, itdmulti, gr_N, gr_Size, gr_dT,
+ & gr_Td, tSiM, tFeM, tMg2SiO4, tMgSiO3, tFe3O4,
+ & tAC, tSiO2D, tMgO, tFeS, tAl2O3, treforg,
+ & tvolorg, tH2Oice, gasgr2a, gamma_isrf2a,
+ & coolunit, gasgr, myisrf, sgSiM, sgFeM, sgMg2SiO4,
+ & sgMgSiO3, sgFe3O4, sgAC, sgSiO2D, sgMgO, sgFeS,
+ & sgAl2O3, sgreforg, sgvolorg, sgH2Oice, sgtot,
+ & alSiM, alFeM, alMg2SiO4, alMgSiO3, alFe3O4, alAC,
+ & alSiO2D, alMgO, alFeS, alAl2O3, alreforg,
+ & alvolorg, alH2Oice, altot, kpSiM, kpFeM,
+ & kpMg2SiO4, kpMgSiO3, kpFe3O4, kpAC, kpSiO2D,
+ & kpMgO, kpFeS, kpAl2O3, kpreforg, kpvolorg,
+ & kpH2Oice, kptot, gasSiM, gasFeM, gasMg2SiO4,
+ & gasMgSiO3, gasFe3O4, gasAC, gasSiO2D, gasMgO,
+ & gasFeS, gasAl2O3, gasreforg, gasvolorg,
+ & gasH2Oice
+ & )
+
+! PURPOSE:
+! Calculate all dust temperature(s) and the gas to grain heat
+! transfer rate(s) (the latter is commonly called gasgr)
+!
+! An argument could be made for directly using gasgr to compute
+! contributions to edot within this routine, rather than returning
+! the gasgr value(s). But that should be reconsidered in the future.
+!
+! We could significantly reduce the amount of buffer space allocated
+! within the routine. But, we will hold off on doing that until after
+! we have transcribed to C/C++
+!
+! INPUTS:
+! is,ie - start and end indicies of active region (zero-based!)
+!
+! PARAMETERS:
+!
+
+!-----------------------------------------------------------------------
+
+ implicit NONE
+#include "grackle_fortran_types.def"
+#include "phys_const.def"
+
+! Arguments
+
+ integer in, jn, kn, is, ie, j, k, nratec, idustfield
+
+ real*8 fgr
+ real*8 gasgra(nratec), gamma_isrfa
+
+! Parameters
+
+ real*8, parameter :: mh = mass_h !DPC
+
+! Locals
+
+ integer i
+ real*8 trad, coolunit
+
+! Slice locals
+
+ integer*8 indixe(in)
+ real*8 tdef(in), tgas(in), tdust(in), nh(in), metallicity(in),
+ & dust2gas(in)
+
+! Cooling/heating slice locals
+
+ real*8 gasgr(in), gasgr_tdust(in), myisrf(in)
+ integer idspecies, itdmulti
+! opacity table
+ integer gr_N(2), gr_Size
+ real*8 gr_dT, gr_Td(gr_N(2))
+! grain growth
+ real*8 sgSiM(in), sgFeM(in), sgMg2SiO4(in)
+ & , sgMgSiO3(in), sgFe3O4(in), sgAC(in)
+ & , sgSiO2D(in), sgMgO(in), sgFeS(in)
+ & , sgAl2O3(in)
+ & , sgreforg(in), sgvolorg(in), sgH2Oice(in)
+ & , sgtot(in)
+ real*8 alSiM(gr_N(2),in), alFeM(gr_N(2),in)
+ & , alMg2SiO4(gr_N(2),in), alMgSiO3(gr_N(2),in)
+ & , alFe3O4(gr_N(2),in), alAC(gr_N(2),in)
+ & , alSiO2D(gr_N(2),in), alMgO(gr_N(2),in)
+ & , alFeS(gr_N(2),in), alAl2O3(gr_N(2),in)
+ & , alreforg(gr_N(2),in)
+ & , alvolorg(gr_N(2),in), alH2Oice(gr_N(2),in)
+ & , altot(gr_N(2),in)
+ real*8 kpSiM(in), kpFeM(in), kpMg2SiO4(in)
+ & , kpMgSiO3(in), kpFe3O4(in), kpAC(in)
+ & , kpSiO2D(in), kpMgO(in), kpFeS(in)
+ & , kpAl2O3(in)
+ & , kpreforg(in), kpvolorg(in), kpH2Oice(in)
+ & , kptot(in)
+! grain temperature
+ real*8 tSiM(in), tFeM(in), tMg2SiO4(in)
+ & , tMgSiO3(in), tFe3O4(in), tAC(in)
+ & , tSiO2D(in), tMgO(in), tFeS(in)
+ & , tAl2O3(in)
+ & , treforg(in), tvolorg(in), tH2Oice(in)
+ real*8 gasgr2a(nratec), gamma_isrf2a
+ real*8 gasSiM(in), gasFeM(in), gasMg2SiO4(in)
+ & , gasMgSiO3(in), gasFe3O4(in), gasAC(in)
+ & , gasSiO2D(in), gasMgO(in), gasFeS(in)
+ & , gasAl2O3(in)
+ & , gasreforg(in), gasvolorg(in), gasH2Oice(in)
+ real*8 gasgr_tSiM(in), gasgr_tFeM(in), gasgr_tMg2SiO4(in)
+ & , gasgr_tMgSiO3(in), gasgr_tFe3O4(in), gasgr_tAC(in)
+ & , gasgr_tSiO2D(in), gasgr_tMgO(in), gasgr_tFeS(in)
+ & , gasgr_tAl2O3(in)
+ & , gasgr_treforg(in), gasgr_tvolorg(in), gasgr_tH2Oice(in)
+ real*8 mygisrf(in), fv2k, fac
+ real*8 gisrfSiM(in), gisrfFeM(in), gisrfMg2SiO4(in)
+ & , gisrfMgSiO3(in), gisrfFe3O4(in), gisrfAC(in)
+ & , gisrfSiO2D(in), gisrfMgO(in), gisrfFeS(in)
+ & , gisrfAl2O3(in)
+ & , gisrfreforg(in), gisrfvolorg(in), gisrfH2Oice(in)
+! Iteration mask
+
+ MASK_TYPE itmask_metal(in)
+
+ ! Calculate heating from interstellar radiation field
+ ! -> this is ONLY used when `itmask_metal .eq. MASK_TRUE`
+
+ do i = is+1, ie+1
+ if ( itmask_metal(i) .ne. MASK_FALSE ) then
+
+ if (idspecies .eq. 0 ) then
+ if (idustfield .gt. 0) then
+ mygisrf(i) = gamma_isrfa
+ & * fgr / dust2gas(i) * metallicity(i)
+ !! correct with the depletion or enhancement of condensation rate.
+ else
+ mygisrf(i) = gamma_isrfa
+ endif
+
+ else ! idspecies
+
+ if (itdmulti .eq. 0) then
+
+ mygisrf(i) = gamma_isrf2a * sgtot(i)
+ !! in UV, absorption coefficient Q ~ 1 (Goldsmith 2001)
+ !! so we use the geometrical cross-section of grains [cgs]
+
+ else
+
+ if (idspecies .gt. 0) then
+ gisrfMgSiO3 (i) = gamma_isrf2a * sgMgSiO3 (i)
+!! write(*,*) 'sil', d(i,j,k), gamma_isrf2a, sgMgSiO3(i)
+ gisrfAC (i) = gamma_isrf2a * sgAC (i)
+!! write(*,*) 'car', d(i,j,k), gamma_isrf2a, sgMgSiO3(i)
+ endif
+ if (idspecies .gt. 1) then
+ gisrfSiM (i) = gamma_isrf2a * sgSiM (i)
+ gisrfFeM (i) = gamma_isrf2a * sgFeM (i)
+ gisrfMg2SiO4 (i) = gamma_isrf2a * sgMg2SiO4 (i)
+ gisrfFe3O4 (i) = gamma_isrf2a * sgFe3O4 (i)
+ gisrfSiO2D (i) = gamma_isrf2a * sgSiO2D (i)
+ gisrfMgO (i) = gamma_isrf2a * sgMgO (i)
+ gisrfFeS (i) = gamma_isrf2a * sgFeS (i)
+ gisrfAl2O3 (i) = gamma_isrf2a * sgAl2O3 (i)
+ endif
+ if (idspecies .gt. 2) then
+ gisrfreforg (i) = gamma_isrf2a * sgreforg (i)
+ gisrfvolorg (i) = gamma_isrf2a * sgvolorg (i)
+ gisrfH2Oice (i) = gamma_isrf2a * sgH2Oice (i)
+ endif
+
+ endif
+
+ endif ! idspecies
+
+ endif
+ enddo
+
+! --- Gas to grain heat transfer ---
+
+! Look up gas/grain heat transfer rates
+
+ do i = is+1, ie+1
+ if ( itmask_metal(i) .ne. MASK_FALSE ) then
+
+ if(idspecies .eq. 0) then
+
+ gasgr(i) = gasgra(indixe(i)) + tdef(i)
+ & *(gasgra(indixe(i)+1) -gasgra(indixe(i)))
+
+!! gasgr_tdust(i) = fgr * gasgr(i) * coolunit / mh
+ gasgr_tdust(i) = (dust2gas(i) / metallicity(i))
+ & * gasgr(i) * coolunit / mh
+ !! apply to (idustfield .eq. 1) GC20200701
+
+ else ! idspecies
+
+ fv2k = gasgr2a(indixe(i)) + tdef(i)
+ & *(gasgr2a(indixe(i)+1) -gasgr2a(indixe(i)))
+
+ fac = coolunit / mh
+
+ if ( itdmulti .eq. 0 ) then
+
+ gasgr(i) = fv2k * sgtot(i)
+
+ gasgr_tdust(i) = gasgr(i) * fac
+
+ else
+
+ if (idspecies .gt. 0) then
+ gasMgSiO3 (i) = fv2k * sgMgSiO3 (i)
+ gasAC (i) = fv2k * sgAC (i)
+ endif
+ if (idspecies .gt. 1) then
+ gasSiM (i) = fv2k * sgSiM (i)
+ gasFeM (i) = fv2k * sgFeM (i)
+ gasMg2SiO4 (i) = fv2k * sgMg2SiO4 (i)
+ gasFe3O4 (i) = fv2k * sgFe3O4 (i)
+ gasSiO2D (i) = fv2k * sgSiO2D (i)
+ gasMgO (i) = fv2k * sgMgO (i)
+ gasFeS (i) = fv2k * sgFeS (i)
+ gasAl2O3 (i) = fv2k * sgAl2O3 (i)
+ endif
+ if (idspecies .gt. 2) then
+ gasreforg (i) = fv2k * sgreforg (i)
+ gasvolorg (i) = fv2k * sgvolorg (i)
+ gasH2Oice (i) = fv2k * sgH2Oice (i)
+ endif
+
+ if (idspecies .gt. 0) then
+ gasgr_tMgSiO3 (i) = gasMgSiO3 (i) * fac
+ gasgr_tAC (i) = gasAC (i) * fac
+ endif
+ if (idspecies .gt. 1) then
+ gasgr_tSiM (i) = gasSiM (i) * fac
+ gasgr_tFeM (i) = gasFeM (i) * fac
+ gasgr_tMg2SiO4 (i) = gasMg2SiO4 (i) * fac
+ gasgr_tFe3O4 (i) = gasFe3O4 (i) * fac
+ gasgr_tSiO2D (i) = gasSiO2D (i) * fac
+ gasgr_tMgO (i) = gasMgO (i) * fac
+ gasgr_tFeS (i) = gasFeS (i) * fac
+ gasgr_tAl2O3 (i) = gasAl2O3 (i) * fac
+ endif
+ if (idspecies .gt. 2) then
+ gasgr_treforg (i) = gasreforg (i) * fac
+ gasgr_tvolorg (i) = gasvolorg (i) * fac
+ gasgr_tH2Oice (i) = gasH2Oice (i) * fac
+ endif
+
+ endif
+
+ endif ! idspecies
+
+ endif
+ enddo
+
+! Compute dust temperature
+
+ if (itdmulti .eq. 0) then
+
+ call calc_tdust_1d_g(tdust, tgas, nh, gasgr_tdust,
+ & mygisrf, myisrf, itmask_metal, trad, in, is, ie, j, k
+ & , gr_N, gr_Size, gr_dT, gr_Td, altot, kptot, idspecies)
+
+ else
+
+ if (idspecies .gt. 0) then
+ call calc_tdust_1d_g(tMgSiO3 , tgas, nh, gasgr_tMgSiO3 ,
+ & gisrfMgSiO3 , myisrf, itmask_metal, trad,
+ & in, is, ie, j, k
+ & , gr_N, gr_Size, gr_dT, gr_Td, alMgSiO3 , kpMgSiO3
+ & , idspecies)
+
+ call calc_tdust_1d_g(tAC , tgas, nh, gasgr_tAC ,
+ & gisrfAC , myisrf, itmask_metal, trad,
+ & in, is, ie, j, k
+ & , gr_N, gr_Size, gr_dT, gr_Td, alAC , kpAC
+ & , idspecies)
+ endif
+
+ if (idspecies .gt. 1) then
+ call calc_tdust_1d_g(tSiM , tgas, nh, gasgr_tSiM ,
+ & gisrfSiM , myisrf, itmask_metal, trad,
+ & in, is, ie, j, k
+ & , gr_N, gr_Size, gr_dT, gr_Td, alSiM , kpSiM
+ & , idspecies)
+
+ call calc_tdust_1d_g(tFeM , tgas, nh, gasgr_tFeM ,
+ & gisrfFeM , myisrf, itmask_metal, trad,
+ & in, is, ie, j, k
+ & , gr_N, gr_Size, gr_dT, gr_Td, alFeM , kpFeM
+ & , idspecies)
+
+ call calc_tdust_1d_g(tMg2SiO4 , tgas, nh, gasgr_tMg2SiO4 ,
+ & gisrfMg2SiO4 , myisrf, itmask_metal, trad,
+ & in, is, ie, j, k
+ & , gr_N, gr_Size, gr_dT, gr_Td, alMg2SiO4 , kpMg2SiO4
+ & , idspecies)
+
+ call calc_tdust_1d_g(tFe3O4 , tgas, nh, gasgr_tFe3O4 ,
+ & gisrfFe3O4 , myisrf, itmask_metal, trad,
+ & in, is, ie, j, k
+ & , gr_N, gr_Size, gr_dT, gr_Td, alFe3O4 , kpFe3O4
+ & , idspecies)
+
+ call calc_tdust_1d_g(tSiO2D , tgas, nh, gasgr_tSiO2D ,
+ & gisrfSiO2D , myisrf, itmask_metal, trad,
+ & in, is, ie, j, k
+ & , gr_N, gr_Size, gr_dT, gr_Td, alSiO2D , kpSiO2D
+ & , idspecies)
+
+ call calc_tdust_1d_g(tMgO , tgas, nh, gasgr_tMgO ,
+ & gisrfMgO , myisrf, itmask_metal, trad,
+ & in, is, ie, j, k
+ & , gr_N, gr_Size, gr_dT, gr_Td, alMgO , kpMgO
+ & , idspecies)
+
+ call calc_tdust_1d_g(tFeS , tgas, nh, gasgr_tFeS ,
+ & gisrfFeS , myisrf, itmask_metal, trad,
+ & in, is, ie, j, k
+ & , gr_N, gr_Size, gr_dT, gr_Td, alFeS , kpFeS
+ & , idspecies)
+
+ call calc_tdust_1d_g(tAl2O3 , tgas, nh, gasgr_tAl2O3 ,
+ & gisrfAl2O3 , myisrf, itmask_metal, trad,
+ & in, is, ie, j, k
+ & , gr_N, gr_Size, gr_dT, gr_Td, alAl2O3 , kpAl2O3
+ & , idspecies)
+ endif
+
+ if (idspecies .gt. 2) then
+ call calc_tdust_1d_g(treforg , tgas, nh, gasgr_treforg ,
+ & gisrfreforg , myisrf, itmask_metal, trad,
+ & in, is, ie, j, k
+ & , gr_N, gr_Size, gr_dT, gr_Td, alreforg , kpreforg
+ & , idspecies)
+
+ call calc_tdust_1d_g(tvolorg , tgas, nh, gasgr_tvolorg ,
+ & gisrfvolorg , myisrf, itmask_metal, trad,
+ & in, is, ie, j, k
+ & , gr_N, gr_Size, gr_dT, gr_Td, alvolorg , kpvolorg
+ & , idspecies)
+
+ call calc_tdust_1d_g(tH2Oice , tgas, nh, gasgr_tH2Oice ,
+ & gisrfH2Oice , myisrf, itmask_metal, trad,
+ & in, is, ie, j, k
+ & , gr_N, gr_Size, gr_dT, gr_Td, alH2Oice , kpH2Oice
+ & , idspecies)
+ endif
+
+ endif
+ end
diff --git a/src/clib/calc_tdust_3d_g.F b/src/clib/calc_tdust_3d_g.F
index 4637a4066..a067ea054 100644
--- a/src/clib/calc_tdust_3d_g.F
+++ b/src/clib/calc_tdust_3d_g.F
@@ -92,14 +92,6 @@ subroutine calc_tdust_3d_g(
& , metal_F50(in,jn,kn), metal_F80(in,jn,kn)
& , metal_P170(in,jn,kn), metal_P200(in,jn,kn)
& , metal_Y19(in,jn,kn)
- & , CI(in,jn,kn) , CII(in,jn,kn) , CO(in,jn,kn)
- & , CO2(in,jn,kn) , OI(in,jn,kn) , OH(in,jn,kn)
- & , H2O(in,jn,kn) , O2(in,jn,kn) , SiI(in,jn,kn)
- & , SiOI(in,jn,kn) , SiO2I(in,jn,kn) , CH(in,jn,kn)
- & , CH2(in,jn,kn) , COII(in,jn,kn) , OII(in,jn,kn)
- & , OHII(in,jn,kn) , H2OII(in,jn,kn) , H3OII(in,jn,kn)
- & , O2II(in,jn,kn) , Mg(in,jn,kn) , Al(in,jn,kn)
- & , S(in,jn,kn) , Fe(in,jn,kn)
R_PREC SiM(in,jn,kn), FeM(in,jn,kn), Mg2SiO4(in,jn,kn)
& , MgSiO3(in,jn,kn), Fe3O4(in,jn,kn), AC(in,jn,kn)
& , SiO2D(in,jn,kn), MgO(in,jn,kn), FeS(in,jn,kn)
@@ -199,22 +191,11 @@ subroutine calc_tdust_3d_g(
! Slice locals
- integer indixe(in)
- R_PREC t1(in), t2(in), logtem(in), tdef(in),
- & tgas(in), tdust(in), nh(in), gasgr(in),
+ integer*8 indixe(in)
+ real*8 t1(in), t2(in), logtem(in), tdef(in),
+ & tgas(in), tdust(in), nh(in), gasgr(in), gasgr_tdust(in),
& myisrf(in)
-! Additional slice locals
- R_PREC brem(in), ceHeI(in), ceHeII(in), ceHI(in),
- & cieco(in), ciHeI(in), ciHeII(in), ciHeIS(in),
- & ciHI(in), comp1(in), comp2(in), edot(in),
- & energy(in), gammaha_eff(in), gasgr_tdust(in),
- & gphdl(in), gpldl(in), h2k01(in), hdlow(in),
- & hdlte(in), hyd01k(in), mmw(in), myde(in),
- & mynh(in), p2d(in), regr(in), reHeII1(in),
- & reHeIII(in), reHII(in), rhoH(in), reHeII(in),
- & reHeII2(in), roth(in), rotl(in), tgasold(in),
- & vibh(in)
! Iteration mask for multi_cool
MASK_TYPE itmask(in)
@@ -250,21 +231,7 @@ subroutine calc_tdust_3d_g(
! parallelize the k and j loops with OpenMP
! flat j and k loops for better parallelism
#ifdef _OPENMP
-!$omp parallel do schedule(runtime) private(
-!$omp& i, j, k,
-!$omp& comp1, comp2, energy,
-!$omp& indixe,
-!$omp& t1, t2, logtem, tdef, p2d,
-!$omp& tgas, tgasold,
-!$omp& tdust, metallicity, dust2gas, rhoH, mmw,
-!$omp& mynh, myde, gammaha_eff, gasgr_tdust, regr, edot,
-!$omp& ceHI, ceHeI, ceHeII,
-!$omp& ciHI, ciHeI, ciHeIS, ciHeII,
-!$omp& reHII, reHeII1, reHeII2, reHeIII,
-!$omp& brem, cieco,
-!$omp& hyd01k, h2k01, vibh, roth, rotl,
-!$omp& gpldl, gphdl, hdlte, hdlow,
-!$omp& itmask )
+!$omp parallel do schedule(runtime) private(i, j, k)
#endif
do t = 0, dk*dj-1
k = t/dj + ks+1
@@ -287,39 +254,6 @@ subroutine calc_tdust_3d_g(
metal_P200(i,j,k)=metal_P200(i,j,k)/real(aye**3, RKIND)
metal_Y19(i,j,k) = metal_Y19(i,j,k)/real(aye**3, RKIND)
endif
-!! if (metal(i,j,k) .gt. 1.d-9 * d(i,j,k)) then
- if (imchem .eq. 1) then
- CI(i,j,k) = CI(i,j,k)/real(aye**3, RKIND)
- CII(i,j,k) = CII(i,j,k)/real(aye**3, RKIND)
- CO(i,j,k) = CO(i,j,k)/real(aye**3, RKIND)
- CO2(i,j,k) = CO2(i,j,k)/real(aye**3, RKIND)
- OI(i,j,k) = OI(i,j,k)/real(aye**3, RKIND)
- OH(i,j,k) = OH(i,j,k)/real(aye**3, RKIND)
- H2O(i,j,k) = H2O(i,j,k)/real(aye**3, RKIND)
- O2(i,j,k) = O2(i,j,k)/real(aye**3, RKIND)
- SiI(i,j,k) = SiI(i,j,k)/real(aye**3, RKIND)
- SiOI(i,j,k) = SiOI(i,j,k)/real(aye**3, RKIND)
- SiO2I(i,j,k) = SiO2I(i,j,k)/real(aye**3, RKIND)
- CH(i,j,k) = CH(i,j,k)/real(aye**3, RKIND)
- CH2(i,j,k) = CH2(i,j,k)/real(aye**3, RKIND)
- COII(i,j,k) = COII(i,j,k)/real(aye**3, RKIND)
- OII(i,j,k) = OII(i,j,k)/real(aye**3, RKIND)
- OHII(i,j,k) = OHII(i,j,k)/real(aye**3, RKIND)
- H2OII(i,j,k) = H2OII(i,j,k)/real(aye**3, RKIND)
- H3OII(i,j,k) = H3OII(i,j,k)/real(aye**3, RKIND)
- O2II(i,j,k) = O2II(i,j,k)/real(aye**3, RKIND)
- if ( ( igrgr .eq. 1 ) .or. ( idsub .eq. 1 ) ) then
- if (idspecies .gt. 0) then
- Mg(i,j,k) = Mg(i,j,k)/real(aye**3, RKIND)
- endif
- if (idspecies .gt. 1) then
- Al(i,j,k) = Al(i,j,k)/real(aye**3, RKIND)
- S(i,j,k) = S(i,j,k)/real(aye**3, RKIND)
- Fe(i,j,k) = Fe(i,j,k)/real(aye**3, RKIND)
- endif
- endif
- endif
-!! endif
enddo
endif
if (idustfield .eq. 1) then
@@ -477,51 +411,6 @@ subroutine calc_tdust_3d_g(
myisrf(i) = isrf
endif
- if (idspecies .eq. 0 ) then
- if (idustfield .gt. 0) then
- mygisrf(i) = gamma_isrfa
- & * fgr / dust2gas(i) * metallicity(i)
- !! correct with the depletion or enhancement of condensation rate.
-!! write(*,*) 'a', mygisrf(i)
- else
- mygisrf(i) = gamma_isrfa
- endif
-
- else ! idspecies
-
- if (itdmulti .eq. 0) then
-
- mygisrf(i) = gamma_isrf2a * sgtot(i)
- !! in UV, absorption coefficient Q ~ 1 (Goldsmith 2001)
- !! so we use the geometrical cross-section of grains [cgs]
-!! write(*,*) 'b', mygisrf(i) / dust2gas(i)
-
- else
-
- if (idspecies .gt. 0) then
- gisrfMgSiO3 (i) = gamma_isrf2a * sgMgSiO3 (i)
-!! write(*,*) d(i,j,k), gamma_isrf2a, sgMgSiO3(i)
- gisrfAC (i) = gamma_isrf2a * sgAC (i)
- endif
- if (idspecies .gt. 1) then
- gisrfSiM (i) = gamma_isrf2a * sgSiM (i)
- gisrfFeM (i) = gamma_isrf2a * sgFeM (i)
- gisrfMg2SiO4 (i) = gamma_isrf2a * sgMg2SiO4 (i)
- gisrfFe3O4 (i) = gamma_isrf2a * sgFe3O4 (i)
- gisrfSiO2D (i) = gamma_isrf2a * sgSiO2D (i)
- gisrfMgO (i) = gamma_isrf2a * sgMgO (i)
- gisrfFeS (i) = gamma_isrf2a * sgFeS (i)
- gisrfAl2O3 (i) = gamma_isrf2a * sgAl2O3 (i)
- endif
- if (idspecies .gt. 2) then
- gisrfreforg (i) = gamma_isrf2a * sgreforg (i)
- gisrfvolorg (i) = gamma_isrf2a * sgvolorg (i)
- gisrfH2Oice (i) = gamma_isrf2a * sgH2Oice (i)
- endif
-
- endif
-
- endif
! Compute hydrogen number density
@@ -549,173 +438,33 @@ subroutine calc_tdust_3d_g(
t2(i) = (logtem0 + (indixe(i) )*dlogtem)
tdef(i) = (logtem(i) - t1(i)) / (t2(i) - t1(i))
-! Lookup values and do a linear temperature in log(T)
-! Convert back to cgs
-
- if(idspecies .eq. 0) then
-
- gasgr(i) = gasgra(indixe(i)) + tdef(i)
- & *(gasgra(indixe(i)+1) -gasgra(indixe(i)))
-
-!! gasgr(i) = fgr * gasgr(i) * coolunit / mh
- gasgr(i) = (dust2gas(i) / metallicity(i))
- & * gasgr(i) * coolunit / mh
- !! apply to (idustfield .eq. 1) GC20200701
-!! write(*,*) 'a', gasgr(i)
-
- else
-
- fv2k = gasgr2a(indixe(i)) + tdef(i)
- & *(gasgr2a(indixe(i)+1) -gasgr2a(indixe(i)))
-
- fac = coolunit / mh
-
- if ( itdmulti .eq. 0 ) then
-
- gasgr(i) = fv2k * sgtot(i) * fac
-!! write(*,*) 'b', gasgr(i) / metallicity(i)
-
- else
-
- if (idspecies .gt. 0) then
- gasMgSiO3 (i) = fv2k * sgMgSiO3 (i) * fac
-!! write(*,*) fv2k, sgMgSiO3(i), fac
- gasAC (i) = fv2k * sgAC (i) * fac
- endif
- if (idspecies .gt. 1) then
- gasSiM (i) = fv2k * sgSiM (i) * fac
- gasFeM (i) = fv2k * sgFeM (i) * fac
- gasMg2SiO4 (i) = fv2k * sgMg2SiO4 (i) * fac
- gasFe3O4 (i) = fv2k * sgFe3O4 (i) * fac
- gasSiO2D (i) = fv2k * sgSiO2D (i) * fac
- gasMgO (i) = fv2k * sgMgO (i) * fac
- gasFeS (i) = fv2k * sgFeS (i) * fac
- gasAl2O3 (i) = fv2k * sgAl2O3 (i) * fac
- endif
- if (idspecies .gt. 2) then
- gasreforg (i) = fv2k * sgreforg (i) * fac
- gasvolorg (i) = fv2k * sgvolorg (i) * fac
- gasH2Oice (i) = fv2k * sgH2Oice (i) * fac
- endif
-
- endif
-
- endif
-
endif ! itmask
enddo
-
-! if (idspecies .eq. 0) then
-! do itd = 1, gr_N(2)
-! do i = is+1, ie + 1
-! if(itmask(i)) then
-! altot(itd,i)=
-! & (SN0_kpFeM (4*itd,1)*SN0_fFeM (1)
-! & /SN0_r0FeM (3 ,1)
-! & +SN0_kpMg2SiO4(4*itd,1)*SN0_fMg2SiO4(1)
-! & /SN0_r0Mg2SiO4(3 ,1)
-! & +SN0_kpMgSiO3 (4*itd,1)*SN0_fMgSiO3 (1)
-! & /SN0_r0MgSiO3 (3 ,1)
-! & +SN0_kpFeS (4*itd,1)*SN0_fFeS (1)
-! & /SN0_r0FeS (3 ,1)
-! & +SN0_kpreforg (4*itd,1)*SN0_freforg (1)
-! & /SN0_r0reforg (3 ,1)
-! & +SN0_kpvolorg (4*itd,1)*SN0_fvolorg (1)
-! & /SN0_r0volorg (3 ,1)
-! & +SN0_kpH2Oice (4*itd,1)*SN0_fH2Oice (1)
-! & /SN0_r0H2Oice (3 ,1))
-! & * metal(i,j,k) / d(i,j,k)
-! endif
-! enddo
-! enddo
-! endif
-
! --- Compute dust temperature in a slice ---
- if (itdmulti .eq. 0) then
-
- call calc_tdust_1d_g(tdust, tgas, nh, gasgr,
- & mygisrf, myisrf, itmask, trad, in, is, ie, j, k
- & , gr_N, gr_Size, gr_dT, gr_Td, altot, kptot, idspecies)
-
-!! write(*,*) tdust
-
- else
-
- if (idspecies .gt. 0) then
- call calc_tdust_1d_g(tMgSiO3 , tgas, nh, gasMgSiO3 ,
- & gisrfMgSiO3 , myisrf, itmask, trad, in, is, ie, j, k
- & , gr_N, gr_Size, gr_dT, gr_Td, alMgSiO3 , kpMgSiO3
- & , idspecies)
-!! write(*,*) 'bb2', gasMgSiO3, gisrfMgSiO3, myisrf, tMgSiO3
-
- call calc_tdust_1d_g(tAC , tgas, nh, gasAC ,
- & gisrfAC , myisrf, itmask, trad, in, is, ie, j, k
- & , gr_N, gr_Size, gr_dT, gr_Td, alAC , kpAC
- & , idspecies)
-!! write(*,*) 'bb2', gasAC , gisrfAC , myisrf, tAC
- endif
-
- if (idspecies .gt. 1) then
- call calc_tdust_1d_g(tSiM , tgas, nh, gasSiM ,
- & gisrfSiM , myisrf, itmask, trad, in, is, ie, j, k
- & , gr_N, gr_Size, gr_dT, gr_Td, alSiM , kpSiM
- & , idspecies)
-
- call calc_tdust_1d_g(tFeM , tgas, nh, gasFeM ,
- & gisrfFeM , myisrf, itmask, trad, in, is, ie, j, k
- & , gr_N, gr_Size, gr_dT, gr_Td, alFeM , kpFeM
- & , idspecies)
-
- call calc_tdust_1d_g(tMg2SiO4 , tgas, nh, gasMg2SiO4 ,
- & gisrfMg2SiO4 , myisrf, itmask, trad, in, is, ie, j, k
- & , gr_N, gr_Size, gr_dT, gr_Td, alMg2SiO4 , kpMg2SiO4
- & , idspecies)
-
- call calc_tdust_1d_g(tFe3O4 , tgas, nh, gasFe3O4 ,
- & gisrfFe3O4 , myisrf, itmask, trad, in, is, ie, j, k
- & , gr_N, gr_Size, gr_dT, gr_Td, alFe3O4 , kpFe3O4
- & , idspecies)
-
- call calc_tdust_1d_g(tSiO2D , tgas, nh, gasSiO2D ,
- & gisrfSiO2D , myisrf, itmask, trad, in, is, ie, j, k
- & , gr_N, gr_Size, gr_dT, gr_Td, alSiO2D , kpSiO2D
- & , idspecies)
-
- call calc_tdust_1d_g(tMgO , tgas, nh, gasMgO ,
- & gisrfMgO , myisrf, itmask, trad, in, is, ie, j, k
- & , gr_N, gr_Size, gr_dT, gr_Td, alMgO , kpMgO
- & , idspecies)
-
- call calc_tdust_1d_g(tFeS , tgas, nh, gasFeS ,
- & gisrfFeS , myisrf, itmask, trad, in, is, ie, j, k
- & , gr_N, gr_Size, gr_dT, gr_Td, alFeS , kpFeS
- & , idspecies)
-
- call calc_tdust_1d_g(tAl2O3 , tgas, nh, gasAl2O3 ,
- & gisrfAl2O3 , myisrf, itmask, trad, in, is, ie, j, k
- & , gr_N, gr_Size, gr_dT, gr_Td, alAl2O3 , kpAl2O3
- & , idspecies)
- endif
-
- if (idspecies .gt. 2) then
- call calc_tdust_1d_g(treforg , tgas, nh, gasreforg ,
- & gisrfreforg , myisrf, itmask, trad, in, is, ie, j, k
- & , gr_N, gr_Size, gr_dT, gr_Td, alreforg , kpreforg
- & , idspecies)
-
- call calc_tdust_1d_g(tvolorg , tgas, nh, gasvolorg ,
- & gisrfvolorg , myisrf, itmask, trad, in, is, ie, j, k
- & , gr_N, gr_Size, gr_dT, gr_Td, alvolorg , kpvolorg
- & , idspecies)
-
- call calc_tdust_1d_g(tH2Oice , tgas, nh, gasH2Oice ,
- & gisrfH2Oice , myisrf, itmask, trad, in, is, ie, j, k
- & , gr_N, gr_Size, gr_dT, gr_Td, alH2Oice , kpH2Oice
- & , idspecies)
- endif
+ call calc_all_tdust_gasgr_1d_g(in, jn, kn, nratec,
+ & idustfield, is, ie, j, k, fgr, gamma_isrfa,
+ & trad, gasgra, indixe, tdef, tgas, tdust,
+ & metallicity, dust2gas, nh, gasgr_tdust,
+ & itmask,
+ & idspecies, itdmulti, gr_N, gr_Size, gr_dT,
+ & gr_Td, tSiM, tFeM, tMg2SiO4, tMgSiO3, tFe3O4,
+ & tAC, tSiO2D, tMgO, tFeS, tAl2O3, treforg,
+ & tvolorg, tH2Oice, gasgr2a, gamma_isrf2a,
+ & coolunit, gasgr, myisrf, sgSiM, sgFeM, sgMg2SiO4,
+ & sgMgSiO3, sgFe3O4, sgAC, sgSiO2D, sgMgO, sgFeS,
+ & sgAl2O3, sgreforg, sgvolorg, sgH2Oice, sgtot,
+ & alSiM, alFeM, alMg2SiO4, alMgSiO3, alFe3O4, alAC,
+ & alSiO2D, alMgO, alFeS, alAl2O3, alreforg,
+ & alvolorg, alH2Oice, altot, kpSiM, kpFeM,
+ & kpMg2SiO4, kpMgSiO3, kpFe3O4, kpAC, kpSiO2D,
+ & kpMgO, kpFeS, kpAl2O3, kpreforg, kpvolorg,
+ & kpH2Oice, kptot, gasSiM, gasFeM, gasMg2SiO4,
+ & gasMgSiO3, gasFe3O4, gasAC, gasSiO2D, gasMgO,
+ & gasFeS, gasAl2O3, gasreforg, gasvolorg,
+ & gasH2Oice
+ & )
- endif
! Copy slice values back to grid
@@ -759,21 +508,7 @@ subroutine calc_tdust_3d_g(
! parallelize the k and j loops with OpenMP
! flat j and k loops for better parallelism
#ifdef _OPENMP
-!$omp parallel do schedule(runtime) private(
-!$omp& i, j, k,
-!$omp& comp1, comp2, energy,
-!$omp& indixe,
-!$omp& t1, t2, logtem, tdef, p2d,
-!$omp& tgas, tgasold,
-!$omp& tdust, metallicity, dust2gas, rhoH, mmw,
-!$omp& mynh, myde, gammaha_eff, gasgr_tdust, regr, edot,
-!$omp& ceHI, ceHeI, ceHeII,
-!$omp& ciHI, ciHeI, ciHeIS, ciHeII,
-!$omp& reHII, reHeII1, reHeII2, reHeIII,
-!$omp& brem, cieco,
-!$omp& hyd01k, h2k01, vibh, roth, rotl,
-!$omp& gpldl, gphdl, hdlte, hdlow,
-!$omp& itmask )
+!$omp parallel do schedule(runtime) private(i, j, k)
#endif
do t = 0, dk*dj-1
k = t/dj + ks+1
@@ -796,39 +531,6 @@ subroutine calc_tdust_3d_g(
metal_P200(i,j,k)=metal_P200(i,j,k)*real(aye**3, RKIND)
metal_Y19(i,j,k) = metal_Y19(i,j,k)*real(aye**3, RKIND)
endif
-!! if (metal(i,j,k) .gt. 1.d-9 * d(i,j,k)) then
- if (imchem .eq. 1) then
- CI(i,j,k) = CI(i,j,k)*real(aye**3, RKIND)
- CII(i,j,k) = CII(i,j,k)*real(aye**3, RKIND)
- CO(i,j,k) = CO(i,j,k)*real(aye**3, RKIND)
- CO2(i,j,k) = CO2(i,j,k)*real(aye**3, RKIND)
- OI(i,j,k) = OI(i,j,k)*real(aye**3, RKIND)
- OH(i,j,k) = OH(i,j,k)*real(aye**3, RKIND)
- H2O(i,j,k) = H2O(i,j,k)*real(aye**3, RKIND)
- O2(i,j,k) = O2(i,j,k)*real(aye**3, RKIND)
- SiI(i,j,k) = SiI(i,j,k)*real(aye**3, RKIND)
- SiOI(i,j,k) = SiOI(i,j,k)*real(aye**3, RKIND)
- SiO2I(i,j,k) = SiO2I(i,j,k)*real(aye**3, RKIND)
- CH(i,j,k) = CH(i,j,k)*real(aye**3, RKIND)
- CH2(i,j,k) = CH2(i,j,k)*real(aye**3, RKIND)
- COII(i,j,k) = COII(i,j,k)*real(aye**3, RKIND)
- OII(i,j,k) = OII(i,j,k)*real(aye**3, RKIND)
- OHII(i,j,k) = OHII(i,j,k)*real(aye**3, RKIND)
- H2OII(i,j,k) = H2OII(i,j,k)*real(aye**3, RKIND)
- H3OII(i,j,k) = H3OII(i,j,k)*real(aye**3, RKIND)
- O2II(i,j,k) = O2II(i,j,k)*real(aye**3, RKIND)
- if ( ( igrgr .eq. 1 ) .or. ( idsub .eq. 1 ) ) then
- if (idspecies .gt. 0) then
- Mg(i,j,k) = Mg(i,j,k)*real(aye**3, RKIND)
- endif
- if (idspecies .gt. 1) then
- Al(i,j,k) = Al(i,j,k)*real(aye**3, RKIND)
- S(i,j,k) = S(i,j,k)*real(aye**3, RKIND)
- Fe(i,j,k) = Fe(i,j,k)*real(aye**3, RKIND)
- endif
- endif
- endif
-!! endif
enddo
endif
if (idustfield .eq. 1) then
diff --git a/src/clib/cool1d_multi_g.F b/src/clib/cool1d_multi_g.F
index 75fa7dedf..fa87e8e71 100644
--- a/src/clib/cool1d_multi_g.F
+++ b/src/clib/cool1d_multi_g.F
@@ -345,17 +345,6 @@ subroutine cool1d_multi_g(
& , gasSiO2D(in), gasMgO(in), gasFeS(in)
& , gasAl2O3(in)
& , gasreforg(in), gasvolorg(in), gasH2Oice(in)
- real*8 gasgr_tSiM(in), gasgr_tFeM(in), gasgr_tMg2SiO4(in)
- & , gasgr_tMgSiO3(in), gasgr_tFe3O4(in), gasgr_tAC(in)
- & , gasgr_tSiO2D(in), gasgr_tMgO(in), gasgr_tFeS(in)
- & , gasgr_tAl2O3(in)
- & , gasgr_treforg(in), gasgr_tvolorg(in), gasgr_tH2Oice(in)
- real*8 mygisrf(in), fv2k, fac
- real*8 gisrfSiM(in), gisrfFeM(in), gisrfMg2SiO4(in)
- & , gisrfMgSiO3(in), gisrfFe3O4(in), gisrfAC(in)
- & , gisrfSiO2D(in), gisrfMgO(in), gisrfFeS(in)
- & , gisrfAl2O3(in)
- & , gisrfreforg(in), gisrfvolorg(in), gisrfH2Oice(in)
! Iteration mask
MASK_TYPE itmask(in), anydust, interp
@@ -1155,240 +1144,37 @@ subroutine cool1d_multi_g(
endif
endif
-! Calculate heating from interstellar radiation field
-! -> this is ONLY used when `itmask_metal .eq. MASK_TRUE`
-
- if ((anydust .ne. MASK_FALSE) .or. (igammah .gt. 1)) then
- do i = is+1, ie+1
- if ( itmask_metal(i) .ne. MASK_FALSE ) then
-
- if (idspecies .eq. 0 ) then
- if (idustfield .gt. 0) then
- mygisrf(i) = gamma_isrfa
- & * fgr / dust2gas(i) * metallicity(i)
- !! correct with the depletion or enhancement of condensation rate.
- else
- mygisrf(i) = gamma_isrfa
- endif
-
- else ! idspecies
-
- if (itdmulti .eq. 0) then
-
- mygisrf(i) = gamma_isrf2a * sgtot(i)
- !! in UV, absorption coefficient Q ~ 1 (Goldsmith 2001)
- !! so we use the geometrical cross-section of grains [cgs]
-
- else
-
- if (idspecies .gt. 0) then
- gisrfMgSiO3 (i) = gamma_isrf2a * sgMgSiO3 (i)
-!! write(*,*) 'sil', d(i,j,k), gamma_isrf2a, sgMgSiO3(i)
- gisrfAC (i) = gamma_isrf2a * sgAC (i)
-!! write(*,*) 'car', d(i,j,k), gamma_isrf2a, sgMgSiO3(i)
- endif
- if (idspecies .gt. 1) then
- gisrfSiM (i) = gamma_isrf2a * sgSiM (i)
- gisrfFeM (i) = gamma_isrf2a * sgFeM (i)
- gisrfMg2SiO4 (i) = gamma_isrf2a * sgMg2SiO4 (i)
- gisrfFe3O4 (i) = gamma_isrf2a * sgFe3O4 (i)
- gisrfSiO2D (i) = gamma_isrf2a * sgSiO2D (i)
- gisrfMgO (i) = gamma_isrf2a * sgMgO (i)
- gisrfFeS (i) = gamma_isrf2a * sgFeS (i)
- gisrfAl2O3 (i) = gamma_isrf2a * sgAl2O3 (i)
- endif
- if (idspecies .gt. 2) then
- gisrfreforg (i) = gamma_isrf2a * sgreforg (i)
- gisrfvolorg (i) = gamma_isrf2a * sgvolorg (i)
- gisrfH2Oice (i) = gamma_isrf2a * sgH2Oice (i)
- endif
-
- endif
-
- endif ! idspecies
-
- endif
- enddo
- endif
-
-! --- Gas to grain heat transfer ---
-
+ ! compute dust temperature and cooling due to dust
if (anydust .ne. MASK_FALSE) then
-! Look up gas/grain heat transfer rates
-
- do i = is+1, ie+1
- if ( itmask_metal(i) .ne. MASK_FALSE ) then
-
- if(idspecies .eq. 0) then
-
- gasgr(i) = gasgra(indixe(i)) + tdef(i)
- & *(gasgra(indixe(i)+1) -gasgra(indixe(i)))
-
-!! gasgr_tdust(i) = fgr * gasgr(i) * coolunit / mh
- gasgr_tdust(i) = (dust2gas(i) / metallicity(i))
- & * gasgr(i) * coolunit / mh
- !! apply to (idustfield .eq. 1) GC20200701
-
- else ! idspecies
-
- fv2k = gasgr2a(indixe(i)) + tdef(i)
- & *(gasgr2a(indixe(i)+1) -gasgr2a(indixe(i)))
-
- fac = coolunit / mh
-
- if ( itdmulti .eq. 0 ) then
-
- gasgr(i) = fv2k * sgtot(i)
-
- gasgr_tdust(i) = gasgr(i) * fac
-
- else
-
- if (idspecies .gt. 0) then
- gasMgSiO3 (i) = fv2k * sgMgSiO3 (i)
- gasAC (i) = fv2k * sgAC (i)
- endif
- if (idspecies .gt. 1) then
- gasSiM (i) = fv2k * sgSiM (i)
- gasFeM (i) = fv2k * sgFeM (i)
- gasMg2SiO4 (i) = fv2k * sgMg2SiO4 (i)
- gasFe3O4 (i) = fv2k * sgFe3O4 (i)
- gasSiO2D (i) = fv2k * sgSiO2D (i)
- gasMgO (i) = fv2k * sgMgO (i)
- gasFeS (i) = fv2k * sgFeS (i)
- gasAl2O3 (i) = fv2k * sgAl2O3 (i)
- endif
- if (idspecies .gt. 2) then
- gasreforg (i) = fv2k * sgreforg (i)
- gasvolorg (i) = fv2k * sgvolorg (i)
- gasH2Oice (i) = fv2k * sgH2Oice (i)
- endif
-
- if (idspecies .gt. 0) then
- gasgr_tMgSiO3 (i) = gasMgSiO3 (i) * fac
- gasgr_tAC (i) = gasAC (i) * fac
- endif
- if (idspecies .gt. 1) then
- gasgr_tSiM (i) = gasSiM (i) * fac
- gasgr_tFeM (i) = gasFeM (i) * fac
- gasgr_tMg2SiO4 (i) = gasMg2SiO4 (i) * fac
- gasgr_tFe3O4 (i) = gasFe3O4 (i) * fac
- gasgr_tSiO2D (i) = gasSiO2D (i) * fac
- gasgr_tMgO (i) = gasMgO (i) * fac
- gasgr_tFeS (i) = gasFeS (i) * fac
- gasgr_tAl2O3 (i) = gasAl2O3 (i) * fac
- endif
- if (idspecies .gt. 2) then
- gasgr_treforg (i) = gasreforg (i) * fac
- gasgr_tvolorg (i) = gasvolorg (i) * fac
- gasgr_tH2Oice (i) = gasH2Oice (i) * fac
- endif
-
- endif
-
- endif ! idspecies
-
- endif
- enddo
-
-! Compute dust temperature
-
- if (itdmulti .eq. 0) then
-
- call calc_tdust_1d_g(tdust, tgas, mynh, gasgr_tdust,
- & mygisrf, myisrf, itmask_metal, comp2, in, is, ie, j, k
- & , gr_N, gr_Size, gr_dT, gr_Td, altot, kptot, idspecies)
-
- else
-
- if (idspecies .gt. 0) then
- call calc_tdust_1d_g(tMgSiO3 , tgas, mynh, gasgr_tMgSiO3 ,
- & gisrfMgSiO3 , myisrf, itmask_metal, comp2,
- & in, is, ie, j, k
- & , gr_N, gr_Size, gr_dT, gr_Td, alMgSiO3 , kpMgSiO3
- & , idspecies)
-
- call calc_tdust_1d_g(tAC , tgas, mynh, gasgr_tAC ,
- & gisrfAC , myisrf, itmask_metal, comp2,
- & in, is, ie, j, k
- & , gr_N, gr_Size, gr_dT, gr_Td, alAC , kpAC
- & , idspecies)
- endif
-
- if (idspecies .gt. 1) then
- call calc_tdust_1d_g(tSiM , tgas, mynh, gasgr_tSiM ,
- & gisrfSiM , myisrf, itmask_metal, comp2,
- & in, is, ie, j, k
- & , gr_N, gr_Size, gr_dT, gr_Td, alSiM , kpSiM
- & , idspecies)
-
- call calc_tdust_1d_g(tFeM , tgas, mynh, gasgr_tFeM ,
- & gisrfFeM , myisrf, itmask_metal, comp2,
- & in, is, ie, j, k
- & , gr_N, gr_Size, gr_dT, gr_Td, alFeM , kpFeM
- & , idspecies)
-
- call calc_tdust_1d_g(tMg2SiO4 , tgas, mynh, gasgr_tMg2SiO4 ,
- & gisrfMg2SiO4 , myisrf, itmask_metal, comp2,
- & in, is, ie, j, k
- & , gr_N, gr_Size, gr_dT, gr_Td, alMg2SiO4 , kpMg2SiO4
- & , idspecies)
-
- call calc_tdust_1d_g(tFe3O4 , tgas, mynh, gasgr_tFe3O4 ,
- & gisrfFe3O4 , myisrf, itmask_metal, comp2,
- & in, is, ie, j, k
- & , gr_N, gr_Size, gr_dT, gr_Td, alFe3O4 , kpFe3O4
- & , idspecies)
-
- call calc_tdust_1d_g(tSiO2D , tgas, mynh, gasgr_tSiO2D ,
- & gisrfSiO2D , myisrf, itmask_metal, comp2,
- & in, is, ie, j, k
- & , gr_N, gr_Size, gr_dT, gr_Td, alSiO2D , kpSiO2D
- & , idspecies)
-
- call calc_tdust_1d_g(tMgO , tgas, mynh, gasgr_tMgO ,
- & gisrfMgO , myisrf, itmask_metal, comp2,
- & in, is, ie, j, k
- & , gr_N, gr_Size, gr_dT, gr_Td, alMgO , kpMgO
- & , idspecies)
-
- call calc_tdust_1d_g(tFeS , tgas, mynh, gasgr_tFeS ,
- & gisrfFeS , myisrf, itmask_metal, comp2,
- & in, is, ie, j, k
- & , gr_N, gr_Size, gr_dT, gr_Td, alFeS , kpFeS
- & , idspecies)
-
- call calc_tdust_1d_g(tAl2O3 , tgas, mynh, gasgr_tAl2O3 ,
- & gisrfAl2O3 , myisrf, itmask_metal, comp2,
- & in, is, ie, j, k
- & , gr_N, gr_Size, gr_dT, gr_Td, alAl2O3 , kpAl2O3
- & , idspecies)
- endif
-
- if (idspecies .gt. 2) then
- call calc_tdust_1d_g(treforg , tgas, mynh, gasgr_treforg ,
- & gisrfreforg , myisrf, itmask_metal, comp2,
- & in, is, ie, j, k
- & , gr_N, gr_Size, gr_dT, gr_Td, alreforg , kpreforg
- & , idspecies)
-
- call calc_tdust_1d_g(tvolorg , tgas, mynh, gasgr_tvolorg ,
- & gisrfvolorg , myisrf, itmask_metal, comp2,
- & in, is, ie, j, k
- & , gr_N, gr_Size, gr_dT, gr_Td, alvolorg , kpvolorg
- & , idspecies)
-
- call calc_tdust_1d_g(tH2Oice , tgas, mynh, gasgr_tH2Oice ,
- & gisrfH2Oice , myisrf, itmask_metal, comp2,
- & in, is, ie, j, k
- & , gr_N, gr_Size, gr_dT, gr_Td, alH2Oice , kpH2Oice
- & , idspecies)
- endif
+ call calc_all_tdust_gasgr_1d_g(in, jn, kn, nratec,
+ & idustfield, is, ie, j, k, fgr, gamma_isrfa,
+ & comp2, gasgra, indixe, tdef, tgas, tdust,
+ & metallicity, dust2gas, mynh, gasgr_tdust,
+ & itmask_metal,
+ & idspecies, itdmulti, gr_N, gr_Size, gr_dT,
+ & gr_Td, tSiM, tFeM, tMg2SiO4, tMgSiO3, tFe3O4,
+ & tAC, tSiO2D, tMgO, tFeS, tAl2O3, treforg,
+ & tvolorg, tH2Oice, gasgr2a, gamma_isrf2a,
+ & coolunit, gasgr, myisrf, sgSiM, sgFeM, sgMg2SiO4,
+ & sgMgSiO3, sgFe3O4, sgAC, sgSiO2D, sgMgO, sgFeS,
+ & sgAl2O3, sgreforg, sgvolorg, sgH2Oice, sgtot,
+ & alSiM, alFeM, alMg2SiO4, alMgSiO3, alFe3O4, alAC,
+ & alSiO2D, alMgO, alFeS, alAl2O3, alreforg,
+ & alvolorg, alH2Oice, altot, kpSiM, kpFeM,
+ & kpMg2SiO4, kpMgSiO3, kpFe3O4, kpAC, kpSiO2D,
+ & kpMgO, kpFeS, kpAl2O3, kpreforg, kpvolorg,
+ & kpH2Oice, kptot, gasSiM, gasFeM, gasMg2SiO4,
+ & gasMgSiO3, gasFe3O4, gasAC, gasSiO2D, gasMgO,
+ & gasFeS, gasAl2O3, gasreforg, gasvolorg,
+ & gasH2Oice
+ & )
endif
! Calculate dust cooling rate
+ if (anydust .ne. MASK_FALSE) then
+
do i = is+1, ie+1
if ( itmask_metal(i) .ne. MASK_FALSE ) then
diff --git a/src/include/grackle_fortran_interface.def b/src/include/grackle_fortran_interface.def
index bd86796c6..96db23394 100644
--- a/src/include/grackle_fortran_interface.def
+++ b/src/include/grackle_fortran_interface.def
@@ -152,7 +152,6 @@ c This is the fortran definition of grackle_chemistry_data
INTEGER(C_INT) :: primordial_chemistry
INTEGER(C_INT) :: dust_chemistry
INTEGER(C_INT) :: metal_cooling
- REAL(C_DOUBLE) :: tabulated_cooling_minimum_temperature
INTEGER(C_INT) :: UVbackground
TYPE(C_PTR) :: grackle_data_file
INTEGER(C_INT) :: cmb_temperature_floor
@@ -161,6 +160,7 @@ c This is the fortran definition of grackle_chemistry_data
INTEGER(C_INT) :: use_dust_density_field
INTEGER(C_INT) :: dust_recombination_cooling
INTEGER(C_INT) :: metal_chemistry
+ REAL(C_DOUBLE) :: tabulated_cooling_minimum_temperature
INTEGER(C_INT) :: grain_growth
INTEGER(C_INT) :: multi_metals
INTEGER(C_INT) :: metal_abundances
@@ -275,7 +275,7 @@ c The following define the fortran interfaces to the C routines
IMPORT
TYPE(grackle_units), INTENT(IN) :: my_units
TYPE(grackle_field_data), INTENT(IN) :: my_fields
- REAL(C_DOUBLE), INTENT(IN) :: dt
+ REAL(C_DOUBLE), VALUE, INTENT(IN) :: dt
END FUNCTION solve_chemistry
END INTERFACE
@@ -335,4 +335,4 @@ c The following define the fortran interfaces to the C routines
IMPORT
TYPE(grackle_field_data), INTENT(INOUT) :: my_fields
END FUNCTION gr_initialize_field_data
- END INTERFACE
\ No newline at end of file
+ END INTERFACE
diff --git a/src/python/pygrackle/utilities/data_path.py b/src/python/pygrackle/utilities/data_path.py
index c640258c5..ffa749694 100644
--- a/src/python/pygrackle/utilities/data_path.py
+++ b/src/python/pygrackle/utilities/data_path.py
@@ -16,20 +16,12 @@
from pygrackle.__config__ import _is_editable_installation
from pygrackle.utilities.misc import dirname
-grackle_data_dir = os.environ.get("GRACKLE_DATA_DIR")
-if (grackle_data_dir is None) and _is_editable_installation():
+if _is_editable_installation():
# Note, this only works with an editable install of pygrackle.
_install_dir = dirname(os.path.abspath(__file__), level=5)
grackle_data_dir = os.path.join(_install_dir, "input")
-elif (grackle_data_dir is None):
+else:
raise RuntimeError(
"in non-editable pygrackle installations, like this one, "
- f"grackle_data_dir can only be imported from {__file__} if it is set "
- "by the GRACKLE_DATA_DIR environment variable"
+ f"grackle_data_dir cannot be imported from {__file__}."
)
-
-if not os.path.isdir(grackle_data_dir):
- raise RuntimeError(
- f"grackle_data_dir not set to a valid directory: {grackle_data_dir}. "
- "Use the GRACKLE_DATA_DIR environment variable to set path to "
- "Grackle data.")
diff --git a/src/python/pygrackle/utilities/testing.py b/src/python/pygrackle/utilities/testing.py
index 71dae01ee..a1665a5e6 100644
--- a/src/python/pygrackle/utilities/testing.py
+++ b/src/python/pygrackle/utilities/testing.py
@@ -11,7 +11,6 @@
# software.
########################################################################
-import contextlib
import importlib
import numpy as np
from numpy.testing import assert_array_equal, assert_almost_equal, \
@@ -21,7 +20,6 @@
import os
import shutil
import subprocess
-import tempfile
def assert_rel_equal(a1, a2, decimals, err_msg='', verbose=True):
if isinstance(a1, np.ndarray):
@@ -60,9 +58,9 @@ def ftrue(func):
else:
return ftrue
-def run_command(command, timeout=None):
+def run_command(command, timeout=None, cwd=None):
try:
- proc = subprocess.run(command, shell=True, timeout=timeout)
+ proc = subprocess.run(command, shell=True, timeout=timeout, cwd=cwd)
if proc.returncode == 0:
success = True
else:
@@ -74,28 +72,3 @@ def run_command(command, timeout=None):
print ("Killed by keyboard interrupt!")
success = False
return success
-
-@contextlib.contextmanager
-def temporary_directory():
- curdir = os.getcwd()
- tmpdir = tempfile.mkdtemp(dir=curdir)
- os.chdir(tmpdir)
- try:
- yield tmpdir
- finally:
- os.chdir(curdir)
- shutil.rmtree(tmpdir)
-
-def ensure_dir(path):
- r"""Parallel safe directory maker."""
- if os.path.exists(path):
- return path
-
- try:
- os.makedirs(path)
- except OSError as e:
- if e.errno == errno.EEXIST:
- pass
- else:
- raise
- return path
diff --git a/src/python/tests/conftest.py b/src/python/tests/conftest.py
new file mode 100644
index 000000000..7e78378be
--- /dev/null
+++ b/src/python/tests/conftest.py
@@ -0,0 +1,67 @@
+# this defines some basic utilities shared among all of the tests
+#
+# DO NOT import pygrackle into global scope in this file (or in any file
+# imported by this file). Some tests need to be runable without installing
+# pygrackle
+
+import os
+from typing import NamedTuple
+
+import pytest
+
+
+# this hook is used to add more command line flags to the pytest launcher
+def pytest_addoption(parser):
+ parser.addoption(
+ "--answer-dir",
+ action="store",
+ default=None,
+ help=(
+ "Path to directory used for storing answer-tests answers. All "
+ "logic related to answer-tests is disabled unless this is "
+ "specified. When specified alonside --answer-store, logic to "
+ "generate the answers will be run (the answers are stored to this "
+ "directory). When specified WITHOUT --answer-store, the results "
+ "of each answer-test is compared against the answers that were "
+ "previously stored in this directory."
+ )
+ )
+
+ parser.addoption(
+ "--answer-store",
+ action="store_true",
+ help=(
+ "Indicates that we should store answer-test results. It is an "
+ "error to specifiy this arg without --answer-dir."
+ ),
+ )
+
+
+class AnswerTestSpec(NamedTuple):
+ generate_answers: bool
+ answer_dir: str
+
+
+@pytest.fixture(scope="session")
+def answertestspec(request):
+ """
+ Return an object specifying all user-specified directives regarding
+ answer tests (whether to run them and where to store/find results)
+ """
+
+ generate_answers = request.config.getoption("--answer-store")
+
+ answer_dir = request.config.getoption("--answer-dir")
+
+ if (answer_dir is None) and generate_answers:
+ raise ValueError(
+ "--answer-store option can't be specified without --answer-dir"
+ )
+ elif answer_dir is None:
+ pytest.skip("no --answer-dir option found")
+ elif (not os.path.isdir(answer_dir)) and (not generate_answers):
+ pytest.skip(f"directory of test answers can't be found, {answer_dir}")
+ else:
+ os.makedirs(answer_dir, exist_ok=True)
+
+ return AnswerTestSpec(generate_answers=generate_answers, answer_dir=answer_dir)
diff --git a/src/python/tests/test_code_examples.py b/src/python/tests/test_code_examples.py
index b1101f97c..c6cc07d19 100644
--- a/src/python/tests/test_code_examples.py
+++ b/src/python/tests/test_code_examples.py
@@ -18,10 +18,7 @@
import re
import subprocess
-from testing_common import \
- generate_test_results, \
- grackle_install_dir, \
- test_answers_dir
+from testing_common import grackle_install_dir
try:
from pygrackle.__config__ import \
@@ -58,12 +55,17 @@
"temperature"
)
-test_file = os.path.join(test_answers_dir, "code_examples.json")
-if generate_test_results and os.path.exists(test_file):
- os.remove(test_file)
-if not generate_test_results and not os.path.exists(test_file):
- raise RuntimeError(
- f"Code example results file not found: {test_file}")
+@pytest.fixture(scope="module")
+def test_file(answertestspec):
+ # this fixture has module-scope so that we will delete the test file once
+ test_file = os.path.join(answertestspec.answer_dir, "code_examples.json")
+ if answertestspec.generate_answers and os.path.exists(test_file):
+ os.remove(test_file)
+
+ # if test_file doesn't exist and answertestspec.generate_answers is False,
+ # defer any error reporting until within the test-case (after the test-case
+ # determines whether or not it should be skipped)
+ return test_file
def run_command(command, cwd, env, timeout=None):
proc = subprocess.run(
@@ -107,7 +109,7 @@ def parse_output(ostr):
return results
@pytest.mark.parametrize("example", code_examples)
-def test_code_examples(example):
+def test_code_examples(answertestspec, test_file, example):
# under the classic build system, we could just execute `make` in the examples
# directory and there is a good chance that it would work out...
# -> now we require the PYTEST_CODE_LINK_CHOICE environment variable to be
@@ -139,7 +141,16 @@ def test_code_examples(example):
else:
raise RuntimeError("PYTEST_CODE_LINK_CHOICE must be '', 'classic' or "
"'cmake:'. {choice!r} is invalid")
+
+ # if we aren't generating test-answers, and the test-file can't be found
+ # report an error (we explicitly wait to do this until after we have
+ # decided whether to skip the test or not).
+ if not answertestspec.generate_answers and not os.path.exists(test_file):
+ raise RuntimeError(f"Code example results file not found: {test_file}")
+
env = dict(os.environ)
+
+ # compile the example
command = f'{make_command} {example}'
run_command(command, examples_dir, env, timeout=60)
@@ -152,7 +163,7 @@ def test_code_examples(example):
if example not in compare_exclude:
results = parse_output(proc.stdout)
- if generate_test_results:
+ if answertestspec.generate_answers:
if os.path.exists(test_file):
with open(test_file, mode="r") as f:
all_results = json.load(f)
diff --git a/src/python/tests/test_get_grackle_version.py b/src/python/tests/test_get_grackle_version.py
index de536d2f4..14df01ca6 100644
--- a/src/python/tests/test_get_grackle_version.py
+++ b/src/python/tests/test_get_grackle_version.py
@@ -19,12 +19,17 @@
def query_grackle_version_props():
# retrieve the current version information with git
- os.chdir(os.path.dirname(os.path.abspath(__file__)))
+
+ cur_dir = os.path.dirname(os.path.abspath(__file__))
+
+ def _run(args):
+ _rslt = subprocess.run(
+ args, cwd=cur_dir, check=True, capture_output=True,
+ )
+ return _rslt.stdout.decode().rstrip()
# get the name of the most recent tag preceeding this commit:
- _rslt = subprocess.run(["git", "describe", "--abbrev=0", "--tags"],
- check = True, capture_output = True)
- most_recent_tag = _rslt.stdout.decode().rstrip()
+ most_recent_tag = _run(["git", "describe", "--abbrev=0", "--tags"])
if most_recent_tag.startswith("grackle-"):
latest_tagged_version = most_recent_tag[8:]
elif most_recent_tag.startswith("gold-standard-v"):
@@ -36,18 +41,12 @@ def query_grackle_version_props():
)
# get the actual revision when most_recent tag was introduced
- _rslt = subprocess.run(["git", "rev-parse", "-n", "1", most_recent_tag],
- check = True, capture_output = True)
- revision_of_tag = _rslt.stdout.decode().rstrip()
+ revision_of_tag = _run(["git", "rev-parse", "-n", "1", most_recent_tag])
# get the branch name and current revision
- _rslt = subprocess.run(["git", "rev-parse", "--abbrev-ref", "HEAD"],
- check = True, capture_output = True)
- branch = _rslt.stdout.decode().rstrip()
+ branch = _run(["git", "rev-parse", "--abbrev-ref", "HEAD"])
- _rslt = subprocess.run(["git", "rev-parse", "HEAD"],
- check = True, capture_output = True)
- revision = _rslt.stdout.decode().rstrip()
+ revision = _run(["git", "rev-parse", "HEAD"])
tagged_on_current_revision = revision == revision_of_tag
return latest_tagged_version, branch, revision, tagged_on_current_revision
diff --git a/src/python/tests/test_initialisation.py b/src/python/tests/test_initialisation.py
index 071df492a..5fa05e355 100644
--- a/src/python/tests/test_initialisation.py
+++ b/src/python/tests/test_initialisation.py
@@ -14,15 +14,7 @@
from pygrackle import chemistry_data
#Necessary constants from grackle
from pygrackle.utilities.physical_constants import mass_hydrogen_cgs
-from pygrackle.utilities.testing import \
- assert_allclose, \
- ensure_dir
-
-from testing_common import \
- generate_test_results, \
- test_answers_dir
-
-ensure_dir(test_answers_dir)
+from pygrackle.utilities.testing import assert_allclose
#* Function which returns chemistry_data instance with default initialisation settings.
def get_defChem():
@@ -108,8 +100,13 @@ def set_parameters(parSet, my_chemistry):
#* Function which tests that the rates have been initialised correctly for each parameter set.
-def test_rate_initialisation(printParameters=False, printOOMdiscrepanices=False, testCustomFile=False, parSets=[1,2,3,4,5,6,7],
- fileName="rate_coefficients.h5"):
+def test_rate_initialisation(answertestspec,
+ tmp_path,
+ printParameters=False,
+ printOOMdiscrepanices=False,
+ testCustomFile=False,
+ parSets=[1,2,3,4,5,6,7],
+ fileName="rate_coefficients.h5"):
"""
Test that the rate tables are initialized correctly.
@@ -117,12 +114,15 @@ def test_rate_initialisation(printParameters=False, printOOMdiscrepanices=False,
be saved into a hdf5 file. This should be used for testing and is not meant for frequent use.
printParameters (bool) --> If set to True will print the parameter settings for each parameter set.
- """
- #* Navigate to the directory where the file is located.
- filePath = os.path.abspath(__file__)
- dirPath = os.path.dirname(filePath)
- os.chdir(dirPath)
+ Fixtures
+ --------
+ answertestspec : AnswerTestSpec
+ A fixture used for all answer tests
+ tmp_path : pathlib.Path
+ A custom built-in fixture provided by pytest that specifies a pre-made temporary directory
+ that is named to be used with tmp_path
+ """
#* List of all rate variable names which will be checked.
testRates = "k1,k3,k4,k2,k5,k6,k7,k8,k9,k10,k11,k12,k14,k15,k16,k17,k18,k19,k20,k23,"\
@@ -134,8 +134,10 @@ def test_rate_initialisation(printParameters=False, printOOMdiscrepanices=False,
#* Calculate rates for each parameter set and write to hdf5 file
#Create and open file. If the file already exists this will overwrite it.
- if generate_test_results:
- fileName = os.path.join(test_answers_dir, fileName)
+ if answertestspec.generate_answers:
+ fileName = os.path.join(answertestspec.answer_dir, fileName)
+ else:
+ fileName = str(tmp_path / fileName)
f = h5py.File(fileName, "w")
#Iterate over parameter sets.
@@ -163,11 +165,11 @@ def test_rate_initialisation(printParameters=False, printOOMdiscrepanices=False,
f.close()
# Just generate results and leave.
- if generate_test_results:
+ if answertestspec.generate_answers:
return
#* Compare rates with the expected (correct) ones which are stored and check they are in agreement
- expectedRates = h5py.File(os.path.join(test_answers_dir, fileName), "r")
+ expectedRates = h5py.File(os.path.join(answertestspec.answer_dir, fileName), "r")
initialisedRates = h5py.File(fileName, "r")
diff --git a/src/python/tests/test_local_functions.py b/src/python/tests/test_local_functions.py
index 62515c2e1..f56f479bf 100644
--- a/src/python/tests/test_local_functions.py
+++ b/src/python/tests/test_local_functions.py
@@ -17,7 +17,6 @@
import os
from numpy.testing import assert_approx_equal
-from unittest import TestCase
from pygrackle import \
FluidContainer, \
@@ -29,18 +28,11 @@
mass_hydrogen_cgs, \
sec_per_Myr
-from pygrackle.utilities.testing import ensure_dir
-
-from testing_common import \
- generate_test_results, \
- grackle_data_dir, \
- test_answers_dir
+from testing_common import grackle_data_dir
local_function_test_format_version = 1
_meta_data = {"format_version": local_function_test_format_version}
-ensure_dir(test_answers_dir)
-
parameter_grid = {
"use_grackle": (1,),
"primordial_chemistry": (0, 1, 2, 3),
@@ -100,7 +92,7 @@ def failure_str(my_pars, my_units, my_in, my_out, comp_out, field):
msg += f"stored output: {comp_out[field]}"
return msg
-class LocalFunctionsTest(TestCase):
+class TestLocalFunctions:
"""
Tests for the local functions.
"""
@@ -108,11 +100,11 @@ class LocalFunctionsTest(TestCase):
n_input_sets = 10
seed = 21062024
digits = 12
- test_file = os.path.join(test_answers_dir, "local_function_tests.json")
+ test_file_basename = "local_function_tests.json"
- def setUp(self):
+ def setup_parameter_sets(self, generate_answers, test_file):
"""
- Setup local function tests.
+ Setup parameter-sets for local function tests.
If we are generating results, then create a list of parameter values
from the parameter_grid and exclude_sets structures defined above.
@@ -121,29 +113,31 @@ def setUp(self):
If we are not generating results, then read everything in from the
json test file.
"""
+ # if we need to reuse this functionality, we need should remove this
+ # from the class and convert it into a pytest fixture
- if generate_test_results:
+ if generate_answers:
my_sets = self.generate_parameter_sets()
self.test_sets = [{"parameters": my_set, "units": base_units}
for my_set in my_sets]
else:
- if not os.path.exists(self.test_file):
- self.skipTest(f"Test file not found: {self.test_file}.")
- with open(self.test_file, mode="r") as f:
+ if not os.path.exists(test_file):
+ self.skipTest(f"Test file not found: {test_file}.")
+ with open(test_file, mode="r") as f:
self.test_sets = json.load(f)
load_meta = self.test_sets.pop(0)
assert load_meta["format_version"] == _meta_data["format_version"], \
f"Test version mismatch: data file is {load_meta['format_version']}, " + \
f"source code is {_meta_data['format_version']}."
- def tearDown(self):
+ def finish_tests(self, generate_answers, test_file):
"""
Write json test file if we are generating resuls.
"""
- if generate_test_results:
+ if generate_answers:
# add the format version to the output
self.test_sets.insert(0, _meta_data)
- with open(self.test_file, mode="w") as f:
+ with open(test_file, mode="w") as f:
f.write(json.dumps(self.test_sets, indent=4))
def generate_parameter_sets(self):
@@ -194,7 +188,9 @@ def generate_base_inputs(self):
for i in range(self.n_input_sets)]
return base_inputs
- def test_local_functions(self):
+ def test_local_functions(self, answertestspec):
+ test_file = os.path.join(answertestspec.answer_dir, self.test_file_basename)
+ self.setup_parameter_sets(answertestspec.generate_answers, test_file)
for test_set in self.test_sets:
par_set = test_set["parameters"]
@@ -209,7 +205,7 @@ def test_local_functions(self):
setattr(my_chemistry, "grackle_data_file",
os.path.join(grackle_data_dir, par_set["grackle_data_file"]))
- if generate_test_results:
+ if answertestspec.generate_answers:
my_tests = []
base_inputs = self.generate_base_inputs()
n_input_sets = len(base_inputs)
@@ -220,7 +216,7 @@ def test_local_functions(self):
for itest in range(n_input_sets):
my_units = base_units.copy()
- if generate_test_results:
+ if answertestspec.generate_answers:
base_input_set = base_inputs[itest]
redshift = base_input_set["redshift"]
else:
@@ -232,7 +228,7 @@ def test_local_functions(self):
setattr(my_chemistry, unit, val)
my_chemistry.set_velocity_units()
- if generate_test_results:
+ if answertestspec.generate_answers:
fc = setup_fluid_container(
my_chemistry,
density=base_input_set["density"],
@@ -262,7 +258,7 @@ def test_local_functions(self):
my_out[fname] = fc[fname][0]
# Compare with existing results unless we are generating them.
- if generate_test_results:
+ if answertestspec.generate_answers:
my_tests.append({"input": my_in, "output": my_out})
else:
comp_out = my_tests[itest]["output"]
@@ -275,5 +271,6 @@ def test_local_functions(self):
significant=self.digits,
err_msg=err_msg)
- if generate_test_results:
+ if answertestspec.generate_answers:
test_set["tests"] = my_tests
+ self.finish_tests(answertestspec.generate_answers, test_file)
diff --git a/src/python/tests/test_models.py b/src/python/tests/test_models.py
index 755c08ddb..4d517b71e 100644
--- a/src/python/tests/test_models.py
+++ b/src/python/tests/test_models.py
@@ -6,20 +6,14 @@
from numpy.testing import assert_allclose
from pygrackle.utilities.model_tests import model_sets
-from pygrackle.utilities.testing import \
- ensure_dir, \
- run_command, \
- temporary_directory
+from pygrackle.utilities.testing import run_command
-from testing_common import \
- generate_test_results, \
- grackle_python_dir, \
- test_answers_dir
+from testing_common import grackle_python_dir
python_example_dir = os.path.join(grackle_python_dir, "examples")
-ensure_dir(test_answers_dir)
-
+# collect all of the python-examples and various model configurations into
+# a list of tuples
all_sets = []
for model_name, model in model_sets.items():
for par_index in range(len(model["parameter_sets"])):
@@ -27,17 +21,33 @@
all_sets.append((model_name, par_index, input_index))
@pytest.mark.parametrize("model_name, par_index, input_index", all_sets)
-def test_model(model_name, par_index, input_index):
+def test_model(answertestspec, tmp_path, model_name, par_index, input_index):
+ """
+ Each execution tests a python example with a set of inputs
+
+ Each of the parameters down below is a fixture
+
+ Parameters
+ ----------
+ answertestspec: AnswerTestSpec
+ A fixture that provides info about the answer-testing configuration
+ tmp_path: pathlib.Path
+ A custom built-in fixture provided by pytest that specifies a pre-made
+ temporary directory that is named for the current test
+ """
+
script_path = os.path.join(python_example_dir, f"{model_name}.py")
command = f"{sys.executable} {script_path} {par_index} {input_index}"
- with temporary_directory():
- rval = run_command(command, timeout=60)
+
+ if True:
+ rval = run_command(command, timeout=60, cwd=tmp_path)
assert rval
- output_file = f"{model_name}_{par_index}_{input_index}.h5"
- answer_path = os.path.join(test_answers_dir, output_file)
+ output_basename = f"{model_name}_{par_index}_{input_index}.h5"
+ output_file = os.path.join(str(tmp_path), output_basename)
+ answer_path = os.path.join(answertestspec.answer_dir, output_basename)
- if generate_test_results:
+ if answertestspec.generate_answers:
os.rename(output_file, answer_path)
else:
assert os.path.exists(answer_path)
diff --git a/src/python/tests/testing_common.py b/src/python/tests/testing_common.py
index adf85be7d..4f3514b02 100644
--- a/src/python/tests/testing_common.py
+++ b/src/python/tests/testing_common.py
@@ -17,16 +17,10 @@
from pygrackle.__config__ import _is_editable_installation
from pygrackle.utilities.misc import dirname
-generate_test_results = \
- int(os.environ.get("GENERATE_PYGRACKLE_TEST_RESULTS", 0)) == 1
-
if _is_editable_installation():
grackle_install_dir = dirname(os.path.abspath(__file__), level=4)
grackle_data_dir = os.path.join(grackle_install_dir, "input")
grackle_python_dir = os.path.join(grackle_install_dir, "src", "python")
- test_answers_dir = os.path.join(
- grackle_python_dir, "tests", "test_answers"
- )
else:
raise RuntimeError(
"the current version of pygrackle is not an editable installation. No "