From 58a5de609c541bf2f964377c2549ec5bacf6f475 Mon Sep 17 00:00:00 2001 From: Darth Vader Date: Mon, 10 Apr 2023 02:27:44 +0000 Subject: [PATCH] Squashed 'src/phast/PhreeqcRM/' changes from 8c960d43..b1f9657e b1f9657e 40 add bmibmi to bmiphreeqcrm and update swig interfaces (#44) f02a1289 Merge pull request #43 from scharlton2/42-undefined-symbol-_zn9phreeqcrm12getviscosityerst6vectoridsaidee 176265c7 ifdef'd out GetViscosity decalaration ba5eff55 Merge pull request #41 from dlparkhurst/bmi-f90 74bb6fe2 private UpdateBMI 47ed834a Merging from master Merge remote-tracking branch 'origin/master' into bmi-f90 ad31056c documenting c++ BMI 3914eca6 34 add pkg config to autotools and cmake distribution (#36) be9a12fa Merge pull request #39 from dlparkhurst/bmi-f90 120819d0 Scott's fixes 5a54a06c Merge pull request #37 from dlparkhurst/bmi-f90 b6dee735 Fixed unhandled enum warnings Renamed BMI_not_implemented.F90 to BMI_not_implemented.inc Added @todo for asserts that fail during ctest c4eaf6be Working on PR #37 33892817 fixed compiler warnings except NAN 4512421c fixed CMakeLists to include BMI_not_implemented.F90 a685d853 fixed bug in AdvectBMI_f90, fixed include file name 9ea68797 added dummy functions for all non-implemented methods 161e8566 Added Fortran pointers 895425c4 runs all the test cases, I'll have to check whether they are right. 58a2dfb0 fixed bug with rm2bmiupdate 961a2488 runs AdvectBMI_cpp.cpp 7c476c22 compiles. Finally figured out how to call the function pointers. 3143686f need to figure out how to run the functions adfd2027 retrieved AdvectBMI_cpp.cpp. Code compiles, start debug b9e47a22 removed static declaration. need to retrieve AdvectBMI_cpp.cpp 5118117c 4 unresolved references? 529a9bee moved enum to RMVARS.h bbd36de7 circular header file problem 653fdb2a PhreeqcRM.h in VarManager.h and VarManager.h in PhreeqcRM.h b274e554 circular references 126ebeda finished the _Var functions. Need to switch from _var and bmi_instance to new _Var and VarManager. 617bd89d through time_var. eight to go 376fed37 through gridcellcount 72b1ba12 Working on Vars, through FilePrefix, but have templates now ede8914a long way to go f6afcea5 reorganizing with VarManager class 787c57f1 All methods for C++ BMI are defined. Need to sort out SetValue and GetValue. Test. Finish F90 BMI. 597f9573 working on get_value_ptr for C++ and Fortran 71753f89 merged from master through bmi-reorg e14ed79c merging 3/26 to bmi-reorg; then merge bmi-f90 Merge remote-tracking branch 'origin/master' into bmi-reorg 8d648fc7 Closes usgs-coupled/phreeqcrm#32 (#33) ebf3fcdf had not checked in BMI_interface_F.h cbf328f8 Have getters, setters, and other grid functions left to do (and documentation) c0879cb9 implementing correct BMI F90. Through time functions. test cases run 6454bfd7 implementing correct BMI F90. Test cases run 9bbcbc99 reorganizing and adjusting for bmi documentation c7ee70dc renamed BMI_methods.h f9b48013 runs all tests ba784fa9 VS2022 & new Intel Fortran. Compiles and runs F90 BMI test case. f5997bd1 can't find the Fortran methods? 52997c17 BMI_interface 1270d87d changed all double precision to real(kind=8) in all files. Compiles and runs test cases. e314056d Merge branch 'dlparkhurst-bmi-reorg' 82859c7e Ran: pre-commit run --all-files bec6e176 Merge branch 'bmi-reorg' of https://github.com/dlparkhurst/phreeqcrm-bmi into dlparkhurst-bmi-reorg 1ba7c513 Cleaned up Fortran GetVarType. f36e7644 all test cases run. Added BMI_Create for F90 29689d21 InputVarNames and OutputVarNames work. Runs AdvectBMI_f90.F90 to completion. Need to work on Fortran GetVarType. 6fb16ecf fixing bugs aff8ac92 Something is broken for F90. 96fdc1bd need to fix logic of Info and GetFn a101bf35 bmi_methods.h has C++ BMI documentation 024a3f2b removed old C++ BMI routines, BMI_Methods.cpp and .h. Now using new version for Fortran (modified RM_BMI_interface_F.cpp to use new BMI methods). Need to keep BMI_Methods.h for C++ documentation. b7942285 Added Instances to BMIPhreeqcRM 8300fa88 Merge pull request #30 from scharlton2/29-configure-enable-fortran-test-with-yaml-cpp-fails-make-check 0989c870 Fixed ERROR: files left in build directory after distclean: d436f5ee Fixed RM_BMI_Initialize seems the call to trim stripped the c_null_char by GNU Fortran (Ubuntu 11.3.0-1ubuntu1~22.04) 11.3.0 fc427dfc Fixed make check 3cf23344 C++11 fix for macos c3d966b6 added BMIPhreeqcRM.cpp and .h to CMake. Separated BMI_methods.h as a #include in PhreeqcRM. Ultimately, BMI_methods should be eliminated. Compiles and runs test cases using new BMIPhreeqcRM methods. 6b108118 Closes usgs-coupled/phreeqcrm#29 2f1f609a AdvectBMI_cpp.cpp runs to completion with BMIPhreeqcRM. Fixed bugs with function map, logic in SetVar and GetVar. Should be equivalent to previous version in the variables for get and set. Will add more variables with time. 3661fd61 ready for testing 11112106 nearly done with original vars 93b035e5 starting on _vars, modifying BMI_Var to have Nbytes and Itemsize. e9f7a86f Tidied a bit, ready to start on the _var methods 77cfae74 All BMI functions are defined. Compiles, but completely untested c3ef0728 beginning to reorganize BMI 39bce39a Merge pull request #28 from dlparkhurst/26-logical-kind-warnings-with-gfortran b4906331 Closes usgs-coupled/phreeqcrm#26 0d773484 Merge remote-tracking branch 'origin/master' into bmi-working a049065d roughed in AdvectBMI_py.py, not working fd611aed Merge pull request #25 from scharlton2/bmi-working d11bbc19 Merge remote-tracking branch 'dlpark/bmi-working' into bmi-working 82052ba5 removed IntVector and DoubleVector 2142702d wrote the Python YAML documentation a43f3fd1 syncing AdvectBMI_xxx.yaml 5a97824c Latest test output files ab533ead Getting Python yaml source and test case 170ad39d Mostly doxygen updates 77724104 Merge remote-tracking branch 'dlpark/bmi-working' into bmi-working 4ed9eddb Finishing up documentation of Python PhreeqcRM bindings bf926632 reformatted paragraphs 1b68510d Working on bmi 916978c9 PhreeqcRM.i compiles f6971034 almost ready to add to .i file 1e641bba python documentation 81569491 fixing python documentation 2e5b0852 indentation ff9cb9e6 emaced the method documentation 1d09244a Updated Makefile.am for pyfragments.swg.in 78142ab9 Can now debug on windows (no numpy) 8c0b8f98 Moved fortran file ee4a3e09 Simple advect should run to nxyz not nxyz/2. Add BMI_Var.h to RM_BMI_interface_F.cpp 637ca8a0 Working on pr #24 95d9e7fb Merge pull request #1 from dlparkhurst/bmi-working f1d1105e merged with master on trunk 223de822 cleaning Doxygen as I can 18acab9f finished documentation, but needs cleanup. Not sure how to document polymorphism in Fortran. Need to get YAML Fortran Doxygen to appear. ce86c074 finished YAML F90 documentation. Need to check c4d92f30 working through YAML_interface.F90 documentation f0afac12 Master swig python (#23) 81d71e34 documenting and fixing bugs ef5b83a1 Finished renaming files and updating CMakeLists. Fixed a couple bugs in AdvectBMI_f90 d5d4cefb renaming to YAML_interface 97706607 Added --output-on-failure to ctest 90ef63c4 put back file accidentally deleted from CLists 1dc4f91d moved RM_BMI_interface.F90 into RM_interface.F90. Makes Doxygen work and avoids some preprocessor bug. 13837b0c F90 YAML works. The preprocessor directive in RM_BMI_interface.F90 is not working. Added other ifdef USE_YAML. No YAML fails because of the preprocessor error. bab47170 works on the test cases including F90 yaml. Need to document F90 YAML and update cmakelists bbe3ffdf added WriteYAMLFile_f90, need to test. Need to update CMakelists 1b3cc6fb YAML F90 bindings done, start checking bf0cbc27 working on Fortran bindings to YAMLPhreeqcRM. Last file is one third done--YAMLPhreeqcRM.F90 905e70cd updated documentation for GetDensity and GetSaturation 54d4ccae tweak 5e90b8dc Final? touches on Doxygen 1b374167 cleaning up documentation 28b17d07 Moved RM_ (no BMI_) to RM_interface.F90, removed RM_ to just GetGridCellCountYAML for Fortran. b0816d5f Will eventually add RM_BMI_interface.F90 to RM_interface.F90 e9413f89 Going to try adding all defs to RM_interface.F90 1ae57981 Going to try adding all defs to RM_interface.F90 401fe2ca reformatted 5a4c10ae F90 GetValue documented ad1e699b F90 GetValue documented 9e7ef5ec Fixed my screwup with void* F90 GetValue and SetValue. Void * version is needed. MadeNthSelectedOutputUserNumber 1 based for Fortran. d8f3bc7a working on doxygen ff51de03 checkin 81d9bf6b Used INCLUDE for BMI Fortran. Continued documenting 6821163e documenting, am going to try to make F90 files smaller f1f38ec7 Need to update BMI documentation for C++ and Fortran d843d409 revised BMI_GetValue and BMI_SetValue to eliminate void* in the C++ version. Fortran still calls a void* version. Revised AdvectBMI_cpp to use the revised methods. 77d976e5 finishing up AdvectBMI_f90 and AdvectBMI_cpp 3822f64d need to add tests for setters 44672f84 Merge branch 'usgs-coupled:master' into bmi-working 491b380c merged fortran branch into bmi-working 777af151 Merge remote-tracking branch 'origin/bmi-working' into bmi-working Scott has updated master fork. Propogating changes here. 683882ee working on testing advectbmi_f90. Added RM_GetPorosity and RM_GetPressure. Modified GetValue and SetValue to ensure dimensions are correct. Added benefit that allocate can occur in GetValue.Need to finish BMI_testing. Still need to document Fortran methods in RM_BMI_Interface_F.F90 c24c7288 started BMI_testing for F90. Started documentation for RM_BMI_interface.F90. Instead, I am going to work on the getters and setters to handle allocation. Also added inputvarnames and output varnames. 0c588c58 cleaned up AdvectBMI_cpp a little. Made case independent 6daa2a66 AdvectBMI_f90 output files 1e9309bd AdvectBMI_f90 is running c6b4fe7b cleaning up RM_BMI_interface.F90 8f8be7cb Working through AdvectBMI_f90.F90 0902e751 Starting on AdvectBMI_f90.F90 test case 5457017e Finished Fortran methods. Need to translate AdvectBMI_f90.F90 e89b47e3 Working on Fortran BMI b443b57a Working on Fortran BMI 604c6480 added GetGridCellCountYAML to example code git-subtree-dir: src/phast/PhreeqcRM git-subtree-split: b1f9657e932a0fe84b159d37a0e5acfb0cf38a12 --- .github/workflows/distro.yml | 91 +- .gitignore | 6 +- .pre-commit-config.yaml | 4 +- CMakeLists.txt | 427 +- Doxygen/Doxyfile | 49 +- Doxygen/DoxygenLayout.xml | 49 +- Doxygen/Makefile | 1 + Doxygen/lower_case.bat | 28 +- Doxygen/lower_case.sh | 153 + Doxygen/upper_case.bat | 105 + Doxygen/upper_case.sh | 83 +- Makefile.am | 84 +- Tests/AdvectBMI_cpp.cpp | 870 +- Tests/AdvectBMI_f90.F90 | 788 ++ Tests/Advect_f90.F90 | 48 +- Tests/CMakeLists.txt | 173 +- Tests/Gas_f90.F90 | 22 +- Tests/Makefile.am | 60 +- Tests/Output/AdvectBMI_cpp.chem.txt | 368 +- Tests/Output/AdvectBMI_cpp.dmp | 620 +- Tests/Output/AdvectBMI_cpp.yaml | 42 + Tests/Output/AdvectBMI_cpp_utility.txt | 6 +- Tests/Output/AdvectBMI_f90.chem.txt | 2481 ++++ Tests/Output/AdvectBMI_f90.dmp | 997 ++ Tests/Output/AdvectBMI_f90.yaml | 1131 ++ Tests/Output/AdvectBMI_py.yaml | 1131 ++ Tests/Output/Advect_c.chem.txt | 72 +- Tests/Output/Advect_c.dmp | 382 +- Tests/Output/Advect_c_utility.txt | 10 +- Tests/Output/Advect_cpp.chem.txt | 104 +- Tests/Output/Advect_cpp.dmp | 284 +- Tests/Output/Advect_cpp_units_utility.txt | 24 +- Tests/Output/Advect_cpp_units_worker.chem.txt | 10 +- Tests/Output/Advect_cpp_utility.txt | 6 +- Tests/Output/Advect_f90.chem.txt | 150 +- Tests/Output/Advect_f90.dmp | 182 +- Tests/Output/Advect_f90_utility.txt | 10 +- Tests/Output/Gas_c.chem.txt | 6 +- Tests/Output/Gas_cpp.chem.txt | 6 +- Tests/Output/Gas_f90.chem.txt | 6 +- Tests/Output/SimpleAdvect_c.chem.txt | 80 +- Tests/Output/SimpleAdvect_cpp.chem.txt | 76 +- Tests/Output/SimpleAdvect_f90.chem.txt | 150 +- Tests/Output/Species_c.chem.txt | 86 +- Tests/Output/Species_c.dmp | 586 +- Tests/Output/Species_c_utility.txt | 4 +- Tests/Output/Species_cpp.chem.txt | 82 +- Tests/Output/Species_cpp.dmp | 446 +- Tests/Output/Species_cpp_utility.txt | 4 +- Tests/Output/Species_f90.chem.txt | 152 +- Tests/Output/Species_f90.dmp | 686 +- Tests/Output/Species_f90_utility.txt | 8 +- Tests/SimpleAdvect_c.c | 2 +- Tests/SimpleAdvect_cpp.cpp | 2 +- Tests/SimpleAdvect_f90.F90 | 22 +- Tests/Species_f90.F90 | 52 +- Tests/WriteYAMLFile_cpp.cpp | 19 +- Tests/WriteYAMLFile_f90.F90 | 141 + Tests/{check.mk => autotools.mk} | 4 +- Tests/main.cpp | 7 + Tests/pkgconfig.mk | 70 + configure.ac | 59 +- phreeqcrm.cmake.in | 12 + phreeqcrm.pc.in | 13 + src/BMIPhreeqcRM.cpp | 1027 ++ src/BMIPhreeqcRM.h | 1090 ++ src/BMI_Var.cpp | 66 + src/BMI_Var.h | 209 +- src/BMI_interface.F90 | 2108 +++ src/BMI_interface_F.cpp | 429 + src/BMI_interface_F.h | 42 + src/BMI_methods.cpp | 1170 +- src/BMI_methods.h | 896 ++ src/BMI_not_implemented.inc | 226 + src/CMakeLists.txt | 3 + src/IPhreeqcPhast/IPhreeqc/CVar.hxx | 2 +- src/IPhreeqcPhast/IPhreeqc/IPhreeqc.h | 6 +- src/IPhreeqcPhast/IPhreeqc/IPhreeqc.hpp | 2 +- .../IPhreeqc/IPhreeqc_interface.F90 | 10 +- src/IPhreeqcPhast/IPhreeqc/phreeqcpp/cl1.cpp | 2 +- .../IPhreeqc/phreeqcpp/gases.cpp | 2 - .../IPhreeqc/phreeqcpp/model.cpp | 5 - .../IPhreeqc/phreeqcpp/pitzer.cpp | 20 +- src/IPhreeqcPhast/IPhreeqc/phreeqcpp/prep.cpp | 7 +- .../IPhreeqc/phreeqcpp/spread.cpp | 4 +- .../IPhreeqc/phreeqcpp/sundialsmath.h | 4 +- .../IPhreeqc/phreeqcpp/sundialstypes.h | 2 +- .../IPhreeqc/phreeqcpp/tally.cpp | 7 - src/PhreeqcRM.cpp | 589 +- src/PhreeqcRM.h | 1499 +- src/PhreeqcRM.i | 49 + src/RMVARS.h | 31 + src/RM_interface.F90 | 11361 ++++++++-------- src/RM_interface_C.h | 5 +- src/RM_interface_F.cpp | 96 +- src/RM_interface_F.h | 13 +- src/VarManager.cpp | 1409 ++ src/VarManager.h | 119 + src/YAMLPhreeqcRM.cpp | 79 +- src/YAMLPhreeqcRM.h | 57 +- src/YAML_interface.F90 | 2702 ++++ src/YAML_interface_F.cpp | 656 + src/YAML_interface_F.h | 84 + src/bmi.hxx | 83 + src/numpy.i | 2970 ++++ src/pyfragments.swg.in | 112 + src/swig/CMakeLists.txt | 5 + src/swig/python/AdvectBMI_py.py | 202 + src/swig/python/CMakeLists.txt | 133 + src/swig/python/PhreeqcRM_docstrings.i | 3195 +++++ src/swig/python/SimpleAdvect.py | 194 + src/swig/python/WriteYAMLFile_py.py | 109 + src/swig/python/YAMLPhreeqcRM.i | 1297 ++ src/swig/python/yamlphreeqcrm.py | 202 + 114 files changed, 38083 insertions(+), 10339 deletions(-) create mode 100644 Tests/AdvectBMI_f90.F90 create mode 100644 Tests/Output/AdvectBMI_f90.chem.txt create mode 100644 Tests/Output/AdvectBMI_f90.dmp create mode 100644 Tests/Output/AdvectBMI_f90.yaml create mode 100644 Tests/Output/AdvectBMI_py.yaml create mode 100644 Tests/WriteYAMLFile_f90.F90 rename Tests/{check.mk => autotools.mk} (92%) create mode 100644 Tests/pkgconfig.mk create mode 100644 phreeqcrm.cmake.in create mode 100644 phreeqcrm.pc.in create mode 100644 src/BMIPhreeqcRM.cpp create mode 100644 src/BMIPhreeqcRM.h create mode 100644 src/BMI_Var.cpp create mode 100644 src/BMI_interface.F90 create mode 100644 src/BMI_interface_F.cpp create mode 100644 src/BMI_interface_F.h create mode 100644 src/BMI_methods.h create mode 100644 src/BMI_not_implemented.inc create mode 100644 src/CMakeLists.txt create mode 100644 src/PhreeqcRM.i create mode 100644 src/RMVARS.h create mode 100644 src/VarManager.cpp create mode 100644 src/VarManager.h create mode 100644 src/YAML_interface.F90 create mode 100644 src/YAML_interface_F.cpp create mode 100644 src/YAML_interface_F.h create mode 100644 src/bmi.hxx create mode 100644 src/numpy.i create mode 100644 src/pyfragments.swg.in create mode 100644 src/swig/CMakeLists.txt create mode 100644 src/swig/python/AdvectBMI_py.py create mode 100644 src/swig/python/CMakeLists.txt create mode 100644 src/swig/python/PhreeqcRM_docstrings.i create mode 100644 src/swig/python/SimpleAdvect.py create mode 100644 src/swig/python/WriteYAMLFile_py.py create mode 100644 src/swig/python/YAMLPhreeqcRM.i create mode 100644 src/swig/python/yamlphreeqcrm.py diff --git a/.github/workflows/distro.yml b/.github/workflows/distro.yml index 04327a947..15fef8581 100644 --- a/.github/workflows/distro.yml +++ b/.github/workflows/distro.yml @@ -14,7 +14,7 @@ env: jobs: init: - if: github.event.pull_request.draft == false + if: github.event.pull_request.draft == false runs-on: ubuntu-latest # Map step outputs to job outputs outputs: @@ -61,7 +61,8 @@ jobs: - name: make shell: bash working-directory: ${{github.workspace}}/_build - run: make -j2 distcheck + # run: DISTCHECK_CONFIGURE_FLAGS="--enable-fortran-test --with-yaml-cpp" make -j2 distcheck + run: DISTCHECK_CONFIGURE_FLAGS="--with-yaml-cpp" make -j2 distcheck - uses: actions/upload-artifact@v3 with: @@ -123,9 +124,17 @@ jobs: - uses: actions/checkout@v3 - - name: Test install + - name: Test autotools install working-directory: ${{ github.workspace }}/Tests - run: env CC='gcc' CXX='g++ -std=gnu++11' make -f check.mk test && ./test + run: env CC='cc' CXX='c++ -std=c++11' make -f autotools.mk autotools_test && ./autotools_test + + - name: Clean autotools test + working-directory: ${{ github.workspace }}/Tests + run: make -f autotools.mk clean + + - name: Test CMake pkg-config + working-directory: ${{ github.workspace }}/Tests + run: env CC='cc' CXX='c++ -std=c++11' make -f pkgconfig.mk pkgconfig_test && ./pkgconfig_test cmake: name: cmake @@ -150,6 +159,7 @@ jobs: - name: Install ninja yaml-cpp valgrind (Linux) if: runner.os == 'Linux' + #run: sudo apt-get install -y ninja-build valgrind libyaml-cpp-dev python3-numpy run: sudo apt-get install -y ninja-build valgrind libyaml-cpp-dev - name: Install ninja yaml-cpp (macOS) @@ -160,6 +170,19 @@ jobs: if: ${{ runner.os == 'Windows' && matrix.phreeqcrm_with_yaml_cpp == 'ON' }} run: vcpkg install yaml-cpp:x64-windows + # - name: Set up Python ${{ matrix.python-version }} + - name: Set up Python 3.8 + uses: actions/setup-python@v4 + with: + # python-version: ${{ matrix.python-version }} + python-version: 3.8 + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + python -m pip install numpy + # @todo if [ -f requirements.txt ]; then pip install -r requirements.txt; fi + - name: Set up Visual Studio shell (Windows) if: runner.os == 'Windows' uses: egor-tensin/vs-shell@v2 @@ -171,19 +194,71 @@ jobs: - name: Configure with CMake (Not Windows) if: runner.os != 'Windows' - run: cmake -B build -S phreeqcrm-${{ env.VER_STRING }} -DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} -DBUILD_SHARED_LIBS=${{ matrix.build_shared_libs }} -DPHREEQCRM_WITH_YAML_CPP=${{ matrix.phreeqcrm_with_yaml_cpp }} + run: cmake -B build -S phreeqcrm-${{ env.VER_STRING }} -DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} -DBUILD_SHARED_LIBS=${{ matrix.build_shared_libs }} -DPHREEQCRM_WITH_YAML_CPP=${{ matrix.phreeqcrm_with_yaml_cpp }} -DPHREEQCRM_BUILD_PYTHON:BOOL=ON - name: Configure with CMake (Windows) if: ${{ runner.os == 'Windows' && matrix.phreeqcrm_with_yaml_cpp != 'ON' }} - run: cmake -B build -S phreeqcrm-${{ env.VER_STRING }} -DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} -DBUILD_SHARED_LIBS=${{ matrix.build_shared_libs }} -DPHREEQCRM_WITH_YAML_CPP=${{ matrix.phreeqcrm_with_yaml_cpp }} + run: cmake -B build -S phreeqcrm-${{ env.VER_STRING }} -DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} -DBUILD_SHARED_LIBS=${{ matrix.build_shared_libs }} -DPHREEQCRM_WITH_YAML_CPP=${{ matrix.phreeqcrm_with_yaml_cpp }} -DPHREEQCRM_BUILD_PYTHON:BOOL=ON - name: Configure with CMake (Windows) if: ${{ runner.os == 'Windows' && matrix.phreeqcrm_with_yaml_cpp == 'ON' }} - run: cmake --toolchain ${{ env.VCPKG_INSTALLATION_ROOT }}/scripts/buildsystems/vcpkg.cmake -B build -S phreeqcrm-${{ env.VER_STRING }} -DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} -DBUILD_SHARED_LIBS=${{ matrix.build_shared_libs }} -DPHREEQCRM_WITH_YAML_CPP=${{ matrix.phreeqcrm_with_yaml_cpp }} + run: cmake --toolchain ${{ env.VCPKG_INSTALLATION_ROOT }}/scripts/buildsystems/vcpkg.cmake -B build -S phreeqcrm-${{ env.VER_STRING }} -DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} -DBUILD_SHARED_LIBS=${{ matrix.build_shared_libs }} -DPHREEQCRM_WITH_YAML_CPP=${{ matrix.phreeqcrm_with_yaml_cpp }} -DPHREEQCRM_BUILD_PYTHON:BOOL=ON + + - name: Print phreeqcrm.pc + working-directory: ${{ github.workspace }}/build + run: cat phreeqcrm.pc - name: Build with CMake run: cmake --build ${{ github.workspace }}/build --config ${{ env.BUILD_TYPE }} - name: Test with CMake working-directory: ${{ github.workspace }}/build - run: ctest -C ${{ env.BUILD_TYPE }} + run: ctest -C ${{ env.BUILD_TYPE }} --output-on-failure + + - name: Install (Non-Windows) + if: runner.os != 'Windows' + run: sudo cmake --install build + + - name: Install (Windows) + if: runner.os == 'Windows' + run: cmake --install build + + - name: Run ldconfig (Linux) + if: ${{ runner.os == 'Linux' && matrix.build_shared_libs == 'ON' }} + run: sudo ldconfig + + - name: Cleanup (Non-Windows) + if: runner.os != 'Windows' + run: sudo rm -rf * + + - name: Cleanup (Windows) + if: runner.os == 'Windows' + run: Remove-Item -Recurse -Force * + + - uses: actions/checkout@v3 + + - name: Test install (configure) (Non-Windows) + if: runner.os != 'Windows' + working-directory: ${{ github.workspace }}/Tests + run: cmake -B build -S . -DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} -D_PHREEQCRM_TEST_INSTALL:BOOL=ON + + - name: Test install (configure) (Windows) + if: runner.os == 'Windows' + working-directory: ${{ github.workspace }}/Tests + run: cmake --toolchain ${{ env.VCPKG_INSTALLATION_ROOT }}/scripts/buildsystems/vcpkg.cmake -B build -S . -DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} -D_PHREEQCRM_TEST_INSTALL:BOOL=ON + + - name: Test install (build) + working-directory: ${{ github.workspace }}/Tests + run: cmake --build build --config ${{ env.BUILD_TYPE }} + + - name: Test install (ctest) (Non-Windows) + if: runner.os != 'Windows' + working-directory: ${{ github.workspace }}/Tests/build + run: ctest -C ${{ env.BUILD_TYPE }} --output-on-failure + + - name: Test install (ctest) (Windows) + if: runner.os == 'Windows' + working-directory: ${{ github.workspace }}/Tests/build + run: | + $env:PATH="${{ env.VCPKG_INSTALLATION_ROOT }}\packages\yaml-cpp_x64-windows\bin;C:\Program Files (x86)\PhreeqcRM\bin;$env:PATH" + ctest -C ${{ env.BUILD_TYPE }} --output-on-failure diff --git a/.gitignore b/.gitignore index c41dadfa4..c03d3ad6a 100644 --- a/.gitignore +++ b/.gitignore @@ -21,6 +21,7 @@ Tests/vs2012/x64 # backup files *~ +.vshistory/ # autotools aclocal.m4 @@ -36,7 +37,7 @@ m4/lt~obsolete.m4 # ignore directories beginning with '_' -/_*/ +_*/ # dist files configure.ac.dist @@ -47,3 +48,6 @@ src/PhreeqcRM.h.dist src/IPhreeqcPhast/IPhreeqc/IPhreeqc.h.dist src/IPhreeqcPhast/IPhreeqc/Version.h.dist CMakeLists.txt.dist + +# mod files (vscode extension?) +src/phreeqcrm.mod diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 12a26d852..990102c32 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -4,9 +4,9 @@ repos: hooks: - id: end-of-file-fixer files: CMakeLists.txt|configure.ac|Makefile.am|\.xml$|\.yml$ - exclude: src/IPhreeqcPhast/IPhreeqc/phreeqcpp/test.xml$ + exclude: src/IPhreeqcPhast/IPhreeqc/phreeqcpp/test.xml$|Doxygen/DoxygenLayout.xml$ - id: trailing-whitespace files: CMakeLists.txt|configure.ac|Makefile.am|\.xml$|\.yml$ - exclude: src/IPhreeqcPhast/IPhreeqc/phreeqcpp/test.xml$ + exclude: src/IPhreeqcPhast/IPhreeqc/phreeqcpp/test.xml$|Doxygen/DoxygenLayout.xml$ - id: no-commit-to-branch args: [--branch, main, --branch, master, --branch, develop] diff --git a/CMakeLists.txt b/CMakeLists.txt index f99268ebd..4e854b8e1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,12 +28,11 @@ endif() include(GNUInstallDirs) option(PHREEQCRM_WITH_YAML_CPP "Build with yaml-cpp support" OFF) -find_package(yaml-cpp QUIET) if(PHREEQCRM_WITH_YAML_CPP) find_package(yaml-cpp REQUIRED) endif() -option(PHREEQCRM_DISABLE_OPENMP "Disable openmp" "OFF") +option(PHREEQCRM_DISABLE_OPENMP "Disable openmp" OFF) if(NOT PHREEQCRM_DISABLE_OPENMP) if(STANDALONE_BUILD EQUAL 1) # check for openmp @@ -42,174 +41,194 @@ if(NOT PHREEQCRM_DISABLE_OPENMP) endif() # check for MPI -option(PHREEQCRM_BUILD_MPI "Build MPI configuration" "OFF") +option(PHREEQCRM_BUILD_MPI "Build MPI configuration" OFF) if(PHREEQCRM_BUILD_MPI) find_package(MPI REQUIRED) endif() +option(PHREEQCRM_BUILD_PYTHON "Build python wrapper using SWIG" OFF) +if (PHREEQCRM_BUILD_PYTHON) + find_package(SWIG REQUIRED) + # find_package(Python 3.8 REQUIRED COMPONENTS Interpreter Development Development.Module NumPy) + # Set Python_ROOT_DIR to specify which python to use + # ie -DPython_ROOT_DIR=C:/Python38-x64 + find_package(Python 3.8 REQUIRED COMPONENTS Interpreter Development) +endif() + set(PhreeqcRM_SOURCES - src/IPhreeqcPhast/IPhreeqc/CSelectedOutput.cpp - src/IPhreeqcPhast/IPhreeqc/CSelectedOutput.hxx - src/IPhreeqcPhast/IPhreeqc/CVar.hxx - src/IPhreeqcPhast/IPhreeqc/Debug.h - src/IPhreeqcPhast/IPhreeqc/ErrorReporter.hxx - src/IPhreeqcPhast/IPhreeqc/IPhreeqc.cpp - src/IPhreeqcPhast/IPhreeqc/IPhreeqc.h - src/IPhreeqcPhast/IPhreeqc/IPhreeqc.hpp - src/IPhreeqcPhast/IPhreeqc/IPhreeqc_interface_F.cpp - src/IPhreeqcPhast/IPhreeqc/IPhreeqc_interface_F.h - src/IPhreeqcPhast/IPhreeqc/IPhreeqcCallbacks.h - src/IPhreeqcPhast/IPhreeqc/IPhreeqcLib.cpp - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/advection.cpp - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/basicsubs.cpp - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/cl1.cpp - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/common/Parser.cxx - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/common/Parser.h - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/common/PHRQ_base.cxx - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/common/PHRQ_base.h - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/common/PHRQ_exports.h - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/common/PHRQ_io.cpp - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/common/PHRQ_io.h - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/common/phrqtype.h - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/common/Utils.cxx - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/common/Utils.h - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/cvdense.cpp - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/cvdense.h - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/cvode.cpp - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/cvode.h - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/cxxKinetics.cxx - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/cxxKinetics.h - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/cxxMix.cxx - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/cxxMix.h - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/dense.cpp - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/dense.h - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/Dictionary.cpp - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/Dictionary.h - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/dumper.cpp - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/dumper.h - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/Exchange.cxx - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/Exchange.h - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/ExchComp.cxx - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/ExchComp.h - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/GasComp.cxx - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/GasComp.h - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/gases.cpp - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/GasPhase.cxx - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/GasPhase.h - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/global_structures.h - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/input.cpp - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/integrate.cpp - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/inverse.cpp - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/ISolution.cxx - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/ISolution.h - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/ISolutionComp.cxx - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/ISolutionComp.h - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/isotopes.cpp - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/kinetics.cpp - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/KineticsComp.cxx - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/KineticsComp.h - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/mainsubs.cpp - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/model.cpp - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/NA.h - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/NameDouble.cxx - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/NameDouble.h - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/NumKeyword.cxx - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/NumKeyword.h - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/nvector.cpp - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/nvector.h - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/nvector_serial.cpp - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/nvector_serial.h - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/parse.cpp - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/PBasic.cpp - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/PBasic.h - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/phqalloc.cpp - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/phqalloc.h - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/Phreeqc.cpp - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/Phreeqc.h - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/PhreeqcKeywords/Keywords.cpp - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/PhreeqcKeywords/Keywords.h - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/PHRQ_io_output.cpp - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/pitzer.cpp - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/pitzer_structures.cpp - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/PPassemblage.cxx - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/PPassemblage.h - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/PPassemblageComp.cxx - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/PPassemblageComp.h - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/prep.cpp - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/Pressure.cxx - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/Pressure.h - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/print.cpp - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/Reaction.cxx - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/Reaction.h - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/read.cpp - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/ReadClass.cxx - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/readtr.cpp - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/runner.cpp - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/runner.h - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/SelectedOutput.cpp - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/SelectedOutput.h - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/Serializer.cxx - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/Serializer.h - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/sit.cpp - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/smalldense.cpp - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/smalldense.h - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/Solution.cxx - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/Solution.h - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/SolutionIsotope.cxx - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/SolutionIsotope.h - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/spread.cpp - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/SS.cxx - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/SS.h - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/SSassemblage.cxx - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/SSassemblage.h - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/SScomp.cxx - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/SScomp.h - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/step.cpp - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/StorageBin.cxx - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/StorageBin.h - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/StorageBinList.cpp - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/StorageBinList.h - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/structures.cpp - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/sundialsmath.cpp - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/sundialsmath.h - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/sundialstypes.h - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/Surface.cxx - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/Surface.h - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/SurfaceCharge.cxx - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/SurfaceCharge.h - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/SurfaceComp.cxx - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/SurfaceComp.h - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/System.cxx - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/System.h - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/tally.cpp - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/Temperature.cxx - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/Temperature.h - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/tidy.cpp - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/transport.cpp - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/Use.cpp - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/Use.h - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/UserPunch.cpp - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/UserPunch.h - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/utilities.cpp - src/IPhreeqcPhast/IPhreeqc/thread.h - src/IPhreeqcPhast/IPhreeqc/Var.c - src/IPhreeqcPhast/IPhreeqc/Var.h - src/IPhreeqcPhast/IPhreeqc/Version.h - src/IPhreeqcPhast/IPhreeqcPhast.cxx - src/IPhreeqcPhast/IPhreeqcPhast.h - src/IPhreeqcPhast/IPhreeqcPhastLib.cpp - src/IPhreeqcPhast/IPhreeqcPhastLib.h - src/BMI_methods.cpp - src/BMI_Var.h - src/IrmResult.h - src/PhreeqcRM.cpp - src/PhreeqcRM.h - src/RM_interface_C.cpp - src/RM_interface_C.h - src/RM_interface_F.cpp - src/RM_interface_F.h - src/YAMLPhreeqcRM.cpp - src/YAMLPhreeqcRM.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/BMI_interface_F.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/BMI_interface_F.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/BMI_Var.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/BMI_Var.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/bmi.hxx + ${CMAKE_CURRENT_SOURCE_DIR}/src/BMIPhreeqcRM.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/BMIPhreeqcRM.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/CSelectedOutput.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/CSelectedOutput.hxx + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/CVar.hxx + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/Debug.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/ErrorReporter.hxx + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/IPhreeqc_interface_F.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/IPhreeqc_interface_F.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/IPhreeqc.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/IPhreeqc.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/IPhreeqc.hpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/IPhreeqcCallbacks.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/IPhreeqcLib.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/advection.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/basicsubs.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/cl1.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/common/Parser.cxx + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/common/Parser.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/common/PHRQ_base.cxx + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/common/PHRQ_base.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/common/PHRQ_exports.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/common/PHRQ_io.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/common/PHRQ_io.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/common/phrqtype.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/common/Utils.cxx + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/common/Utils.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/cvdense.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/cvdense.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/cvode.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/cvode.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/cxxKinetics.cxx + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/cxxKinetics.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/cxxMix.cxx + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/cxxMix.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/dense.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/dense.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/Dictionary.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/Dictionary.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/dumper.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/dumper.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/Exchange.cxx + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/Exchange.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/ExchComp.cxx + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/ExchComp.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/GasComp.cxx + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/GasComp.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/gases.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/GasPhase.cxx + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/GasPhase.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/global_structures.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/input.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/integrate.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/inverse.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/ISolution.cxx + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/ISolution.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/ISolutionComp.cxx + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/ISolutionComp.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/isotopes.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/kinetics.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/KineticsComp.cxx + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/KineticsComp.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/mainsubs.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/model.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/NA.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/NameDouble.cxx + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/NameDouble.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/NumKeyword.cxx + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/NumKeyword.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/nvector_serial.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/nvector_serial.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/nvector.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/nvector.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/parse.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/PBasic.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/PBasic.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/phqalloc.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/phqalloc.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/Phreeqc.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/Phreeqc.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/PhreeqcKeywords/Keywords.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/PhreeqcKeywords/Keywords.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/PHRQ_io_output.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/pitzer_structures.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/pitzer.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/PPassemblage.cxx + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/PPassemblage.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/PPassemblageComp.cxx + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/PPassemblageComp.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/prep.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/Pressure.cxx + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/Pressure.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/print.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/Reaction.cxx + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/Reaction.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/read.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/ReadClass.cxx + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/readtr.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/runner.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/runner.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/SelectedOutput.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/SelectedOutput.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/Serializer.cxx + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/Serializer.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/sit.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/smalldense.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/smalldense.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/Solution.cxx + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/Solution.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/SolutionIsotope.cxx + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/SolutionIsotope.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/spread.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/SS.cxx + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/SS.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/SSassemblage.cxx + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/SSassemblage.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/SScomp.cxx + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/SScomp.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/step.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/StorageBin.cxx + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/StorageBin.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/StorageBinList.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/StorageBinList.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/structures.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/sundialsmath.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/sundialsmath.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/sundialstypes.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/Surface.cxx + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/Surface.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/SurfaceCharge.cxx + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/SurfaceCharge.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/SurfaceComp.cxx + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/SurfaceComp.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/System.cxx + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/System.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/tally.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/Temperature.cxx + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/Temperature.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/tidy.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/transport.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/Use.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/Use.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/UserPunch.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/UserPunch.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/utilities.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/thread.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/Var.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/Var.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/Version.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqcPhast.cxx + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqcPhast.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqcPhastLib.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqcPhastLib.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/IrmResult.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/PhreeqcRM.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/PhreeqcRM.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/BMI_interface_F.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/RM_interface_C.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/RM_interface_C.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/RM_interface_F.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/RM_interface_F.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/RMVARS.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/VarManager.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/VarManager.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/YAML_interface_F.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/YAML_interface_F.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/YAMLPhreeqcRM.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/YAMLPhreeqcRM.h ) # setup include directories @@ -244,15 +263,18 @@ if(MSVC_VERSION EQUAL 1400 OR MSVC_VERSION GREATER 1400) target_compile_definitions(PhreeqcRM PRIVATE _SCL_SECURE_NO_WARNINGS) endif() +# init exportPackageDependencies +set(exportPackageDependencies "") + # yaml-cpp -if(yaml-cpp_FOUND) +if(PHREEQCRM_WITH_YAML_CPP AND yaml-cpp_FOUND) target_compile_definitions(PhreeqcRM PUBLIC USE_YAML) target_link_libraries(PhreeqcRM PUBLIC yaml-cpp) + # set(phreeqcrm_requires "yaml-cpp") + set(useyaml_define "-DUSE_YAML") + string(APPEND exportPackageDependencies "find_dependency(yaml-cpp)\n") endif() -# init exportPackageDependencies -set(exportPackageDependencies "") - # check for zlib if(NOT ZLIB_ROOT) if(EXISTS $ENV{ZLIB_ROOT}) @@ -286,6 +308,11 @@ if(MSVC AND BUILD_SHARED_LIBS AND PHREEQCRM_USE_ZLIB AND ZLIB_FOUND) endif() set(PhreeqcRM_Headers + ${PROJECT_SOURCE_DIR}/src/BMI_interface_F.h + ${PROJECT_SOURCE_DIR}/src/BMI_Var.h + ${PROJECT_SOURCE_DIR}/src/BMI_Var.h + ${PROJECT_SOURCE_DIR}/src/bmi.hxx + ${PROJECT_SOURCE_DIR}/src/BMIPhreeqcRM.h ${PROJECT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/IPhreeqc.h ${PROJECT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/IPhreeqc.hpp ${PROJECT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/IPhreeqcCallbacks.h @@ -303,12 +330,18 @@ set(PhreeqcRM_Headers ${PROJECT_SOURCE_DIR}/src/IrmResult.h ${PROJECT_SOURCE_DIR}/src/PhreeqcRM.h ${PROJECT_SOURCE_DIR}/src/RM_interface_C.h + ${PROJECT_SOURCE_DIR}/src/RMVARS.h + ${PROJECT_SOURCE_DIR}/src/VarManager.h + ${PROJECT_SOURCE_DIR}/src/YAML_interface_F.h ${PROJECT_SOURCE_DIR}/src/YAMLPhreeqcRM.h ) set(PhreeqcRM_SRC - ${PROJECT_SOURCE_DIR}/src/RM_interface.F90 + ${PROJECT_SOURCE_DIR}/src/BMI_interface.F90 + ${PROJECT_SOURCE_DIR}/src/BMI_not_implemented.inc ${PROJECT_SOURCE_DIR}/src/IPhreeqcPhast/IPhreeqc/IPhreeqc_interface.F90 + ${PROJECT_SOURCE_DIR}/src/RM_interface.F90 + ${PROJECT_SOURCE_DIR}/src/YAML_interface.F90 ) if(PHREEQCRM_BUILD_MPI) @@ -320,6 +353,7 @@ if(PHREEQCRM_BUILD_MPI) ##include_directories(${MPI_Fortran_INCLUDE_PATH}) target_link_libraries(PhreeqcRM PUBLIC MPI::MPI_Fortran) endif() + set(usempi_define "-DUSE_MPI") string(APPEND exportPackageDependencies "find_dependency(MPI)\n") else() if(NOT PHREEQCRM_DISABLE_OPENMP) @@ -334,6 +368,49 @@ else() endif() endif() +# pkg-config +# Skip imported link libraries +# +# set(PKGCONFIG_LIBS "") +# set(PKGCONFIG_INCS "") +# set(PHREEQCRM_OpenMP_C_FLAGS "") +# if(NOT PHREEQCRM_DISABLE_OPENMP AND OpenMP_FOUND) +# set(PHREEQCRM_OpenMP_C_FLAGS ${OpenMP_C_FLAGS}) +# endif() +# get_target_property(_link_libs PhreeqcRM LINK_LIBRARIES) +# if (_link_libs) +# foreach(_link_lib ${_link_libs}) +# cmake_print_variables(_link_lib) +# get_target_property(_imported ${_link_lib} IMPORTED) +# if(_imported) +# get_target_property(_incs ${_link_lib} INTERFACE_INCLUDE_DIRECTORIES) +# if(_incs) +# foreach(_inc ${_incs}) +# string(APPEND PKGCONFIG_INCS " -I${_inc}") +# endforeach() +# endif() +# get_target_property(_loc ${_link_lib} LOCATION) +# if (_loc) +# string(APPEND PKGCONFIG_LIBS " ${_loc}") +# else() +# get_target_property(_libs ${_link_lib} INTERFACE_LINK_LIBRARIES) +# if(_libs) +# foreach(_lib ${_libs}) +# string(APPEND PKGCONFIG_LIBS " ${_lib}") +# endforeach() +# endif() +# endif() +# endif() +# endforeach() +# if(PKGCONFIG_INCS) +# string(STRIP ${PKGCONFIG_INCS} PKGCONFIG_INCS) +# endif() +# if(PKGCONFIG_LIBS) +# string(STRIP ${PKGCONFIG_LIBS} PKGCONFIG_LIBS) +# endif() +# endif() +configure_file(phreeqcrm.cmake.in phreeqcrm.pc @ONLY) + # install if(STANDALONE_BUILD EQUAL 1) @@ -372,7 +449,11 @@ if(STANDALONE_BUILD EQUAL 1) ) install(FILES ${PhreeqcRM_SRC} - DESTINATION src + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/PhreeqcRM/src + ) + + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/phreeqcrm.pc + DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig ) else() # option(PHREEQCRM_INSTALL_TARGETS "" OFF) @@ -427,6 +508,10 @@ if(STANDALONE_BUILD EQUAL 1) add_subdirectory(doc) add_subdirectory(Doxygen) add_subdirectory(Tests) + + if (PHREEQCRM_BUILD_PYTHON) + add_subdirectory(src) + endif() endif() # Turn off Incremental Linking for Debug and RelWithDebInfo diff --git a/Doxygen/Doxyfile b/Doxygen/Doxyfile index eb880e503..b396dd548 100644 --- a/Doxygen/Doxyfile +++ b/Doxygen/Doxyfile @@ -277,7 +277,7 @@ ALIASES = # members will be omitted, etc. # The default value is: NO. -OPTIMIZE_OUTPUT_FOR_C = YES +OPTIMIZE_OUTPUT_FOR_C = NO # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or # Python sources only. Doxygen will then generate output that is more tailored @@ -328,7 +328,14 @@ OPTIMIZE_OUTPUT_SLICE = NO # # Note see also the list of default file extension mappings. -EXTENSION_MAPPING = +EXTENSION_MAPPING = f95=FortranFree \ + f90=FortranFree \ + f03=FortranFree \ + f08=FortranFree \ + f2003=FortranFree \ + f2008=FortranFree \ + F95=FortranFree \ + docs=FortranFree # If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments # according to the Markdown format, which allows for more readable @@ -355,7 +362,7 @@ TOC_INCLUDE_HEADINGS = 5 # globally by setting AUTOLINK_SUPPORT to NO. # The default value is: YES. -AUTOLINK_SUPPORT = NO +AUTOLINK_SUPPORT = YES # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should set this @@ -485,7 +492,7 @@ NUM_PROC_THREADS = 1 # normally produced when WARNINGS is set to YES. # The default value is: NO. -EXTRACT_ALL = NO +EXTRACT_ALL = YES # If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will # be included in the documentation. @@ -509,7 +516,7 @@ EXTRACT_PACKAGE = NO # included in the documentation. # The default value is: NO. -EXTRACT_STATIC = NO +EXTRACT_STATIC = YES # If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined # locally in source files will be included in the documentation. If set to NO, @@ -525,7 +532,7 @@ EXTRACT_LOCAL_CLASSES = YES # included. # The default value is: NO. -EXTRACT_LOCAL_METHODS = NO +EXTRACT_LOCAL_METHODS = YES # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called @@ -594,14 +601,14 @@ INTERNAL_DOCS = NO # YES. # The default value is: system dependent. -CASE_SENSE_NAMES = NO +CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with # their full class and namespace scopes in the documentation. If set to YES, the # scope will be hidden. # The default value is: NO. -HIDE_SCOPE_NAMES = YES +HIDE_SCOPE_NAMES = NO # If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will # append additional text to a page's title, such as Class Reference. If set to @@ -729,7 +736,7 @@ ENABLED_SECTIONS = # documentation regardless of this setting. # Minimum value: 0, maximum value: 10000, default value: 30. -MAX_INITIALIZER_LINES = 30 +MAX_INITIALIZER_LINES = 300 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated at # the bottom of the documentation of classes and structs. If set to YES, the @@ -773,7 +780,7 @@ FILE_VERSION_FILTER = # DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE # tag is left empty. -LAYOUT_FILE = DoxygenLayout.xml +LAYOUT_FILE = # The CITE_BIB_FILES tag can be used to specify one or more bib files containing # the reference definitions. This must be a list of .bib files. The .bib @@ -827,7 +834,7 @@ WARN_IF_DOC_ERROR = YES # EXTRACT_ALL is set to YES then this flag will automatically be disabled. # The default value is: NO. -WARN_NO_PARAMDOC = NO +WARN_NO_PARAMDOC = YES # If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when # a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS @@ -868,7 +875,8 @@ INPUT = ../src/PhreeqcRM.h \ ../src/RM_interface_C.h \ ../src/RM_interface.F90 \ ../src/IrmResult.h \ - ../src/YAMLPhreeqcRM.h + ../src/YAMLPhreeqcRM.h \ + ../src/YAML_interface.F90 # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses @@ -929,7 +937,11 @@ FILE_PATTERNS = *.c \ *.mm \ *.dox \ *.py \ + *.pyw \ *.f90 \ + *.f95 \ + *.f03 \ + *.f08 \ *.f \ *.for \ *.tcl \ @@ -937,8 +949,7 @@ FILE_PATTERNS = *.c \ *.vhdl \ *.ucf \ *.qsf \ - *.as \ - *.js + *.docs # The RECURSIVE tag can be used to specify whether or not subdirectories should # be searched for input files as well. @@ -1583,7 +1594,7 @@ DISABLE_INDEX = NO # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. -GENERATE_TREEVIEW = NO +GENERATE_TREEVIEW = YES # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that # doxygen will group on one line in the generated HTML documentation. @@ -1627,7 +1638,7 @@ HTML_FORMULA_FORMAT = png # Minimum value: 8, maximum value: 50, default value: 10. # This tag requires that the tag GENERATE_HTML is set to YES. -FORMULA_FONTSIZE = 10 +FORMULA_FONTSIZE = 12 # Use the FORMULA_TRANSPARENT tag to determine whether or not the images # generated for formulas are transparent PNGs. Transparent PNGs are not @@ -1839,7 +1850,7 @@ LATEX_MAKEINDEX_CMD = makeindex # The default value is: NO. # This tag requires that the tag GENERATE_LATEX is set to YES. -COMPACT_LATEX = NO +COMPACT_LATEX = YES # The PAPER_TYPE tag can be used to set the paper type that is used by the # printer. @@ -2333,7 +2344,7 @@ EXTERNAL_PAGES = YES # powerful graphs. # The default value is: YES. -CLASS_DIAGRAMS = NO +CLASS_DIAGRAMS = YES # You can include diagrams made with dia in doxygen documentation. Doxygen will # then run dia to produce the diagram and insert it in the documentation. The @@ -2355,7 +2366,7 @@ HIDE_UNDOC_RELATIONS = YES # set to NO # The default value is: YES. -HAVE_DOT = NO +HAVE_DOT = YES # The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed # to run in parallel. When set to 0 doxygen will base this on the number of diff --git a/Doxygen/DoxygenLayout.xml b/Doxygen/DoxygenLayout.xml index 4e7fe9af7..cb4ab179c 100644 --- a/Doxygen/DoxygenLayout.xml +++ b/Doxygen/DoxygenLayout.xml @@ -1,32 +1,45 @@ - + - - - - + + + + + - + @@ -94,8 +107,13 @@ + + + + + @@ -105,6 +123,8 @@ + + @@ -120,11 +140,16 @@ + + + + + @@ -135,6 +160,8 @@ + + @@ -154,6 +181,8 @@ + + @@ -173,6 +202,8 @@ + + diff --git a/Doxygen/Makefile b/Doxygen/Makefile index 2b58f61e2..1d0882092 100644 --- a/Doxygen/Makefile +++ b/Doxygen/Makefile @@ -1,3 +1,4 @@ +USE_YAML = true DOXYGEN ?= doxygen all: diff --git a/Doxygen/lower_case.bat b/Doxygen/lower_case.bat index 95b5d3a5b..2bff3f271 100644 --- a/Doxygen/lower_case.bat +++ b/Doxygen/lower_case.bat @@ -1,5 +1,7 @@ set RM_INTERFACE_F90=..\src\RM_interface.F90 REM sed -i -e "s/PhreeqcRM/phreeqcrm/g" %RM_INTERFACE_F90% +sed -i -e "s/GetGridCellCountYAML/getgridcellcountyaml/g" %RM_INTERFACE_F90% +sed -i -e "s/SetGridCellCountYAML/setgridcellcountyaml/g" %RM_INTERFACE_F90% sed -i -e "s/RM_Abort/rm_abort/g" %RM_INTERFACE_F90% sed -i -e "s/RM_Abort/rm_abort/g" %RM_INTERFACE_F90% sed -i -e "s/RM_CloseFiles/rm_closefiles/g" %RM_INTERFACE_F90% @@ -32,6 +34,8 @@ sed -i -e "s/RM_GetIPhreeqcId/rm_getiphreeqcid/g" %RM_INTERFACE_F90% sed -i -e "s/RM_GetMpiMyself/rm_getmpimyself/g" %RM_INTERFACE_F90% sed -i -e "s/RM_GetMpiTasks/rm_getmpitasks/g" %RM_INTERFACE_F90% sed -i -e "s/RM_GetNthSelectedOutputUserNumber/rm_getnthselectedoutputusernumber/g" %RM_INTERFACE_F90% +sed -i -e "s/RM_GetPorosity/rm_getporosity/g" %RM_INTERFACE_F90% +sed -i -e "s/RM_GetPressure/rm_getpressure/g" %RM_INTERFACE_F90% sed -i -e "s/RM_GetSaturation/rm_getsaturation/g" %RM_INTERFACE_F90% sed -i -e "s/RM_GetSelectedOutputColumnCount/rm_getselectedoutputcolumncount/g" %RM_INTERFACE_F90% sed -i -e "s/RM_GetSelectedOutputCount/rm_getselectedoutputcount/g" %RM_INTERFACE_F90% @@ -127,6 +131,28 @@ sed -i -e "s/RM_GetSIName/rm_getsiname/g" %RM_INTERFACE_F90% sed -i -e "s/RM_StateSave/rm_statesave/g" %RM_INTERFACE_F90% sed -i -e "s/RM_StateApply/rm_stateapply/g" %RM_INTERFACE_F90% sed -i -e "s/RM_StateDelete/rm_statedelete/g" %RM_INTERFACE_F90% +sed -i -e "s/RM_BMI_Finalize/rm_bmi_finalize/g" %RM_INTERFACE_F90% +sed -i -e "s/RM_BMI_GetComponentName/rm_bmi_getcomponentname/g" %RM_INTERFACE_F90% +sed -i -e "s/RM_BMI_GetCurrentTime/rm_bmi_getcurrenttime/g" %RM_INTERFACE_F90% +sed -i -e "s/RM_BMI_GetEndTime/rm_bmi_getendtime/g" %RM_INTERFACE_F90% +sed -i -e "s/RM_BMI_GetInputItemCount/rm_bmi_getinputitemcount/g" %RM_INTERFACE_F90% +sed -i -e "s/RM_BMI_GetInputVarNames/rm_bmi_getinputvarnames/g" %RM_INTERFACE_F90% +sed -i -e "s/RM_BMI_GetOutputItemCount/rm_bmi_getoutputitemcount/g" %RM_INTERFACE_F90% +sed -i -e "s/RM_BMI_GetOutputVarNames/rm_bmi_getoutputvarnames/g" %RM_INTERFACE_F90% +sed -i -e "s/RM_BMI_GetTimeStep/rm_bmi_gettimestep/g" %RM_INTERFACE_F90% +sed -i -e "s/RM_BMI_GetTimeUnits/rm_bmi_gettimeunits/g" %RM_INTERFACE_F90% +sed -i -e "s/RM_BMI_GetValue/rm_bmi_getvalue/g" %RM_INTERFACE_F90% +sed -i -e "s/RM_BMI_GetVarItemsize/rm_bmi_getvaritemsize/g" %RM_INTERFACE_F90% +sed -i -e "s/RM_BMI_GetVarNbytes/rm_bmi_getvarnbytes/g" %RM_INTERFACE_F90% +sed -i -e "s/RM_BMI_GetVarType/rm_bmi_getvartype/g" %RM_INTERFACE_F90% +sed -i -e "s/RM_BMI_GetVarUnits/rm_bmi_getvarunits/g" %RM_INTERFACE_F90% +sed -i -e "s/RM_BMI_Initialize/rm_bmi_initialize/g" %RM_INTERFACE_F90% +sed -i -e "s/RM_BMI_SetValue/rm_bmi_setvalue/g" %RM_INTERFACE_F90% +sed -i -e "s/RM_BMI_Update/rm_bmi_update/g" %RM_INTERFACE_F90% +sed -i -e "s/RM_GetComponents/rm_getcomponents/g" %RM_INTERFACE_F90% +sed -i -e "s/RM_GetGridCellCountYAML/rm_getgridcellcountyaml/g" %RM_INTERFACE_F90% +sed -i -e "s/RM_GetSelectedOutputHeadings/rm_getselectedoutputheadings/g" %RM_INTERFACE_F90% +sed -i -e "s/RM_GetTemperature/rm_gettemperature/g" %RM_INTERFACE_F90% +del sed* -del sed* \ No newline at end of file diff --git a/Doxygen/lower_case.sh b/Doxygen/lower_case.sh index a76b524a5..0a1ba815f 100755 --- a/Doxygen/lower_case.sh +++ b/Doxygen/lower_case.sh @@ -1,6 +1,8 @@ #!/bin/sh export RM_INTERFACE_F90=../src/RM_interface.F90 # sed -i -e "s/PhreeqcRM/phreeqcrm/g" $RM_INTERFACE_F90 +sed -i -e "s/GetGridCellCountYAML/getgridcellcountyaml/g" $RM_INTERFACE_F90 +sed -i -e "s/SetGridCellCountYAML/setgridcellcountyaml/g" $RM_INTERFACE_F90 sed -i -e "s/RM_Abort/rm_abort/g" $RM_INTERFACE_F90 sed -i -e "s/RM_Abort/rm_abort/g" $RM_INTERFACE_F90 sed -i -e "s/RM_CloseFiles/rm_closefiles/g" $RM_INTERFACE_F90 @@ -33,6 +35,8 @@ sed -i -e "s/RM_GetIPhreeqcId/rm_getiphreeqcid/g" $RM_INTERFACE_F90 sed -i -e "s/RM_GetMpiMyself/rm_getmpimyself/g" $RM_INTERFACE_F90 sed -i -e "s/RM_GetMpiTasks/rm_getmpitasks/g" $RM_INTERFACE_F90 sed -i -e "s/RM_GetNthSelectedOutputUserNumber/rm_getnthselectedoutputusernumber/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetPorosity/rm_getporosity/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetPressure/rm_getpressure/g" $RM_INTERFACE_F90 sed -i -e "s/RM_GetSaturation/rm_getsaturation/g" $RM_INTERFACE_F90 sed -i -e "s/RM_GetSelectedOutputColumnCount/rm_getselectedoutputcolumncount/g" $RM_INTERFACE_F90 sed -i -e "s/RM_GetSelectedOutputCount/rm_getselectedoutputcount/g" $RM_INTERFACE_F90 @@ -128,3 +132,152 @@ sed -i -e "s/RM_GetSIName/rm_getsiname/g" $RM_INTERFACE_F90 sed -i -e "s/RM_StateSave/rm_statesave/g" $RM_INTERFACE_F90 sed -i -e "s/RM_StateApply/rm_stateapply/g" $RM_INTERFACE_F90 sed -i -e "s/RM_StateDelete/rm_statedelete/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_Abort/rm_abort/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_Abort/rm_abort/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_CloseFiles/rm_closefiles/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_Concentrations2Utility/rm_concentrations2utility/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_CreateMapping/rm_createmapping/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_Create/rm_create/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_DecodeError/rm_decodeerror/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_Destroy/rm_destroy/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_DumpModule/rm_dumpmodule/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_ErrorMessage/rm_errormessage/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_FindComponents/rm_findcomponents/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetBackwardMapping/rm_getbackwardmapping/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetChemistryCellCount/rm_getchemistrycellcount/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetComponentCount/rm_getcomponentcount/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetComponent/rm_getcomponent/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetConcentrations/rm_getconcentrations/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetCurrentSelectedOutputUserNumber/rm_getcurrentselectedoutputusernumber/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetDensity/rm_getdensity/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetEndCell/rm_getendcell/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetErrorString/rm_geterrorstring/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetErrorStringLength/rm_geterrorstringlength/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetFilePrefix/rm_getfileprefix/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetGasCompMoles/rm_getgascompmoles/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetGasCompPhi/rm_getgascompphi/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetGasCompPressures/rm_getgascomppressures/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetGasPhaseVolume/rm_getgasphasevolume/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetGfw/rm_getgfw/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetGridCellCount/rm_getgridcellcount/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetIPhreeqcId/rm_getiphreeqcid/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetMpiMyself/rm_getmpimyself/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetMpiTasks/rm_getmpitasks/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetNthSelectedOutputUserNumber/rm_getnthselectedoutputusernumber/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetSaturation/rm_getsaturation/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetSelectedOutputColumnCount/rm_getselectedoutputcolumncount/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetSelectedOutputCount/rm_getselectedoutputcount/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetSelectedOutputHeading/rm_getselectedoutputheading/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetSelectedOutputRowCount/rm_getselectedoutputrowcount/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetSelectedOutput/rm_getselectedoutput/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetSolutionVolume/rm_getsolutionvolume/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetSpeciesConcentrations/rm_getspeciesconcentrations/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetSpeciesCount/rm_getspeciescount/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetSpeciesD25/rm_getspeciesd25/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetSpeciesLog10Molalities/rm_getspecieslog10molalities/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetSpeciesName/rm_getspeciesname/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetSpeciesSaveOn/rm_getspeciessaveon/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetSpeciesZ/rm_getspeciesz/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetStartCell/rm_getstartcell/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetThreadCount/rm_getthreadcount/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetTimeConversion/rm_gettimeconversion/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetTimeStep/rm_gettimestep/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetTime/rm_gettime/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_InitialPhreeqc2Concentrations/rm_initialphreeqc2concentrations/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_InitialPhreeqc2Module/rm_initialphreeqc2module/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_InitialPhreeqcCell2Module/rm_initialphreeqccell2module/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_InitialPhreeqc2SpeciesConcentrations/rm_initialphreeqc2speciesconcentrations/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_LoadDatabase/rm_loaddatabase/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_LogMessage/rm_logmessage/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_MpiWorkerBreak/rm_mpiworkerbreak/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_MpiWorker/rm_mpiworker/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_OpenFiles/rm_openfiles/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_OutputMessage/rm_outputmessage/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_RunCells/rm_runcells/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_RunFile/rm_runfile/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_RunString/rm_runstring/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_ScreenMessage/rm_screenmessage/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_SetComponentH2O/rm_setcomponenth2o/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_SetConcentrations/rm_setconcentrations/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_SetCurrentSelectedOutputUserNumber/rm_setcurrentselectedoutputusernumber/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_SetDensity/rm_setdensity/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_SetDumpFileName/rm_setdumpfilename/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_SetErrorHandlerMode/rm_seterrorhandlermode/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_SetErrorOn/rm_seterroron/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_SetFilePrefix/rm_setfileprefix/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_SetGasCompMoles/rm_setgascompmoles/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_SetGasPhaseVolume/rm_setgasphasevolume/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_SetMpiWorkerCallback/rm_setmpiworkercallback/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_SetNthSelectedOutput/rm_setnthselectedoutput/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_SetPartitionUZSolids/rm_setpartitionuzsolids/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_SetPorosity/rm_setporosity/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_SetPrintChemistryMask/rm_setprintchemistrymask/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_SetPrintChemistryOn/rm_setprintchemistryon/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_SetPressure/rm_setpressure/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_SetRebalanceFraction/rm_setrebalancefraction/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_SetRebalanceByCell/rm_setrebalancebycell/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_SetRepresentativeVolume/rm_setrepresentativevolume/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_SetSaturation/rm_setsaturation/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_SetScreenOn/rm_setscreenon/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_SetSelectedOutputOn/rm_setselectedoutputon/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_SetSpeciesSaveOn/rm_setspeciessaveon/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_SetTemperature/rm_settemperature/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_SetTimeConversion/rm_settimeconversion/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_SetTimeStep/rm_settimestep/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_SetTime/rm_settime/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_SetUnitsExchange/rm_setunitsexchange/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_SetUnitsGasPhase/rm_setunitsgasphase/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_SetUnitsKinetics/rm_setunitskinetics/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_SetUnitsPPassemblage/rm_setunitsppassemblage/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_SetUnitsSolution/rm_setunitssolution/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_SetUnitsSSassemblage/rm_setunitsssassemblage/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_SetUnitsSSassemblage/rm_setunitsssassemblage/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_SetUnitsSurface/rm_setunitssurface/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_SpeciesConcentrations2Module/rm_speciesconcentrations2module/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_UseSolutionDensityVolume/rm_usesolutiondensityvolume/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_WarningMessage/rm_warningmessage/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetSpeciesLog10Gammas/rm_getspecieslog10gammas/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetExchangeSpeciesCount/rm_getexchangespeciescount/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetExchangeSpeciesName/rm_getexchangespeciesname/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetExchangeName/rm_getexchangename/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetSurfaceSpeciesCount/rm_getsurfacespeciescount/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetSurfaceSpeciesName/rm_getsurfacespeciesname/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetSurfaceType/rm_getsurfacetype/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetSurfaceName/rm_getsurfacename/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetEquilibriumPhasesCount/rm_getequilibriumphasescount/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetEquilibriumPhasesName/rm_getequilibriumphasesname/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetGasComponentsCount/rm_getgascomponentscount/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetGasComponentsName/rm_getgascomponentsname/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetKineticReactionsCount/rm_getkineticreactionscount/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetKineticReactionsName/rm_getkineticreactionsname/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetSolidSolutionComponentsCount/rm_getsolidsolutioncomponentscount/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetSolidSolutionComponentsName/rm_getsolidsolutioncomponentsname/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetSolidSolutionName/rm_getsolidsolutionname/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetSICount/rm_getsicount/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetSIName/rm_getsiname/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_StateSave/rm_statesave/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_StateApply/rm_stateapply/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_StateDelete/rm_statedelete/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_BMI_Finalize/rm_bmi_finalize/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_BMI_GetComponentName/rm_bmi_getcomponentname/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_BMI_GetCurrentTime/rm_bmi_getcurrenttime/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_BMI_GetEndTime/rm_bmi_getendtime/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_BMI_GetInputItemCount/rm_bmi_getinputitemcount/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_BMI_GetInputVarNames/rm_bmi_getinputvarnames/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_BMI_GetOutputItemCount/rm_bmi_getoutputitemcount/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_BMI_GetOutputVarNames/rm_bmi_getoutputvarnames/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_BMI_GetTimeStep/rm_bmi_gettimestep/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_BMI_GetTimeUnits/rm_bmi_gettimeunits/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_BMI_GetValue/rm_bmi_getvalue/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_BMI_GetVarItemsize/rm_bmi_getvaritemsize/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_BMI_GetVarNbytes/rm_bmi_getvarnbytes/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_BMI_GetVarType/rm_bmi_getvartype/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_BMI_GetVarUnits/rm_bmi_getvarunits/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_BMI_Initialize/rm_bmi_initialize/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_BMI_SetValue/rm_bmi_setvalue/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_BMI_Update/rm_bmi_update/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetComponents/rm_getcomponents/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetGridCellCountYAML/rm_getgridcellcountyaml/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetSelectedOutputHeadings/rm_getselectedoutputheadings/g" $RM_INTERFACE_F90 +sed -i -e "s/RM_GetTemperature/rm_gettemperature/g" $RM_INTERFACE_F90 + diff --git a/Doxygen/upper_case.bat b/Doxygen/upper_case.bat index c180a0fc2..401406baf 100644 --- a/Doxygen/upper_case.bat +++ b/Doxygen/upper_case.bat @@ -1,3 +1,11 @@ +@FOR %%f IN (.\html\*.html) DO @( + @sed -i "s/getgridcellcountyaml/GetGridCellCountYAML/g" %%f + @del sed* +) +@FOR %%f IN (.\html\*.html) DO @( + @sed -i "s/setgridcellcountyaml/SetGridCellCountYAML/g" %%f + @del sed* +) @FOR %%f IN (.\html\*.html) DO @( @sed -i "s/rm_abort/RM_Abort/g" %%f @del sed* @@ -122,6 +130,14 @@ @sed -i "s/rm_getnthselectedoutputusernumber/RM_GetNthSelectedOutputUserNumber/g" %%f @del sed* ) +@FOR %%f IN (.\html\*.html) DO @( + @sed -i "s/rm_getporosity/RM_GetPorosity/g" %%f + @del sed* +) +@FOR %%f IN (.\html\*.html) DO @( + @sed -i "s/rm_getpressure/RM_GetPressure/g" %%f + @del sed* +) @FOR %%f IN (.\html\*.html) DO @( @sed -i "s/rm_getsaturation/RM_GetSaturation/g" %%f @del sed* @@ -503,6 +519,95 @@ @del sed* ) +@FOR %%f IN (.\html\*.html) DO @( +@sed -i "s/\brm_bmi_finalize\b/RM_BMI_Finalize/g" %%f + @del sed* +) +@FOR %%f IN (.\html\*.html) DO @( +@sed -i "s/\brm_bmi_getcomponentname\b/RM_BMI_GetComponentName/g" %%f + @del sed* +) +@FOR %%f IN (.\html\*.html) DO @( +@sed -i "s/\brm_bmi_getcurrenttime\b/RM_BMI_GetCurrentTime/g" %%f + @del sed* +) +@FOR %%f IN (.\html\*.html) DO @( +@sed -i "s/\brm_bmi_getendtime\b/RM_BMI_GetEndTime/g" %%f + @del sed* +) +@FOR %%f IN (.\html\*.html) DO @( +@sed -i "s/\brm_bmi_getinputitemcount\b/RM_BMI_GetInputItemCount/g" %%f + @del sed* +) +@FOR %%f IN (.\html\*.html) DO @( +@sed -i "s/\brm_bmi_getinputvarnames\b/RM_BMI_GetInputVarNames/g" %%f + @del sed* +) +@FOR %%f IN (.\html\*.html) DO @( +@sed -i "s/\brm_bmi_getoutputitemcount\b/RM_BMI_GetOutputItemCount/g" %%f + @del sed* +) +@FOR %%f IN (.\html\*.html) DO @( +@sed -i "s/\brm_bmi_getoutputvarnames\b/RM_BMI_GetOutputVarNames/g" %%f + @del sed* +) +@FOR %%f IN (.\html\*.html) DO @( +@sed -i "s/\brm_bmi_gettimestep\b/RM_BMI_GetTimeStep/g" %%f + @del sed* +) +@FOR %%f IN (.\html\*.html) DO @( +@sed -i "s/\brm_bmi_gettimeunits\b/RM_BMI_GetTimeUnits/g" %%f + @del sed* +) +@FOR %%f IN (.\html\*.html) DO @( +@sed -i "s/\brm_bmi_getvalue\b/RM_BMI_GetValue/g" %%f + @del sed* +) +@FOR %%f IN (.\html\*.html) DO @( +@sed -i "s/\brm_bmi_getvaritemsize\b/RM_BMI_GetVarItemsize/g" %%f + @del sed* +) +@FOR %%f IN (.\html\*.html) DO @( +@sed -i "s/\brm_bmi_getvarnbytes\b/RM_BMI_GetVarNbytes/g" %%f + @del sed* +) +@FOR %%f IN (.\html\*.html) DO @( +@sed -i "s/\brm_bmi_getvartype\b/RM_BMI_GetVarType/g" %%f + @del sed* +) +@FOR %%f IN (.\html\*.html) DO @( +@sed -i "s/\brm_bmi_getvarunits\b/RM_BMI_GetVarUnits/g" %%f + @del sed* +) +@FOR %%f IN (.\html\*.html) DO @( +@sed -i "s/\brm_bmi_initialize\b/RM_BMI_Initialize/g" %%f + @del sed* +) +@FOR %%f IN (.\html\*.html) DO @( +@sed -i "s/\brm_bmi_setvalue\b/RM_BMI_SetValue/g" %%f + @del sed* +) +@FOR %%f IN (.\html\*.html) DO @( +@sed -i "s/\brm_bmi_update\b/RM_BMI_Update/g" %%f + @del sed* +) +@FOR %%f IN (.\html\*.html) DO @( +@sed -i "s/\brm_getcomponents\b/RM_GetComponents/g" %%f + @del sed* +) +@FOR %%f IN (.\html\*.html) DO @( +@sed -i "s/\brm_getgridcellcountyaml\b/RM_GetGridCellCountYAML/g" %%f + @del sed* +) +@FOR %%f IN (.\html\*.html) DO @( +@sed -i "s/\brm_getselectedoutputheadings\b/RM_GetSelectedOutputHeadings/g" %%f + @del sed* +) +@FOR %%f IN (.\html\*.html) DO @( +@sed -i "s/\brm_gettemperature\b/RM_GetTemperature/g" %%f + @del sed* +) + @REM Rename PhreeqcRM to mixed case @FOR %%f IN (.\html\*.html) DO @( @sed -i "s/\bphreeqcrm\b/PhreeqcRM/g" %%f diff --git a/Doxygen/upper_case.sh b/Doxygen/upper_case.sh index e4d78576f..11f5ea325 100755 --- a/Doxygen/upper_case.sh +++ b/Doxygen/upper_case.sh @@ -1,4 +1,10 @@ #!/bin/sh +for f in html/*.html; do + sed -i "s/getgridcellcountyaml/GetGridCellCountYAML/g" $f +done +for f in html/*.html; do + sed -i "s/setgridcellcountyaml/SetGridCellCountYAML/g" $f +done for f in html/*.html; do sed -i "s/rm_abort/RM_Abort/g" $f done @@ -103,6 +109,12 @@ done for f in html/*.html; do sed -i "s/rm_getnthselectedoutputusernumber/RM_GetNthSelectedOutputUserNumber/g" $f done +for f in html/*.html; do + sed -i "s/rm_getporosity/RM_GetPorosity/g" $f +done +for f in html/*.html; do + sed -i "s/rm_getpressure/RM_GetPressure/g" $f +done for f in html/*.html; do sed -i "s/rm_getsaturation/RM_GetSaturation/g" $f done @@ -379,7 +391,72 @@ done for f in html/*.html; do sed -i "s/rm_statedelete/RM_StateDelete/g" $f done - +for f in html/*.html; do + sed -i "s/rm_bmi_finalize/RM_BMI_Finalize/g" $f +done +for f in html/*.html; do + sed -i "s/rm_bmi_getcomponentname/RM_BMI_GetComponentName/g" $f +done +for f in html/*.html; do + sed -i "s/rm_bmi_getcurrenttime/RM_BMI_GetCurrentTime/g" $f +done +for f in html/*.html; do + sed -i "s/rm_bmi_getendtime/RM_BMI_GetEndTime/g" $f +done +for f in html/*.html; do + sed -i "s/rm_bmi_getinputitemcount/RM_BMI_GetInputItemCount/g" $f +done +for f in html/*.html; do + sed -i "s/rm_bmi_getinputvarnames/RM_BMI_GetInputVarNames/g" $f +done +for f in html/*.html; do + sed -i "s/rm_bmi_getoutputitemcount/RM_BMI_GetOutputItemCount/g" $f +done +for f in html/*.html; do + sed -i "s/rm_bmi_getoutputvarnames/RM_BMI_GetOutputVarNames/g" $f +done +for f in html/*.html; do + sed -i "s/rm_bmi_gettimestep/RM_BMI_GetTimeStep/g" $f +done +for f in html/*.html; do + sed -i "s/rm_bmi_gettimeunits/RM_BMI_GetTimeUnits/g" $f +done +for f in html/*.html; do + sed -i "s/rm_bmi_getvalue/RM_BMI_GetValue/g" $f +done +for f in html/*.html; do + sed -i "s/rm_bmi_getvaritemsize/RM_BMI_GetVarItemsize/g" $f +done +for f in html/*.html; do + sed -i "s/rm_bmi_getvarnbytes/RM_BMI_GetVarNbytes/g" $f +done +for f in html/*.html; do + sed -i "s/rm_bmi_getvartype/RM_BMI_GetVarType/g" $f +done +for f in html/*.html; do + sed -i "s/rm_bmi_getvarunits/RM_BMI_GetVarUnits/g" $f +done +for f in html/*.html; do + sed -i "s/rm_bmi_initialize/RM_BMI_Initialize/g" $f +done +for f in html/*.html; do + sed -i "s/rm_bmi_setvalue/RM_BMI_SetValue/g" $f +done +for f in html/*.html; do + sed -i "s/rm_bmi_update/RM_BMI_Update/g" $f +done +for f in html/*.html; do + sed -i "s/rm_getcomponents/RM_GetComponents/g" $f +done +for f in html/*.html; do + sed -i "s/rm_getgridcellcountyaml/RM_GetGridCellCountYAML/g" $f +done +for f in html/*.html; do + sed -i "s/rm_getselectedoutputheadings/RM_GetSelectedOutputHeadings/g" $f +done +for f in html/*.html; do + sed -i "s/rm_gettemperature/RM_GetTemperature/g" $f +done # Rename PhreeqcRM to mixed case for f in html/*.html; do sed -i "s/\bphreeqcrm\b/PhreeqcRM/g" $f @@ -387,7 +464,7 @@ done # Change Titles sed -i "s/PhreeqcRM Module Reference/PhreeqcRM Fortran Module Reference/g" html/namespacephreeqcrm.html -sed -i "s/RM_interface_C.h File Reference/PhreeqcRM C Reference/g" html/_r_m__interface___c_8h.html -sed -i "s/PhreeqcRM Class Reference/PhreeqcRM C++ Class Reference/g" html/class_phreeqc_r_m.html +sed -i "s/RM_interface_C.h File Reference/PhreeqcRM C Reference/g" html/RM__interface__C_8h.html +sed -i "s/PhreeqcRM Class Reference/PhreeqcRM C++ Class Reference/g" html/classPhreeqcRM.html echo finished diff --git a/Makefile.am b/Makefile.am index 93d099494..48cf5f68b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,30 +1,49 @@ ACLOCAL_AMFLAGS=-I m4 -PHREEQCRM_CMAKELISTS=\ +PHREEQCRM_EXTRA_DIST=\ CMakeLists.txt\ - PhreeqcRMConfig.cmake.in + phreeqcrm.cmake.in\ + PhreeqcRMConfig.cmake.in\ + src/CMakeLists.txt\ + src/numpy.i\ + src/PhreeqcRM.i\ + src/pyfragments.swg.in\ + src/swig/CMakeLists.txt\ + src/swig/python/CMakeLists.txt\ + src/swig/python/PhreeqcRM_docstrings.i\ + src/swig/python/SimpleAdvect.py -EXTRA_DIST=$(PHREEQCRM_CMAKELISTS) +EXTRA_DIST=$(PHREEQCRM_EXTRA_DIST) AM_CPPFLAGS=-I$(top_srcdir)/src/IPhreeqcPhast -I$(top_srcdir)/src/IPhreeqcPhast/IPhreeqc -I$(top_srcdir)/src/IPhreeqcPhast/IPhreeqc/phreeqcpp -I$(top_srcdir)/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/common -I$(top_srcdir)/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/PhreeqcKeywords AM_LDFLAGS=-release 3.0.0 +pkgconfigdir = $(datadir)/pkgconfig +pkgconfig_DATA = phreeqcrm.pc + # libtool libraries to build lib_LTLIBRARIES=libphreeqcrm.la # library sources for libphreeqcrm.la libphreeqcrm_la_SOURCES=\ + src/BMI_interface_F.cpp\ + src/BMI_interface_F.h\ + src/BMI_Var.cpp\ + src/BMI_Var.h\ + src/bmi.hxx\ + src/BMIPhreeqcRM.cpp\ + src/BMIPhreeqcRM.h\ src/IPhreeqcPhast/IPhreeqc/CSelectedOutput.cpp\ src/IPhreeqcPhast/IPhreeqc/CSelectedOutput.hxx\ src/IPhreeqcPhast/IPhreeqc/CVar.hxx\ src/IPhreeqcPhast/IPhreeqc/Debug.h\ src/IPhreeqcPhast/IPhreeqc/ErrorReporter.hxx\ + src/IPhreeqcPhast/IPhreeqc/IPhreeqc_interface_F.cpp\ + src/IPhreeqcPhast/IPhreeqc/IPhreeqc_interface_F.h\ src/IPhreeqcPhast/IPhreeqc/IPhreeqc.cpp\ src/IPhreeqcPhast/IPhreeqc/IPhreeqc.h\ src/IPhreeqcPhast/IPhreeqc/IPhreeqc.hpp\ - src/IPhreeqcPhast/IPhreeqc/IPhreeqc_interface_F.cpp\ - src/IPhreeqcPhast/IPhreeqc/IPhreeqc_interface_F.h\ src/IPhreeqcPhast/IPhreeqc/IPhreeqcCallbacks.h\ src/IPhreeqcPhast/IPhreeqc/IPhreeqcLib.cpp\ src/IPhreeqcPhast/IPhreeqc/phreeqcpp/advection.cpp\ @@ -82,10 +101,10 @@ libphreeqcrm_la_SOURCES=\ src/IPhreeqcPhast/IPhreeqc/phreeqcpp/NameDouble.h\ src/IPhreeqcPhast/IPhreeqc/phreeqcpp/NumKeyword.cxx\ src/IPhreeqcPhast/IPhreeqc/phreeqcpp/NumKeyword.h\ - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/nvector.cpp\ - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/nvector.h\ src/IPhreeqcPhast/IPhreeqc/phreeqcpp/nvector_serial.cpp\ src/IPhreeqcPhast/IPhreeqc/phreeqcpp/nvector_serial.h\ + src/IPhreeqcPhast/IPhreeqc/phreeqcpp/nvector.cpp\ + src/IPhreeqcPhast/IPhreeqc/phreeqcpp/nvector.h\ src/IPhreeqcPhast/IPhreeqc/phreeqcpp/parse.cpp\ src/IPhreeqcPhast/IPhreeqc/phreeqcpp/PBasic.cpp\ src/IPhreeqcPhast/IPhreeqc/phreeqcpp/PBasic.h\ @@ -96,8 +115,8 @@ libphreeqcrm_la_SOURCES=\ src/IPhreeqcPhast/IPhreeqc/phreeqcpp/PhreeqcKeywords/Keywords.cpp\ src/IPhreeqcPhast/IPhreeqc/phreeqcpp/PhreeqcKeywords/Keywords.h\ src/IPhreeqcPhast/IPhreeqc/phreeqcpp/PHRQ_io_output.cpp\ - src/IPhreeqcPhast/IPhreeqc/phreeqcpp/pitzer.cpp\ src/IPhreeqcPhast/IPhreeqc/phreeqcpp/pitzer_structures.cpp\ + src/IPhreeqcPhast/IPhreeqc/phreeqcpp/pitzer.cpp\ src/IPhreeqcPhast/IPhreeqc/phreeqcpp/PPassemblage.cxx\ src/IPhreeqcPhast/IPhreeqc/phreeqcpp/PPassemblage.h\ src/IPhreeqcPhast/IPhreeqc/phreeqcpp/PPassemblageComp.cxx\ @@ -166,42 +185,48 @@ libphreeqcrm_la_SOURCES=\ src/IPhreeqcPhast/IPhreeqcPhast.h\ src/IPhreeqcPhast/IPhreeqcPhastLib.cpp\ src/IPhreeqcPhast/IPhreeqcPhastLib.h\ - src/BMI_methods.cpp\ - src/BMI_Var.h\ src/PhreeqcRM.cpp\ src/RM_interface_C.cpp\ src/RM_interface_F.cpp\ src/RM_interface_F.h\ + src/RMVARS.h\ + src/VarManager.cpp\ + src/VarManager.h\ + src/YAML_interface_F.cpp\ + src/YAML_interface_F.h\ src/YAMLPhreeqcRM.cpp\ src/YAMLPhreeqcRM.h - include_HEADERS=\ + $(top_srcdir)/src/BMI_Var.h\ + $(top_srcdir)/src/bmi.hxx\ + $(top_srcdir)/src/BMIPhreeqcRM.h\ $(top_srcdir)/src/IPhreeqcPhast/IPhreeqc/IPhreeqc.h\ $(top_srcdir)/src/IPhreeqcPhast/IPhreeqc/IPhreeqc.hpp\ $(top_srcdir)/src/IPhreeqcPhast/IPhreeqc/IPhreeqcCallbacks.h\ + $(top_srcdir)/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/common/Parser.h\ + $(top_srcdir)/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/common/PHRQ_base.h\ + $(top_srcdir)/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/common/PHRQ_exports.h\ + $(top_srcdir)/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/common/PHRQ_io.h\ + $(top_srcdir)/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/common/phrqtype.h\ + $(top_srcdir)/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/NameDouble.h\ + $(top_srcdir)/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/PhreeqcKeywords/Keywords.h\ + $(top_srcdir)/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/StorageBin.h\ + $(top_srcdir)/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/System.h\ $(top_srcdir)/src/IPhreeqcPhast/IPhreeqc/Var.h\ $(top_srcdir)/src/IPhreeqcPhast/IPhreeqcPhast.h\ $(top_srcdir)/src/IrmResult.h\ $(top_srcdir)/src/PhreeqcRM.h\ $(top_srcdir)/src/RM_interface_C.h\ - $(top_srcdir)/src/YAMLPhreeqcRM.h\ - ${top_srcdir}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/common/Parser.h\ - ${top_srcdir}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/common/PHRQ_base.h\ - ${top_srcdir}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/common/PHRQ_exports.h\ - ${top_srcdir}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/common/PHRQ_io.h\ - ${top_srcdir}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/common/phrqtype.h\ - ${top_srcdir}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/NameDouble.h\ - ${top_srcdir}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/PhreeqcKeywords/Keywords.h\ - ${top_srcdir}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/StorageBin.h\ - ${top_srcdir}/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/System.h - + $(top_srcdir)/src/RMVARS.h\ + $(top_srcdir)/src/VarManager.h\ + $(top_srcdir)/src/YAMLPhreeqcRM.h +FCDEFS= if PHREEQCRM_TEST_FORTRAN - -DEFS+=\ - -DTEST_FORTRAN +DEFS+=-DTEST_FORTRAN +FCDEFS+=-DTEST_FORTRAN endif # Docs @@ -211,13 +236,20 @@ sourcedir=$(docdir)/src dist_source_DATA=$(SRC) SRC=\ + src/BMI_interface.F90\ + src/BMI_not_implemented.inc\ src/IPhreeqcPhast/IPhreeqc/IPhreeqc_interface.F90\ - src/RM_interface.F90 + src/RM_interface.F90\ + src/YAML_interface.F90 + # We must override the default PPFCCOMPILE since ifort can't # handle the FC_FUNC define correctly so $(DEFS) is replaced # by $(FCDEFS) # +if PHREEQCRM_WITH_YAMLCPP +FCDEFS+=-DUSE_YAML +endif PPFCCOMPILE = $(FC) $(FCDEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_FCFLAGS) $(FCFLAGS) LTPPFCCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=FC $(AM_LIBTOOLFLAGS) \ diff --git a/Tests/AdvectBMI_cpp.cpp b/Tests/AdvectBMI_cpp.cpp index c6b34eea2..e49067a30 100644 --- a/Tests/AdvectBMI_cpp.cpp +++ b/Tests/AdvectBMI_cpp.cpp @@ -7,7 +7,7 @@ #include #include #include -#include "PhreeqcRM.h" +#include "BMIPhreeqcRM.h" #include "IPhreeqc.hpp" #include "IPhreeqcPhast.h" #include @@ -20,14 +20,14 @@ double bmi_basic_callback(double x1, double x2, const char* str, void* cookie); void bmi_register_basic_callback(void* cookie); void advectionbmi_cpp(std::vector& c, std::vector bc_conc, int ncomps, int nxyz, int dim); -int bmi_example_selected_output(PhreeqcRM& phreeqc_rm); +int bmi_example_selected_output(BMIPhreeqcRM& brm); double bmi_basic_callback(double x1, double x2, const char* str, void* cookie); -void BMI_testing(PhreeqcRM& phreeqc_rm); +void testing(BMIPhreeqcRM& brm); //void GenerateYAML(int nxyz, std::string YAML_filename); class my_data { public: - PhreeqcRM* PhreeqcRM_ptr; + BMIPhreeqcRM* brm_ptr; #ifdef USE_MPI MPI_Comm rm_commxx; #endif @@ -54,8 +54,8 @@ int AdvectBMI_cpp() // using the YAMLPhreeqcRM class and the method // YAMLSetGridCellCount), the return // value is zero. - int nxyz = GetGridCellCountYAML(yaml_file); - + int nxyz = BMIPhreeqcRM::GetGridCellCountYAML(yaml_file.c_str()); + //int nxyz = 40; // Data for call_back demostration std::vector hydraulic_K; for (int i = 0; i < nxyz; i++) @@ -67,8 +67,8 @@ int AdvectBMI_cpp() #ifdef USE_MPI // MPI - PhreeqcRM phreeqc_rm(nxyz, MPI_COMM_WORLD); - some_data.PhreeqcRM_ptr = &phreeqc_rm; + PhreeqcRM brm(nxyz, MPI_COMM_WORLD); + some_data.PhreeqcRM_ptr = &brm; MP_TYPE comm = MPI_COMM_WORLD; int mpi_myself; if (MPI_Comm_rank(MPI_COMM_WORLD, &mpi_myself) != MPI_SUCCESS) @@ -77,186 +77,150 @@ int AdvectBMI_cpp() } if (mpi_myself > 0) { - phreeqc_rm.SetMpiWorkerCallbackC(worker_tasks_cc); - phreeqc_rm.SetMpiWorkerCallbackCookie(&some_data); - phreeqc_rm.MpiWorker(); + brm.SetMpiWorkerCallbackC(worker_tasks_cc); + brm.SetMpiWorkerCallbackCookie(&some_data); + brm.MpiWorker(); return EXIT_SUCCESS; } #else // OpenMP int nthreads = 3; - PhreeqcRM phreeqc_rm(nxyz, nthreads); - some_data.PhreeqcRM_ptr = &phreeqc_rm; + BMIPhreeqcRM brm(nxyz, nthreads); + some_data.brm_ptr = &brm; #endif + //brm.SetValue("FilePrefix", "Advectcpp"); + //brm.OpenFiles(); // Demonstrate add to Basic: Set a function for Basic CALLBACK after LoadDatabase bmi_register_basic_callback(&some_data); - // Use YAML file to initialize - phreeqc_rm.InitializeYAML(yaml_file); - + brm.Initialize(yaml_file); // Get number of components int ncomps; - phreeqc_rm.BMI_GetValue("ComponentCount", &ncomps); + brm.GetValue("ComponentCount", ncomps); // Example for generating automatic selected-output definitions - bmi_example_selected_output(phreeqc_rm); - + bmi_example_selected_output(brm); // Print some of the reaction module information { std::ostringstream oss; - oss << "Database: " << phreeqc_rm.GetDatabaseFileName().c_str() << "\n"; - oss << "Number of threads: " << phreeqc_rm.GetThreadCount() << "\n"; - oss << "Number of MPI processes: " << phreeqc_rm.GetMpiTasks() << "\n"; - oss << "MPI task number: " << phreeqc_rm.GetMpiMyself() << "\n"; - oss << "File prefix: " << phreeqc_rm.GetFilePrefix() << "\n"; - oss << "Number of grid cells in the user's model: " << phreeqc_rm.GetGridCellCount() << "\n"; - oss << "Number of chemistry cells in the reaction module: " << phreeqc_rm.GetChemistryCellCount() << "\n"; - oss << "Number of components for transport: " << phreeqc_rm.GetComponentCount() << "\n"; - oss << "Partioning of UZ solids: " << phreeqc_rm.GetPartitionUZSolids() << "\n"; - oss << "Error handler mode: " << phreeqc_rm.GetErrorHandlerMode() << "\n"; - phreeqc_rm.OutputMessage(oss.str()); - } - const std::vector& f_map = phreeqc_rm.GetForwardMapping(); - - // BMI version of getting component list - // equivalent to following statement - // const std::vector& components = phreeqc_rm.GetComponents(); - std::vector components; - { - size_t nbytes = (size_t)phreeqc_rm.BMI_GetVarNbytes("Components"); - std::string all_comps(nbytes, ' '); - phreeqc_rm.BMI_GetValue("Components", (void*)all_comps.data()); - size_t string_size = (size_t)phreeqc_rm.BMI_GetVarItemsize("Components"); - for (size_t i = 0; i < ncomps; i++) - { - std::string bmi_comp = all_comps.substr((i * string_size), string_size); - // strip trailing spaces - size_t end = bmi_comp.find_last_not_of(' '); - bmi_comp = (end == std::string::npos) ? "" : bmi_comp.substr(0, end + 1); - // store in components - components.push_back(bmi_comp); - } + oss << "Database: " << brm.GetDatabaseFileName().c_str() << "\n"; + oss << "Number of threads: " << brm.GetThreadCount() << "\n"; + oss << "Number of MPI processes: " << brm.GetMpiTasks() << "\n"; + oss << "MPI task number: " << brm.GetMpiMyself() << "\n"; + std::string prefix; + brm.GetValue("FilePrefix", prefix); + oss << "File prefix: " << prefix << "\n"; + int ngrid; + brm.GetValue("GridCellCount", ngrid); + oss << "Number of grid cells in the user's model: " << ngrid << "\n"; + oss << "Number of chemistry cells in the reaction module: " << brm.GetChemistryCellCount() << "\n"; + int ncomps; + brm.GetValue("ComponentCount", ncomps); + oss << "Number of components for transport: " << ncomps << "\n"; + oss << "Partioning of UZ solids: " << brm.GetPartitionUZSolids() << "\n"; + oss << "Error handler mode: " << brm.GetErrorHandlerMode() << std::endl; + brm.OutputMessage(oss.str()); } - - // BMI version of getting gram formula weights of components - // equivalent to following statement - //const std::vector < double >& gfw = phreeqc_rm.GetGfw(); + const std::vector& f_map = brm.GetForwardMapping(); + // Get components + std::vector components; + brm.GetValue("Components", components); + // Get gfw std::vector gfw(ncomps, 0); - phreeqc_rm.BMI_GetValue("Gfw", gfw.data()); - + brm.GetValue("Gfw", gfw); // write component information for (int i = 0; i < ncomps; i++) { std::ostringstream strm; strm.width(10); strm << components[i] << " " << gfw[i] << "\n"; - phreeqc_rm.OutputMessage(strm.str()); + brm.OutputMessage(strm.str()); } - phreeqc_rm.OutputMessage("\n"); - + brm.OutputMessage("\n"); // Get temperatures (unchanged by PhreeqcRM) - //const std::vector& tempc = phreeqc_rm.GetTemperature(); - std::vector tempc(nxyz, 0.0); - phreeqc_rm.BMI_GetValue("Temperature", tempc.data()); - - // get current saturation (unchanged by PhreeqcRM) - //std::vector current_sat; - //IRM_RESULT status = phreeqc_rm.GetSaturation(current_sat); // Demonstration of error handling if ErrorHandlerMode is 0 - //if (status != IRM_OK) - //{ - // std::cerr << phreeqc_rm.GetErrorString(); // retrieve error messages if needed - // throw PhreeqcRMStop(); - //} + std::vector tempc; + brm.GetValue("Temperature", tempc); + // Get initial saturation IRM_RESULT status; - std::vector current_sat(nxyz, 0.0); - phreeqc_rm.BMI_GetValue("Saturation", current_sat.data()); - + std::vector sat; + brm.GetValue("Saturation", sat); + //Get initial porosity + std::vector por; + brm.GetValue("Porosity", por); + //Get initial solution volume + std::vector volume; + brm.GetValue("SolutionVolume", volume); + //Get initial concentrations std::vector c; - c.resize(nxyz * components.size()); - //status = phreeqc_rm.GetConcentrations(c); - phreeqc_rm.BMI_GetValue("Concentrations", c.data()); + brm.GetValue("Concentrations", c); // Set density, temperature, and pressure std::vector density(nxyz, 1.0); std::vector temperature(nxyz, 20.0); std::vector pressure(nxyz, 2.0); - phreeqc_rm.BMI_SetValue("Density", density.data()); - phreeqc_rm.BMI_SetValue("Temperature", temperature.data()); - phreeqc_rm.BMI_SetValue("Pressure", pressure.data()); + brm.SetValue("Density", density); + brm.SetValue("Temperature", temperature); + brm.SetValue("Pressure", pressure); // -------------------------------------------------------------------------- // Set boundary condition // -------------------------------------------------------------------------- - std::vector bc_conc, bc_f1; std::vector bc1, bc2; int nbound = 1; bc1.resize(nbound, 0); // solution 0 from Initial IPhreeqc instance bc2.resize(nbound, -1); // no bc2 solution for mixing bc_f1.resize(nbound, 1.0); // mixing fraction for bc1 - status = phreeqc_rm.InitialPhreeqc2Concentrations(bc_conc, bc1, bc2, bc_f1); - + status = brm.InitialPhreeqc2Concentrations(bc_conc, bc1, bc2, bc_f1); // -------------------------------------------------------------------------- // Transient loop // -------------------------------------------------------------------------- - int nsteps = 10; - std::vector por(nxyz, 0.2); - std::vector sat(nxyz, 1.0); - - double time_step = phreeqc_rm.BMI_GetTimeStep(); - double time = phreeqc_rm.BMI_GetCurrentTime(); + double time = 0.0; + brm.SetValue("Time", time); + double time_step = 86400; + brm.SetValue("TimeStep", time_step); for (int steps = 0; steps < nsteps; steps++) { - // Transport calculation here { std::ostringstream strm; - strm << "Beginning transport calculation " << phreeqc_rm.GetTime() * phreeqc_rm.GetTimeConversion() << " days\n"; - strm << " Time step " << phreeqc_rm.GetTimeStep() * phreeqc_rm.GetTimeConversion() << " days\n"; - phreeqc_rm.LogMessage(strm.str()); - phreeqc_rm.SetScreenOn(true); - phreeqc_rm.ScreenMessage(strm.str()); + strm << "Beginning transport calculation " << brm.GetTime() * brm.GetTimeConversion() << " days\n"; + strm << " Time step " << brm.GetTimeStep() * brm.GetTimeConversion() << " days\n"; + brm.LogMessage(strm.str()); + brm.SetScreenOn(true); + brm.ScreenMessage(strm.str()); } + // Transport calculation here advectionbmi_cpp(c, bc_conc, ncomps, nxyz, nbound); // Transfer data to PhreeqcRM for reactions bool print_selected_output_on = (steps == nsteps - 1) ? true : false; + brm.SetValue("SelectedOutputOn", print_selected_output_on); bool print_chemistry_on = (steps == nsteps - 1) ? true : false; - //status = phreeqc_rm.SetSelectedOutputOn(print_selected_output_on); - phreeqc_rm.BMI_SetValue("SelectedOutputOn", &print_selected_output_on); - status = phreeqc_rm.SetPrintChemistryOn(print_chemistry_on, false, false); // workers, initial_phreeqc, utility - //status = phreeqc_rm.SetPorosity(por); // If pororosity changes due to compressibility - phreeqc_rm.BMI_SetValue("Porosity", por.data()); - //status = phreeqc_rm.SetSaturation(sat); // If saturation changes - phreeqc_rm.BMI_SetValue("Saturation", sat.data()); - //status = phreeqc_rm.SetTemperature(temperature); // If temperature changes - phreeqc_rm.BMI_SetValue("Temperature", temperature.data()); - //status = phreeqc_rm.SetPressure(pressure); // If pressure changes - phreeqc_rm.BMI_SetValue("Pressure", pressure.data()); - //status = phreeqc_rm.SetConcentrations(c); // Transported concentrations - phreeqc_rm.BMI_SetValue("Concentrations", c.data()); - //status = phreeqc_rm.SetTimeStep(time_step); // Time step for kinetic reactions - phreeqc_rm.BMI_SetValue("TimeStep", &time_step); + status = brm.SetPrintChemistryOn(print_chemistry_on, false, false); // workers, initial_phreeqc, utility + brm.SetValue("Concentrations", c); // Transported concentrations + brm.SetValue("Porosity", por); // If pororosity changes due to compressibility + brm.SetValue("Saturation", sat); // If saturation changes + brm.SetValue("Temperature", temperature); // If temperature changes + brm.SetValue("Pressure", pressure); // If pressure changes + brm.SetValue("TimeStep", time_step); // Time step for kinetic reactions time += time_step; - //status = phreeqc_rm.SetTime(time); - phreeqc_rm.BMI_SetValue("Time", &time); + brm.SetValue("Time", time); // Run cells with transported conditions { std::ostringstream strm; - strm << "Beginning reaction calculation " << time * phreeqc_rm.GetTimeConversion() << " days\n"; - phreeqc_rm.LogMessage(strm.str()); - phreeqc_rm.ScreenMessage(strm.str()); + strm << "Beginning reaction calculation " << time * brm.GetTimeConversion() << " days\n"; + brm.LogMessage(strm.str()); + brm.ScreenMessage(strm.str()); } // Demonstration of state - status = phreeqc_rm.StateSave(1); - status = phreeqc_rm.StateApply(1); - status = phreeqc_rm.StateDelete(1); - //status = phreeqc_rm.RunCells(); - phreeqc_rm.BMI_Update(); + status = brm.StateSave(1); + status = brm.StateApply(1); + status = brm.StateDelete(1); + //Run chemistry + brm.Update(); // Transfer data from PhreeqcRM for transport - //status = phreeqc_rm.GetConcentrations(c); - phreeqc_rm.BMI_GetValue("Concentrations", c.data()); - //status = phreeqc_rm.GetDensity(density); - phreeqc_rm.BMI_GetValue("Density", density.data()); - const std::vector& volume = phreeqc_rm.GetSolutionVolume(); + brm.GetValue("Concentrations", c); + brm.GetValue("Density", density); + brm.GetValue("SolutionVolume", volume); // Print results at last time step if (print_chemistry_on != 0) { @@ -265,58 +229,37 @@ int AdvectBMI_cpp() oss << "Current distribution of cells for workers\n"; oss << "Worker First cell Last Cell\n"; int n; - n = phreeqc_rm.GetThreadCount() * phreeqc_rm.GetMpiTasks(); + n = brm.GetThreadCount() * brm.GetMpiTasks(); for (int i = 0; i < n; i++) { - oss << i << " " << phreeqc_rm.GetStartCell()[i] << " " - << phreeqc_rm.GetEndCell()[i] << "\n"; + oss << i << " " << brm.GetStartCell()[i] << " " + << brm.GetEndCell()[i] << "\n"; } - phreeqc_rm.OutputMessage(oss.str()); + brm.OutputMessage(oss.str()); } int selected_output_count; - phreeqc_rm.BMI_GetValue("SelectedOutputCount", &selected_output_count); + brm.GetValue("SelectedOutputCount", selected_output_count); for (int isel = 0; isel < selected_output_count; isel++) { std::ostringstream oss; // Loop through possible multiple selected output definitions - //int n_user = phreeqc_rm.GetNthSelectedOutputUserNumber(isel); - //status = phreeqc_rm.SetCurrentSelectedOutputUserNumber(n_user); - phreeqc_rm.BMI_SetValue("NthSelectedOutput", &isel); + brm.SetValue("NthSelectedOutput", isel); oss << "Selected output sequence number: " << isel << "\n"; - int n_user = -1; - phreeqc_rm.BMI_GetValue("CurrentSelectedOutputUserNumber", &n_user); + int n_user; + brm.GetValue("CurrentSelectedOutputUserNumber", n_user); oss << "Selected output user number: " << n_user << "\n"; - // Get double array of selected output values - //std::vector so; - //int col = phreeqc_rm.GetSelectedOutputColumnCount(); - //status = phreeqc_rm.GetSelectedOutput(so); - + // Get array of selected output values int col; - phreeqc_rm.BMI_GetValue("SelectedOutputColumnCount", &col); + brm.GetValue("SelectedOutputColumnCount", col); int bmi_row_count; - phreeqc_rm.BMI_GetValue("SelectedOutputRowCount", &bmi_row_count); + brm.GetValue("SelectedOutputRowCount", bmi_row_count); // Get selected output - int bmi_nbytes = phreeqc_rm.BMI_GetVarNbytes("SelectedOutput"); - int bmi_itemsize = phreeqc_rm.BMI_GetVarItemsize("SelectedOutput"); - int bmi_dim = bmi_nbytes / bmi_itemsize; - std::vector so(bmi_dim, INACTIVE_CELL_VALUE); - phreeqc_rm.BMI_GetValue("SelectedOutput", so.data()); - + std::vector so; + brm.GetValue("SelectedOutput", so); // Get headings - bmi_nbytes = phreeqc_rm.BMI_GetVarNbytes("SelectedOutputHeadings"); - int bmi_string_size = phreeqc_rm.BMI_GetVarItemsize("SelectedOutputHeadings"); - std::string all_headings(bmi_nbytes, ' '); - phreeqc_rm.BMI_GetValue("SelectedOutputHeadings", (void*)all_headings.c_str()); std::vector headings; - for (int j = 0; j < col; j++) - { - std::string bmi_head = all_headings.substr((size_t)(j * bmi_string_size), bmi_string_size); - size_t end = bmi_head.find_last_not_of(' '); - bmi_head = (end == std::string::npos) ? "" : bmi_head.substr(0, end + 1); - headings.push_back(bmi_head); - } - + brm.GetValue("SelectedOutputHeadings", headings); // Print results for (int i = 0; i < bmi_row_count / 2; i++) { @@ -328,25 +271,20 @@ int AdvectBMI_cpp() { oss << " " << j << " " << components[j] << ": " << c[j * nxyz + i] << "\n"; } - //std::vector headings; - //headings.resize(col); - oss << " Selected output: " << "\n"; for (int j = 0; j < col; j++) { - //status = phreeqc_rm.GetSelectedOutputHeading(j, headings[j]); oss << " " << j << " " << headings[j] << ": " << so[j * nxyz + i] << "\n"; } } - phreeqc_rm.OutputMessage(oss.str()); + brm.OutputMessage(oss.str()); } } } - BMI_testing(phreeqc_rm); // Tests BMI_GetValue + testing(brm); // Tests GetValue // -------------------------------------------------------------------------- // Additional features and finalize // -------------------------------------------------------------------------- - // Use utility instance of PhreeqcRM to calculate pH of a mixture std::vector c_well; c_well.resize(1 * ncomps, 0.0); @@ -357,17 +295,17 @@ int AdvectBMI_cpp() std::vector tc, p_atm; tc.resize(1, 15.0); p_atm.resize(1, 3.0); - IPhreeqc* util_ptr = phreeqc_rm.Concentrations2Utility(c_well, tc, p_atm); + IPhreeqc* util_ptr = brm.Concentrations2Utility(c_well, tc, p_atm); std::string input = "SELECTED_OUTPUT 5; -pH;RUN_CELLS; -cells 1"; int iphreeqc_result; - util_ptr->SetOutputFileName("AdvectBMI_cpp_utility.txt"); + util_ptr->SetOutputFileName("Advectcpp_utility.txt"); util_ptr->SetOutputFileOn(true); iphreeqc_result = util_ptr->RunString(input.c_str()); // Alternatively, utility pointer is worker nthreads + 1 - IPhreeqc* util_ptr1 = phreeqc_rm.GetIPhreeqcPointer(phreeqc_rm.GetThreadCount() + 1); + IPhreeqc* util_ptr1 = brm.GetIPhreeqcPointer(brm.GetThreadCount() + 1); if (iphreeqc_result != 0) { - phreeqc_rm.ErrorHandler(IRM_FAIL, "IPhreeqc RunString failed"); + brm.ErrorHandler(IRM_FAIL, "IPhreeqc RunString failed"); } int vtype; double pH; @@ -377,15 +315,15 @@ int AdvectBMI_cpp() // Dump results bool dump_on = true; bool append = false; - status = phreeqc_rm.SetDumpFileName("AdvectBMI_cpp.dmp"); - status = phreeqc_rm.DumpModule(dump_on, append); // gz disabled unless compiled with #define USE_GZ + status = brm.SetDumpFileName("Advectcpp.dmp"); + status = brm.DumpModule(dump_on, append); // gz disabled unless compiled with #define USE_GZ // Get pointer to worker - const std::vector w = phreeqc_rm.GetWorkers(); + const std::vector w = brm.GetWorkers(); w[0]->AccumulateLine("Delete; -all"); iphreeqc_result = w[0]->RunAccumulated(); // Clean up - status = phreeqc_rm.CloseFiles(); - status = phreeqc_rm.MpiWorkerBreak(); + status = brm.CloseFiles(); + status = brm.MpiWorkerBreak(); } catch (PhreeqcRMStop) { @@ -434,7 +372,7 @@ int bmi_units_tester() int nxyz = 3; #ifdef USE_MPI // MPI - PhreeqcRM phreeqc_rm(nxyz, MPI_COMM_WORLD); + PhreeqcRM brm(nxyz, MPI_COMM_WORLD); int mpi_myself; if (MPI_Comm_rank(MPI_COMM_WORLD, &mpi_myself) != MPI_SUCCESS) { @@ -442,96 +380,96 @@ int bmi_units_tester() } if (mpi_myself > 0) { - phreeqc_rm.MpiWorker(); + brm.MpiWorker(); return EXIT_SUCCESS; } #else // OpenMP int nthreads = 3; - PhreeqcRM phreeqc_rm(nxyz, nthreads); + PhreeqcRM brm(nxyz, nthreads); #endif IRM_RESULT status; // Set properties - status = phreeqc_rm.SetErrorOn(true); - status = phreeqc_rm.SetErrorHandlerMode(1); - status = phreeqc_rm.SetFilePrefix("AdvectBMI_cpp"); - if (phreeqc_rm.GetMpiMyself() == 0) + status = brm.SetErrorOn(true); + status = brm.SetErrorHandlerMode(1); + status = brm.SetFilePrefix("Advectcpp"); + if (brm.GetMpiMyself() == 0) { - phreeqc_rm.OpenFiles(); + brm.OpenFiles(); } // Set concentration units - status = phreeqc_rm.SetUnitsSolution(1); // 1, mg/L; 2, mol/L; 3, kg/kgs - status = phreeqc_rm.SetUnitsPPassemblage(2); // 0, mol/L cell; 1, mol/L water; 2 mol/L rock - status = phreeqc_rm.SetUnitsExchange(1); // 0, mol/L cell; 1, mol/L water; 2 mol/L rock - status = phreeqc_rm.SetUnitsSurface(1); // 0, mol/L cell; 1, mol/L water; 2 mol/L rock - status = phreeqc_rm.SetUnitsGasPhase(1); // 0, mol/L cell; 1, mol/L water; 2 mol/L rock - status = phreeqc_rm.SetUnitsSSassemblage(1); // 0, mol/L cell; 1, mol/L water; 2 mol/L rock - status = phreeqc_rm.SetUnitsKinetics(1); // 0, mol/L cell; 1, mol/L water; 2 mol/L rock + status = brm.SetUnitsSolution(1); // 1, mg/L; 2, mol/L; 3, kg/kgs + status = brm.SetUnitsPPassemblage(2); // 0, mol/L cell; 1, mol/L water; 2 mol/L rock + status = brm.SetUnitsExchange(1); // 0, mol/L cell; 1, mol/L water; 2 mol/L rock + status = brm.SetUnitsSurface(1); // 0, mol/L cell; 1, mol/L water; 2 mol/L rock + status = brm.SetUnitsGasPhase(1); // 0, mol/L cell; 1, mol/L water; 2 mol/L rock + status = brm.SetUnitsSSassemblage(1); // 0, mol/L cell; 1, mol/L water; 2 mol/L rock + status = brm.SetUnitsKinetics(1); // 0, mol/L cell; 1, mol/L water; 2 mol/L rock // Set representative volume std::vector rv; rv.resize(nxyz, 1.0); - status = phreeqc_rm.SetRepresentativeVolume(rv); + status = brm.SetRepresentativeVolume(rv); // Set current porosity std::vector por; por.resize(nxyz, 0.2); - status = phreeqc_rm.SetPorosity(por); + status = brm.SetPorosity(por); // Set saturation std::vector sat; sat.resize(nxyz, 1.0); - status = phreeqc_rm.SetSaturation(sat); + status = brm.SetSaturation(sat); // Set printing of chemistry file - status = phreeqc_rm.SetPrintChemistryOn(false, true, false); // workers, initial_phreeqc, utility + status = brm.SetPrintChemistryOn(false, true, false); // workers, initial_phreeqc, utility // -------------------------------------------------------------------------- // Set initial conditions // -------------------------------------------------------------------------- // Load database - status = phreeqc_rm.LoadDatabase("phreeqc.dat"); + status = brm.LoadDatabase("phreeqc.dat"); // Run file to define solutions and reactants for initial conditions, selected output bool workers = true; bool initial_phreeqc = true; bool utility = false; - status = phreeqc_rm.RunFile(workers, initial_phreeqc, utility, "units.pqi"); + status = brm.RunFile(workers, initial_phreeqc, utility, "units.pqi"); { std::string input = "DELETE; -all"; - status = phreeqc_rm.RunString(true, false, true, input.c_str()); + status = brm.RunString(true, false, true, input.c_str()); } - //status = phreeqc_rm.SetFilePrefix("Units_InitialPhreeqc_2"); - if (phreeqc_rm.GetMpiMyself() == 0) + //status = brm.SetFilePrefix("Units_InitialPhreeqc_2"); + if (brm.GetMpiMyself() == 0) { - phreeqc_rm.OpenFiles(); + brm.OpenFiles(); } // Set reference to components - int ncomps = phreeqc_rm.FindComponents(); - const std::vector& components = phreeqc_rm.GetComponents(); + int ncomps = brm.FindComponents(); + const std::vector& components = brm.GetComponents(); // Set initial conditions std::vector < int > cell_numbers; cell_numbers.push_back(0); - status = phreeqc_rm.InitialPhreeqcCell2Module(1, cell_numbers); + status = brm.InitialPhreeqcCell2Module(1, cell_numbers); cell_numbers[0] = 1; - status = phreeqc_rm.InitialPhreeqcCell2Module(2, cell_numbers); + status = brm.InitialPhreeqcCell2Module(2, cell_numbers); cell_numbers[0] = 2; - status = phreeqc_rm.InitialPhreeqcCell2Module(3, cell_numbers); + status = brm.InitialPhreeqcCell2Module(3, cell_numbers); // Retrieve concentrations std::vector c; - status = phreeqc_rm.SetFilePrefix("AdvectBMI_cpp_units_worker"); - if (phreeqc_rm.GetMpiMyself() == 0) + status = brm.SetFilePrefix("Advectcpp_units_worker"); + if (brm.GetMpiMyself() == 0) { - phreeqc_rm.OpenFiles(); + brm.OpenFiles(); } std::vector < int > print_mask; print_mask.resize(3, 1); - phreeqc_rm.SetPrintChemistryMask(print_mask); - phreeqc_rm.SetPrintChemistryOn(true, true, true); - status = phreeqc_rm.RunCells(); - status = phreeqc_rm.GetConcentrations(c); + brm.SetPrintChemistryMask(print_mask); + brm.SetPrintChemistryOn(true, true, true); + status = brm.RunCells(); + status = brm.GetConcentrations(c); std::vector so; - status = phreeqc_rm.GetSelectedOutput(so); + status = brm.GetSelectedOutput(so); std::vector headings; { std::string heading; - phreeqc_rm.GetSelectedOutputHeading(0, heading); + brm.GetSelectedOutputHeading(0, heading); std::cerr << "Cell " << heading << std::endl; for (int i = 0; i < nxyz; i++) { @@ -542,15 +480,15 @@ int bmi_units_tester() std::vector tc, p_atm; tc.resize(nxyz, 25.0); p_atm.resize(nxyz, 1.0); - IPhreeqc* util_ptr = phreeqc_rm.Concentrations2Utility(c, tc, p_atm); + IPhreeqc* util_ptr = brm.Concentrations2Utility(c, tc, p_atm); std::string input; input = "RUN_CELLS; -cells 0-2"; // Output goes to new file int iphreeqc_result; - util_ptr->SetOutputFileName("AdvectBMI_cpp_units_utility.txt"); + util_ptr->SetOutputFileName("Advectcpp_units_utility.txt"); util_ptr->SetOutputFileOn(true); iphreeqc_result = util_ptr->RunString(input.c_str()); - status = phreeqc_rm.MpiWorkerBreak(); + status = brm.MpiWorkerBreak(); } catch (PhreeqcRMStop) { @@ -629,7 +567,7 @@ void bmi_register_basic_callback(void* cookie) } #endif - const std::vector w = data->PhreeqcRM_ptr->GetWorkers(); + const std::vector w = data->brm_ptr->GetWorkers(); for (int i = 0; i < (int)w.size(); i++) { w[i]->SetBasicCallback(bmi_basic_callback, cookie); @@ -638,13 +576,13 @@ void bmi_register_basic_callback(void* cookie) double bmi_basic_callback(double x1, double x2, const char* str, void* cookie) { my_data* data_ptr = (my_data*)cookie; - PhreeqcRM* phreeqcrm_ptr = data_ptr->PhreeqcRM_ptr; + BMIPhreeqcRM* brm_ptr = data_ptr->brm_ptr; std::string option(str); int rm_cell_number = (int)x1; - if (rm_cell_number >= 0 && rm_cell_number < phreeqcrm_ptr->GetChemistryCellCount()) + if (rm_cell_number >= 0 && rm_cell_number < brm_ptr->GetChemistryCellCount()) { - const std::vector < std::vector >& back = phreeqcrm_ptr->GetBackwardMapping(); + const std::vector < std::vector >& back = brm_ptr->GetBackwardMapping(); if (option == "HYDRAULIC_K") { return (*data_ptr->hydraulic_K)[back[rm_cell_number][0]]; @@ -652,15 +590,15 @@ double bmi_basic_callback(double x1, double x2, const char* str, void* cookie) } return -999.9; } -int bmi_example_selected_output(PhreeqcRM& phreeqc_rm) +int bmi_example_selected_output(BMIPhreeqcRM& brm) { std::ostringstream oss; oss << "SELECTED_OUTPUT 2" << "\n"; // totals oss << " -totals " << "\n"; - const std::vector& components = phreeqc_rm.GetComponents(); - for (size_t i = 0; i < phreeqc_rm.GetComponents().size(); i++) + const std::vector& components = brm.GetComponents(); + for (size_t i = 0; i < brm.GetComponents().size(); i++) { if (components[i] != "H" && components[i] != "O" && @@ -675,17 +613,17 @@ int bmi_example_selected_output(PhreeqcRM& phreeqc_rm) oss << " -molalities " << "\n"; { // molalities of aqueous species - const std::vector& aq_species = phreeqc_rm.GetSpeciesNames(); - for (size_t i = 0; i < phreeqc_rm.GetSpeciesNames().size(); i++) + const std::vector& aq_species = brm.GetSpeciesNames(); + for (size_t i = 0; i < brm.GetSpeciesNames().size(); i++) { oss << " " << aq_species[i] << "\n"; } } { // molalities of exchange species - const std::vector& ex_species = phreeqc_rm.GetExchangeSpecies(); - const std::vector& ex_names = phreeqc_rm.GetExchangeNames(); - for (size_t i = 0; i < phreeqc_rm.GetExchangeSpeciesCount(); i++) + const std::vector& ex_species = brm.GetExchangeSpecies(); + const std::vector& ex_names = brm.GetExchangeNames(); + for (size_t i = 0; i < brm.GetExchangeSpeciesCount(); i++) { oss << " "; @@ -696,10 +634,10 @@ int bmi_example_selected_output(PhreeqcRM& phreeqc_rm) } { // molalities of surface species - const std::vector& surf_species = phreeqc_rm.GetSurfaceSpecies(); - const std::vector& surf_types = phreeqc_rm.GetSurfaceTypes(); - const std::vector& surf_names = phreeqc_rm.GetSurfaceNames(); - for (size_t i = 0; i < phreeqc_rm.GetSurfaceSpeciesCount(); i++) + const std::vector& surf_species = brm.GetSurfaceSpecies(); + const std::vector& surf_types = brm.GetSurfaceTypes(); + const std::vector& surf_names = brm.GetSurfaceNames(); + for (size_t i = 0; i < brm.GetSurfaceSpeciesCount(); i++) { oss << " "; oss.width(15); @@ -712,8 +650,8 @@ int bmi_example_selected_output(PhreeqcRM& phreeqc_rm) oss << " -equilibrium_phases " << "\n"; { // equilibrium phases - const std::vector& eq_phases = phreeqc_rm.GetEquilibriumPhases(); - for (size_t i = 0; i < phreeqc_rm.GetEquilibriumPhasesCount(); i++) + const std::vector& eq_phases = brm.GetEquilibriumPhases(); + for (size_t i = 0; i < brm.GetEquilibriumPhasesCount(); i++) { oss << " " << eq_phases[i] << "\n"; } @@ -721,8 +659,8 @@ int bmi_example_selected_output(PhreeqcRM& phreeqc_rm) oss << " -gases " << "\n"; { // gas components - const std::vector& gas_phases = phreeqc_rm.GetGasComponents(); - for (size_t i = 0; i < phreeqc_rm.GetGasComponentsCount(); i++) + const std::vector& gas_phases = brm.GetGasComponents(); + for (size_t i = 0; i < brm.GetGasComponentsCount(); i++) { oss << " " << gas_phases[i] << "\n"; } @@ -730,8 +668,8 @@ int bmi_example_selected_output(PhreeqcRM& phreeqc_rm) oss << " -kinetics " << "\n"; { // kinetic reactions - const std::vector& kin_reactions = phreeqc_rm.GetKineticReactions(); - for (size_t i = 0; i < phreeqc_rm.GetKineticReactionsCount(); i++) + const std::vector& kin_reactions = brm.GetKineticReactions(); + for (size_t i = 0; i < brm.GetKineticReactionsCount(); i++) { oss << " " << kin_reactions[i] << "\n"; } @@ -739,9 +677,9 @@ int bmi_example_selected_output(PhreeqcRM& phreeqc_rm) oss << " -solid_solutions " << "\n"; { // solid solutions - const std::vector& ss_comps = phreeqc_rm.GetSolidSolutionComponents(); - const std::vector& ss_names = phreeqc_rm.GetSolidSolutionNames(); - for (size_t i = 0; i < phreeqc_rm.GetSolidSolutionComponentsCount(); i++) + const std::vector& ss_comps = brm.GetSolidSolutionComponents(); + const std::vector& ss_names = brm.GetSolidSolutionNames(); + for (size_t i = 0; i < brm.GetSolidSolutionComponentsCount(); i++) { oss << " "; @@ -753,263 +691,437 @@ int bmi_example_selected_output(PhreeqcRM& phreeqc_rm) oss << " -saturation_indices " << "\n"; { // molalities of aqueous species - const std::vector& si = phreeqc_rm.GetSINames(); - for (size_t i = 0; i < phreeqc_rm.GetSICount(); i++) + const std::vector& si = brm.GetSINames(); + for (size_t i = 0; i < brm.GetSICount(); i++) { oss << " " << si[i] << "\n"; } } // Uncommenting the following line would define SELECTED_OUTPUT 2 with all species, reactants, and SIs - // int status = phreeqc_rm.RunString(true, false, false, oss.str().c_str()); + // int status = brm.RunString(true, false, false, oss.str().c_str()); std::cerr << oss.str(); return(0); } -void BMI_testing(PhreeqcRM& phreeqc_rm) +void testing(BMIPhreeqcRM& brm) { std::ostringstream oss; - //std::string BMI_GetComponentName() { return "PhreeqcRM_BMI"; } - { - oss << phreeqc_rm.BMI_GetComponentName() << "\n"; - } - //double BMI_GetCurrentTime() { return this->GetTime(); } - { - oss << "BMI_GetCurrentTime: " << phreeqc_rm.BMI_GetCurrentTime() << "\n"; - } - //double BMI_GetEndTime() { return this->GetTime() + this->GetTimeStep(); } - { - oss << "BMI_GetEndTime: " << phreeqc_rm.BMI_GetEndTime() << "\n"; - } - //std::string BMI_GetTimeUnits() { return "seconds"; }; + int* nxyz_ptr = (int*)brm.GetValuePtr("GridCellCount"); + int* ncomps_ptr = (int*)brm.GetValuePtr("ComponentCount"); + double* time_ptr = (double*)brm.GetValuePtr("Time"); + double* timestep_ptr = (double*)brm.GetValuePtr("TimeStep"); + + // ComponentName + oss << brm.GetComponentName() << "\n"; + // Time { - oss << "BMI_GetTimeUnits: " << phreeqc_rm.BMI_GetTimeUnits() << "\n"; + double rm_time = 3600.0; + brm.SetValue("Time", rm_time); + double bmi_time = 0.0; + brm.GetValue("Time", bmi_time); + assert(rm_time == bmi_time); + rm_time = brm.GetTime(); + assert(rm_time == bmi_time); + bmi_time = brm.GetCurrentTime(); + assert(rm_time == bmi_time); } - //double BMI_GetTimeStep() { return this->GetTimeStep(); } + // TimeStep { - oss << "BMI_GetTimeStep: " << phreeqc_rm.BMI_GetTimeStep() << "\n"; + double rm_timestep = 60.; + brm.SetValue("TimeStep", rm_timestep); + double bmi_timestep = 0.0; + brm.GetValue("TimeStep", bmi_timestep); + assert(rm_timestep == bmi_timestep); + rm_timestep = brm.GetTimeStep(); + assert(rm_timestep == bmi_timestep); + bmi_timestep = brm.GetTimeStep(); + assert(rm_timestep == bmi_timestep); } - // std::vector BMI_GetInputVarNames() { return this->bmi_input_vars; } - // int BMI_GetInputItemCount() { return (int)this->bmi_input_vars.size(); } + // EndTime + oss << "GetEndTime: " << brm.GetEndTime() << "\n"; + // TimeUnits + oss << "GetTimeUnits: " << brm.GetTimeUnits() << "\n"; + // TimeStep + oss << "GetTimeStep: " << brm.GetTimeStep() << "\n"; + // InputVarNames { - std::vector InputVarNames = phreeqc_rm.BMI_GetInputVarNames(); - int count = phreeqc_rm.BMI_GetInputItemCount(); + std::vector InputVarNames = brm.GetInputVarNames(); + int count = brm.GetInputItemCount(); assert(InputVarNames.size() == (size_t)count); - oss << "BMI_SetValues variables:\n"; + oss << "SetValues variables:\n"; for (size_t i = 0; i < count; i++) { oss << " " << i << " " << InputVarNames[i] << "\n"; - oss << " Type: " << phreeqc_rm.BMI_GetVarType(InputVarNames[i]) << "\n"; - oss << " Units: " << phreeqc_rm.BMI_GetVarUnits(InputVarNames[i]) << "\n"; + oss << " Type: " << brm.GetVarType(InputVarNames[i]) << "\n"; + oss << " Units: " << brm.GetVarUnits(InputVarNames[i]) << "\n"; + oss << " Itemsize: " << brm.GetVarItemsize(InputVarNames[i]) << "\n"; + oss << " NBytes: " << brm.GetVarNbytes(InputVarNames[i]) << "\n"; } } - // std::vector BMI_GetOutputVarNames() { return this->bmi_output_vars; }; - // int BMI_GetOutputItemCount() { return (int)this->bmi_output_vars.size(); } + // OutputVarNames { - std::vector OutputVarNames = phreeqc_rm.BMI_GetOutputVarNames(); - int count = phreeqc_rm.BMI_GetOutputItemCount(); + std::vector OutputVarNames = brm.GetOutputVarNames(); + int count = brm.GetOutputItemCount(); assert(OutputVarNames.size() == (size_t)count); - oss << "BMI_GetValues variables:\n"; + oss << "GetValues variables:\n"; for (size_t i = 0; i < count; i++) { oss << " " << i << " " << OutputVarNames[i] << "\n"; - oss << " Type: " << phreeqc_rm.BMI_GetVarType(OutputVarNames[i]) << "\n"; - oss << " Units: " << phreeqc_rm.BMI_GetVarUnits(OutputVarNames[i]) << "\n"; + oss << " Type: " << brm.GetVarType(OutputVarNames[i]) << "\n"; + oss << " Units: " << brm.GetVarUnits(OutputVarNames[i]) << "\n"; + oss << " Itemsize: " << brm.GetVarItemsize(OutputVarNames[i]) << "\n"; + oss << " NBytes: " << brm.GetVarNbytes(OutputVarNames[i]) << "\n"; } } - phreeqc_rm.OutputMessage(oss.str()); - // GetValue("Components") + brm.OutputMessage(oss.str()); + // PointableVarNames { - int ncomps = -1; - phreeqc_rm.BMI_GetValue("ComponentCount", &ncomps); - assert(ncomps == (size_t)phreeqc_rm.GetComponentCount()); - size_t nbytes = (size_t)phreeqc_rm.BMI_GetVarNbytes("Components"); - std::string all_comps(nbytes, ' '); - phreeqc_rm.BMI_GetValue("Components", (void*)all_comps.data()); - size_t string_size = (size_t)phreeqc_rm.BMI_GetVarItemsize("Components"); - std::vector bmi_comps; - for (size_t i = 0; i < ncomps; i++) + std::vector PointableVarNames = brm.GetPointableVarNames(); + int count = brm.GetPointableItemCount(); + assert(PointableVarNames.size() == (size_t)count); + oss << "PointableValues variables:\n"; + for (size_t i = 0; i < count; i++) { - std::string bmi_comp = all_comps.substr((i * string_size), string_size); - size_t end = bmi_comp.find_last_not_of(' '); - bmi_comp = (end == std::string::npos) ? "" : bmi_comp.substr(0, end + 1); - bmi_comps.push_back(bmi_comp); + oss << " " << i << " " << PointableVarNames[i] << "\n"; + oss << " Type: " << brm.GetVarType(PointableVarNames[i]) << "\n"; + oss << " Units: " << brm.GetVarUnits(PointableVarNames[i]) << "\n"; + oss << " Itemsize: " << brm.GetVarItemsize(PointableVarNames[i]) << "\n"; + oss << " NBytes: " << brm.GetVarNbytes(PointableVarNames[i]) << "\n"; } - assert(bmi_comps == phreeqc_rm.GetComponents()); + } + brm.OutputMessage(oss.str()); + // GetValue("Components") + { + int ncomps; + brm.GetValue("ComponentCount", ncomps); + assert(ncomps == *ncomps_ptr); + assert(ncomps == brm.GetComponentCount()); + std::vector bmi_comps; + brm.GetValue("Components", bmi_comps); + std::vector rm_comps; + rm_comps = brm.GetComponents(); + assert(bmi_comps == rm_comps); } // GetValue("Concentrations") { - int ncomps = -1; - phreeqc_rm.BMI_GetValue("ComponentCount", &ncomps); - assert(ncomps == phreeqc_rm.GetComponentCount()); - int conc_nbytes = phreeqc_rm.BMI_GetVarNbytes("Concentrations"); - int conc_itemsize = phreeqc_rm.BMI_GetVarItemsize("Concentrations"); + int ncomps; + brm.GetValue("ComponentCount", ncomps); + double* concentrations_ptr = (double*)brm.GetValuePtr("Concentrations"); + int conc_nbytes = brm.GetVarNbytes("Concentrations"); + int conc_itemsize = brm.GetVarItemsize("Concentrations"); int conc_dim = conc_nbytes / conc_itemsize; + std::vector bmi_conc; + brm.GetValue("Concentrations", bmi_conc); + assert(conc_dim == (int)bmi_conc.size()); std::vector rm_conc; - phreeqc_rm.GetConcentrations(rm_conc); - assert(conc_nbytes == (int)(rm_conc.size() * sizeof(double))); - assert(conc_dim == (int)rm_conc.size()); - std::vector bmi_conc(conc_dim, INACTIVE_CELL_VALUE); - phreeqc_rm.BMI_GetValue("Concentrations", bmi_conc.data()); + brm.GetConcentrations(rm_conc); assert(rm_conc == bmi_conc); + for (int i = 0; i < conc_dim; i++) + { + bmi_conc[i] = concentrations_ptr[i]; + } } // GetValue("Density") + // GetDensity and GetValue("Density) always return + // the calculated solution density { - int ngrid; - phreeqc_rm.BMI_GetValue("GridCellCount", &ngrid); - std::vector bmi_density(ngrid, INACTIVE_CELL_VALUE); - phreeqc_rm.BMI_GetValue("Density", bmi_density.data()); + double* density_ptr = (double*)brm.GetValuePtr("Density"); + int dim = brm.GetVarNbytes("Density") / brm.GetVarItemsize("Density"); std::vector rm_density; - phreeqc_rm.GetDensity(rm_density); + brm.GetDensity(rm_density); + std::vector bmi_density; + brm.GetValue("Density", bmi_density); assert(bmi_density == rm_density); + for (int i = 0; i < dim; i++) + { + assert(density_ptr[i] == rm_density[i]); + } } // GetValue("ErrorString") { - int nbytes = phreeqc_rm.BMI_GetVarNbytes("ErrorString"); - std::string bmi_err(nbytes, ' '); - std::string rm_err = phreeqc_rm.GetErrorString(); + std::string bmi_err; + brm.GetValue("ErrorString", bmi_err); + std::string rm_err = brm.GetErrorString(); assert(bmi_err == rm_err); } + //FilePrefix + { + std::string str = "NewPrefix"; + brm.SetValue("FilePrefix", str); + std::string rm_prefix = brm.GetFilePrefix(); + assert(str == rm_prefix); + std::string prefix; + brm.GetValue("FilePrefix", prefix); + assert(prefix == rm_prefix); + } // GetValue("Gfw") { - int ncomps = -1; - phreeqc_rm.BMI_GetValue("ComponentCount", &ncomps); - std::vector bmi_gfw(ncomps, INACTIVE_CELL_VALUE); - phreeqc_rm.BMI_GetValue("Gfw", bmi_gfw.data()); - const std::vector rm_gfw = phreeqc_rm.GetGfw(); + double* gfw_ptr = (double*)brm.GetValuePtr("Gfw"); + std::vector bmi_gfw; + brm.GetValue("Gfw", bmi_gfw); + std::vector rm_gfw = brm.GetGfw(); assert(bmi_gfw == rm_gfw); + for (int i = 0; i < *ncomps_ptr; i++) + { + assert(gfw_ptr[i] == rm_gfw[i]); + } } // GetValue("GridCellCount") { int bmi_ngrid; - phreeqc_rm.BMI_GetValue("GridCellCount", &bmi_ngrid); - int rm_ngrid = phreeqc_rm.GetGridCellCount(); + brm.GetValue("GridCellCount", bmi_ngrid); + int rm_ngrid = brm.GetGridCellCount(); assert(bmi_ngrid == rm_ngrid); + assert(bmi_ngrid == *nxyz_ptr); } // SetValue("NthSelectedOutput") { // tested in "SelectedOutput" // tested in "SelectedOutputHeadings" } + // GetValue("Porosity") + { + int ngrid; + brm.GetValue("GridCellCount", ngrid); + std::vector bmi_porosity(ngrid, 0.3); + brm.SetValue("Porosity", bmi_porosity); + std::vector rm_porosity; + rm_porosity = brm.GetPorosity(); + assert(bmi_porosity == rm_porosity); + brm.GetValue("Porosity", bmi_porosity); + assert(bmi_porosity == rm_porosity); + } + // testing of pointers and allocated values + { + double* por_ptr = (double*)brm.GetValuePtr("Porosity"); + double* por_ptr1 = (double*)brm.GetValuePtr("Porosity"); + assert(por_ptr == por_ptr1); + double* my_porosity_alloc; + my_porosity_alloc = (double*)malloc(40 * sizeof(double)); + double my_porosity_dim[40]; + std::vector my_por; + brm.GetValue("Porosity", my_por); + brm.GetValue("Porosity", my_porosity_dim); + brm.GetValue("Porosity", my_porosity_alloc); + for (size_t i = 0; i < *nxyz_ptr; i++) + { + assert(my_por[i] == my_porosity_dim[i]); + assert(my_por[i] == my_porosity_alloc[i]); + assert(my_por[i] == por_ptr[i]); + assert(por_ptr[i] == por_ptr[i]); + } + my_por.resize(40, 0.4); + brm.SetValue("Porosity", my_por); + brm.GetValue("Porosity", my_porosity_dim); + brm.GetValue("Porosity", my_porosity_alloc); + for (size_t i = 0; i < *nxyz_ptr; i++) + { + assert(my_por[i] == my_porosity_dim[i]); + assert(my_por[i] == my_porosity_alloc[i]); + assert(my_por[i] == por_ptr[i]); + assert(por_ptr[i] == por_ptr[i]); + } + my_por.resize(40, 0.5); + brm.SetPorosity(my_por); + brm.GetValue("Porosity", my_porosity_dim); + brm.GetValue("Porosity", my_porosity_alloc); + for (size_t i = 0; i < *nxyz_ptr; i++) + { + assert(my_por[i] == my_porosity_dim[i]); + assert(my_por[i] == my_porosity_alloc[i]); + assert(my_por[i] == por_ptr[i]); + assert(por_ptr[i] == por_ptr[i]); + } + free((void*)my_porosity_alloc); + } // GetValue("Pressure") { int ngrid; - phreeqc_rm.BMI_GetValue("GridCellCount", &ngrid); - std::vector bmi_pressure(ngrid, INACTIVE_CELL_VALUE); - phreeqc_rm.BMI_GetValue("Pressure", bmi_pressure.data()); - const std::vector rm_pressure = phreeqc_rm.GetPressure(); + brm.GetValue("GridCellCount", ngrid); + int* nxyz_ptr = (int*)brm.GetValuePtr("GridCellCount"); + assert(*nxyz_ptr == ngrid); + double* pressure_ptr = (double*)brm.GetValuePtr("Pressure"); + std::vector bmi_pressure(ngrid, 1.1); + brm.SetPressure(bmi_pressure); + std::vector rm_pressure; + rm_pressure = brm.GetPressure(); + assert(bmi_pressure == rm_pressure); + brm.GetValue("Pressure", bmi_pressure); assert(bmi_pressure == rm_pressure); + for (size_t i = 0; i < *nxyz_ptr; i++) + { + assert(pressure_ptr[i] == rm_pressure[i]); + } } // GetValue("Saturation") + // Always returns solution_volume / (rv * porosity) for each cell { - int ngrid; - phreeqc_rm.BMI_GetValue("GridCellCount", &ngrid); - std::vector bmi_sat(ngrid, INACTIVE_CELL_VALUE); - phreeqc_rm.BMI_GetValue("Saturation", bmi_sat.data()); + double* saturation_ptr = (double*)brm.GetValuePtr("Saturation"); + std::vector bmi_sat; + brm.GetValue("Saturation", bmi_sat); std::vector rm_sat; - phreeqc_rm.GetSaturation(rm_sat); + brm.GetSaturation(rm_sat); assert(bmi_sat == rm_sat); + for (int i = 0; i < *nxyz_ptr; i++) + { + assert(saturation_ptr[i] == bmi_sat[i]); + } + rm_sat.resize(*nxyz_ptr, 0.8); + brm.SetValue("Saturation", rm_sat); + brm.GetValue("Saturation", bmi_sat); + assert(bmi_sat == rm_sat); + for (int i = 0; i < *nxyz_ptr; i++) + { + assert(saturation_ptr[i] == bmi_sat[i]); + } + } + // GetValue("SolutionVolume") + // Always returns solution_volume / (rv * porosity) for each cell + { + double* solution_volume_ptr = (double*)brm.GetValuePtr("SolutionVolume"); + std::vector bmi_vol; + brm.GetValue("SolutionVolume", bmi_vol); + std::vector rm_vol; + rm_vol = brm.GetSolutionVolume(); + assert(bmi_vol == rm_vol); + for (int i = 0; i < *nxyz_ptr; i++) + { + assert(solution_volume_ptr[i] == bmi_vol[i]); + } + } + // GetValue("Temperature") + { + double* temperature_ptr = (double*)brm.GetValuePtr("Temperature"); + int ngrid; + brm.GetValue("GridCellCount", ngrid); + std::vector bmi_temperature(ngrid, 50.); + brm.SetValue("Temperature", bmi_temperature); + std::vector rm_temperature; + rm_temperature = brm.GetTemperature(); + assert(bmi_temperature == rm_temperature); + brm.GetValue("Temperature", bmi_temperature); + assert(bmi_temperature == rm_temperature); + for (int i = 0; i < *nxyz_ptr; i++) + { + assert(temperature_ptr[i] == bmi_temperature[i]); + } } // GetValue("SelectedOutput") { int bmi_so_count; - phreeqc_rm.BMI_GetValue("SelectedOutputCount", &bmi_so_count); - int rm_so_count = phreeqc_rm.GetSelectedOutputCount(); + brm.GetValue("SelectedOutputCount", bmi_so_count); + int rm_so_count = brm.GetSelectedOutputCount(); assert(bmi_so_count == rm_so_count); for (int i = 0; i < bmi_so_count; i++) { - phreeqc_rm.BMI_SetValue("NthSelectedOutput", &i); + brm.SetValue("NthSelectedOutput", i); int bmi_nuser; - phreeqc_rm.BMI_GetValue("CurrentSelectedOutputUserNumber", &bmi_nuser); - int rm_nuser = phreeqc_rm.GetNthSelectedOutputUserNumber(i); + brm.GetValue("CurrentSelectedOutputUserNumber", bmi_nuser); + int rm_nuser = brm.GetNthSelectedOutputUserNumber(i); assert(bmi_nuser == rm_nuser); int bmi_col_count; - phreeqc_rm.BMI_GetValue("SelectedOutputColumnCount", &bmi_col_count); - int rm_col_count = phreeqc_rm.GetSelectedOutputColumnCount(); + brm.GetValue("SelectedOutputColumnCount", bmi_col_count); + int rm_col_count = brm.GetSelectedOutputColumnCount(); assert(bmi_col_count == rm_col_count); int bmi_row_count; - phreeqc_rm.BMI_GetValue("SelectedOutputRowCount", &bmi_row_count); - int rm_row_count = phreeqc_rm.GetSelectedOutputRowCount(); + brm.GetValue("SelectedOutputRowCount", bmi_row_count); + int rm_row_count = brm.GetSelectedOutputRowCount(); assert(bmi_row_count == rm_row_count); - int bmi_nbytes = phreeqc_rm.BMI_GetVarNbytes("SelectedOutput"); - int bmi_itemsize = phreeqc_rm.BMI_GetVarItemsize("SelectedOutput"); - int bmi_dim = bmi_nbytes / bmi_itemsize; - std::vector bmi_so(bmi_dim, INACTIVE_CELL_VALUE); - phreeqc_rm.BMI_GetValue("SelectedOutput", bmi_so.data()); + std::vector bmi_so; + brm.GetValue("SelectedOutput", bmi_so); std::vector rm_so; - phreeqc_rm.GetSelectedOutput(rm_so); - assert(bmi_dim == (int)rm_so.size()); - assert(bmi_nbytes == (int)(rm_so.size() * sizeof(double))); + brm.GetSelectedOutput(rm_so); assert(bmi_so == rm_so); } } // GetValue("SelectedOutputColumnCount") { int bmi_so_col_count; - phreeqc_rm.BMI_GetValue("SelectedOutputColumnCount", &bmi_so_col_count); - int rm_so_col_count = phreeqc_rm.GetSelectedOutputColumnCount(); + brm.GetValue("SelectedOutputColumnCount", bmi_so_col_count); + int rm_so_col_count = brm.GetSelectedOutputColumnCount(); assert(bmi_so_col_count == rm_so_col_count); } // GetValue("SelectedOutputCount") { int bmi_so_count; - phreeqc_rm.BMI_GetValue("SelectedOutputCount", &bmi_so_count); - int rm_so_count = phreeqc_rm.GetSelectedOutputCount(); + brm.GetValue("SelectedOutputCount", bmi_so_count); + int rm_so_count = brm.GetSelectedOutputCount(); assert(bmi_so_count == rm_so_count); } // GetValue("SelectedOutputHeadings") { int bmi_so_count; - phreeqc_rm.BMI_GetValue("SelectedOutputCount", &bmi_so_count); - int rm_so_count = phreeqc_rm.GetSelectedOutputCount(); + brm.GetValue("SelectedOutputCount", bmi_so_count); + int rm_so_count = brm.GetSelectedOutputCount(); assert(bmi_so_count == rm_so_count); for (int i = 0; i < bmi_so_count; i++) { - phreeqc_rm.BMI_SetValue("NthSelectedOutput", &i); + brm.SetValue("NthSelectedOutput", i); int bmi_nuser; - phreeqc_rm.BMI_GetValue("CurrentSelectedOutputUserNumber", &bmi_nuser); - int rm_nuser = phreeqc_rm.GetNthSelectedOutputUserNumber(i); + brm.GetValue("CurrentSelectedOutputUserNumber", bmi_nuser); + int rm_nuser = brm.GetNthSelectedOutputUserNumber(i); assert(bmi_nuser == rm_nuser); - int bmi_nbytes = phreeqc_rm.BMI_GetVarNbytes("SelectedOutputHeadings"); - int bmi_string_size = phreeqc_rm.BMI_GetVarItemsize("SelectedOutputHeadings"); - std::string all_headings(bmi_nbytes, ' '); - phreeqc_rm.BMI_GetValue("SelectedOutputHeadings", (void*)all_headings.c_str()); - int bmi_col_count; - phreeqc_rm.BMI_GetValue("SelectedOutputColumnCount", &bmi_col_count); - int rm_col_count = phreeqc_rm.GetSelectedOutputColumnCount(); + brm.GetValue("SelectedOutputColumnCount", bmi_col_count); + int rm_col_count = brm.GetSelectedOutputColumnCount(); assert(bmi_col_count == rm_col_count); - for (int j = 0; j < bmi_col_count; j++) - { - std::string bmi_head = all_headings.substr((j * bmi_string_size), bmi_string_size); - size_t end = bmi_head.find_last_not_of(' '); - bmi_head = (end == std::string::npos) ? "" : bmi_head.substr(0, end + 1); - std::string rm_head; - phreeqc_rm.GetSelectedOutputHeading(j, rm_head); - assert(bmi_head == rm_head); - } + std::vector< std::string > bmi_headings; + brm.GetValue("SelectedOutputHeadings", bmi_headings); + std::vector< std::string > rm_headings; + IRM_RESULT status = brm.GetSelectedOutputHeadings(rm_headings); + assert(bmi_headings == rm_headings); } } + // GetValue("SelectedOutputOn") + { + bool* selectedoutput_on_ptr = (bool*)brm.GetValuePtr("SelectedOutputOn"); + bool bmi_so_on; + brm.GetValue("SelectedOutputOn", bmi_so_on); + int rm_so_row_count = brm.GetSelectedOutputRowCount(); + assert(bmi_so_on == *selectedoutput_on_ptr); + bmi_so_on = false; + brm.SetValue("SelectedOutputOn", bmi_so_on); + assert(*selectedoutput_on_ptr == bmi_so_on); + bmi_so_on = true; + brm.SetValue("SelectedOutputOn", bmi_so_on); + assert(*selectedoutput_on_ptr == bmi_so_on); + } // GetValue("SelectedOutputRowCount") { int bmi_so_row_count; - phreeqc_rm.BMI_GetValue("SelectedOutputRowCount", &bmi_so_row_count); - int rm_so_row_count = phreeqc_rm.GetSelectedOutputRowCount(); + brm.GetValue("SelectedOutputRowCount", bmi_so_row_count); + int rm_so_row_count = brm.GetSelectedOutputRowCount(); assert(bmi_so_row_count == rm_so_row_count); } - // GetValue("Temperature") + // Time { - int ngrid; - phreeqc_rm.BMI_GetValue("GridCellCount", &ngrid); - std::vector bmi_temp(ngrid, INACTIVE_CELL_VALUE); - phreeqc_rm.BMI_GetValue("Temperature", bmi_temp.data()); - const std::vector rm_temp = phreeqc_rm.GetTemperature(); - assert(bmi_temp == rm_temp); + double time = 1.0; + double* time_ptr = (double*)brm.GetValuePtr("Time"); + brm.SetTime(time); + double time1; + brm.GetValue("Time", time1); + assert(time1 == time); + assert(*time_ptr = time); + } + // TimeStep + { + double timestep = 1.1; + double* timestep_ptr = (double*)brm.GetValuePtr("TimeStep"); + brm.SetValue("TimeStep", timestep); + assert(*timestep_ptr == timestep); + timestep = 1.2; + brm.SetTimeStep(timestep); + assert(*timestep_ptr == timestep); + double timestep1; + brm.GetValue("TimeStep", timestep1); + assert(timestep1 == timestep); + assert(*timestep_ptr = timestep); } } #endif // YAML \ No newline at end of file diff --git a/Tests/AdvectBMI_f90.F90 b/Tests/AdvectBMI_f90.F90 new file mode 100644 index 000000000..7695d38e2 --- /dev/null +++ b/Tests/AdvectBMI_f90.F90 @@ -0,0 +1,788 @@ +#ifdef USE_YAML + !module mydata + ! real(kind=8), dimension(:), pointer :: K_ptr + ! integer :: rm_id + !end module mydata + + subroutine AdvectBMI_f90() BIND(C, NAME='AdvectBMI_f90') + USE, intrinsic :: ISO_C_BINDING + USE BMIPhreeqcRM + !USE PhreeqcRM + USE IPhreeqc + USE mydata + implicit none +#ifdef USE_MPI + INCLUDE 'mpif.h' +#endif + interface + subroutine advectionbmi_f90(c, bc_conc, ncomps, nxyz) + implicit none + real(kind=8), dimension(:,:), allocatable, intent(inout) :: c + real(kind=8), dimension(:,:), allocatable, intent(in) :: bc_conc + integer, intent(in) :: ncomps, nxyz + end subroutine advectionbmi_f90 + integer function do_something() + end function do_something + integer(kind=C_INT) function worker_tasks_f(method_number) BIND(C, NAME='worker_tasks_f') + USE ISO_C_BINDING + implicit none + integer(kind=c_int), intent(in) :: method_number + end function worker_tasks_f + SUBROUTINE register_basic_callback_fortran() + implicit none + END SUBROUTINE register_basic_callback_fortran + subroutine BMI_testing(id) + implicit none + integer, intent(in) :: id + end subroutine BMI_testing + + end interface + + ! Based on PHREEQC Example 11 + real(kind=8), pointer :: d1_ptr(:) + character(100) :: yaml_file + integer :: mpi_myself + integer :: i, j + logical :: tf + integer :: nxyz + integer :: nthreads + integer :: id + integer :: status + integer :: bytes, nbytes + real(kind=8), dimension(:), allocatable, target :: hydraulic_K + real(kind=8), dimension(:), allocatable :: por + real(kind=8), dimension(:), allocatable :: sat + integer :: nchem + character(len=:), allocatable :: prefix + character(len=2) :: shortprefix + character(len=:), allocatable :: alloc_string + character(100) :: string + character(200) :: string1 + integer :: ncomps, ncomps1 + character(len=:), dimension(:), allocatable :: components + real(kind=8), dimension(:), allocatable :: gfw + integer :: nbound + integer, dimension(:), allocatable :: bc1, bc2 + real(kind=8), dimension(:), allocatable :: bc_f1 + integer, dimension(:), allocatable :: module_cells + real(kind=8), dimension(:,:), allocatable :: bc_conc + real(kind=8), dimension(:,:), allocatable :: c + real(kind=8) :: time, time_step + real(kind=8), dimension(:), allocatable :: density + real(kind=8), dimension(:), allocatable :: sat_calc + real(kind=8), dimension(:), allocatable :: volume + real(kind=8), dimension(:), allocatable :: temperature + real(kind=8), dimension(:), allocatable :: pressure + integer :: isteps, nsteps + real(kind=8), dimension(:,:), allocatable :: selected_out + integer :: col, isel, n_user, rows + character(len=:), dimension(:), allocatable :: headings + real(kind=8), dimension(:,:), allocatable :: c_well + real(kind=8), dimension(:), allocatable :: tc, p_atm + integer :: vtype + real(kind=8) :: pH + character(100) :: svalue + integer :: iphreeqc_id, iphreeqc_id1 + integer :: dump_on, append + !character(LEN=1), dimension(:), allocatable :: errstr +#ifdef FORTRAN_2003 + character(LEN=:), allocatable :: errstr +#else + character(LEN=10000) :: errstr +#endif + integer :: l, n + integer, dimension(:), allocatable :: sc, ec + ! -------------------------------------------------------------------------- + ! Create PhreeqcRM + ! -------------------------------------------------------------------------- + yaml_file = "AdvectBMI_f90.yaml" + ! RM_GetGridCellCountYAML must be called BEFORE + ! the PhreeqcRM instance is created. The + ! return value can be used to create the + ! PhreeqcRM instance. + ! + ! If the YAML file does not contain + ! a node "SetGridCellCount:" (usually written + ! using the YAMLPhreeqcRM class and the method + ! YAMLSetGridCellCount), the return + ! value is zero. + nxyz = GetGridCellCountYAML(yaml_file) + + ! Bogus conductivity field for Basic callback demonstration + allocate(hydraulic_K(nxyz)) + do i = 1, nxyz + hydraulic_K(i) = i * 2.0 + enddo + K_ptr => hydraulic_K +#ifdef USE_MPI + ! MPI + id = BMI_Create(nxyz, MPI_COMM_WORLD) + rm_id = id + call MPI_Comm_rank(MPI_COMM_WORLD, mpi_myself, status) + if (status .ne. MPI_SUCCESS) then + stop "Failed to get mpi_myself" + endif + if (mpi_myself > 0) then + status = RM_SetMpiWorkerCallback(id, worker_tasks_f) + status = RM_MpiWorker(id) + status = RM_Destroy(id) + return + endif +#else + ! OpenMP + nthreads = 3 + id = BMIF_Create(nxyz, nthreads) + rm_id = id +#endif + ! Open files + !status = bmif_set_value(id, "FilePrefix", "AdvectBMI_f90") + !status = RM_OpenFiles(id) + ! Initialize with YAML file + status = bmif_initialize(id, yaml_file) + + ! Demonstrate add to Basic: Set a function for Basic CALLBACK after LoadDatabase + CALL register_basic_callback_fortran() +#ifdef USE_MPI + ! Optional callback for MPI + status = do_something() ! only root is calling do_something here +#endif + status = bmif_get_value(id, "ComponentCount", ncomps) + + ! Print some of the reaction module information + write(string1, "(A,I10)") "Number of threads: ", RM_GetThreadCount(id) + status = RM_OutputMessage(id, string1) + write(string1, "(A,I10)") "Number of MPI processes: ", RM_GetMpiTasks(id) + status = RM_OutputMessage(id, string1) + write(string1, "(A,I10)") "MPI task number: ", RM_GetMpiMyself(id) + status = RM_OutputMessage(id, string1) + status = bmif_get_var_nbytes(id, "FilePrefix", n) + if (len(prefix) < n) then + if(allocated(prefix)) deallocate(prefix) + allocate(character(len=n) :: prefix) + endif + status = bmif_get_value(id, "FilePrefix", prefix) + write(string1, "(A,A)") "File prefix: ", prefix + status = RM_OutputMessage(id, trim(string1)) + write(string1, "(A,I10)") "Number of grid cells in the user's model: ", nxyz + status = RM_OutputMessage(id, trim(string1)) + !write(string1, "(A,I10)") "Number of chemistry cells in the reaction module: ", nchem + !status = RM_OutputMessage(id, trim(string1)) + write(string1, "(A,I10)") "Number of components for transport: ", ncomps + status = RM_OutputMessage(id, trim(string1)) + ! Get component information + status = bmif_get_value(id, "Components", components) + status = bmif_get_value(id, "Gfw", gfw) + do i = 1, ncomps + write(string,"(A10, F15.4)") trim(components(i)), gfw(i) + status = RM_OutputMessage(id, string) + enddo + status = RM_OutputMessage(id, " ") + ! Get initial temperatures + status = bmif_get_value(id, "Temperature", temperature) + ! Get initial temperature + status = bmif_get_value(id, "Saturation", sat) + ! Get initial porosity + status = bmif_get_value(id, "Porosity", por) + ! Get initial temperature + status = bmif_get_value(id, "SolutionVolume", volume) + ! Get initial concentrations + status = bmif_get_value(id, "Concentrations", c) + ! Set density, pressure, and temperature (previously allocated) + allocate(density(nxyz)) + allocate(pressure(nxyz)) + density = 1.0 + status = bmif_set_value(id, "Density", density) + pressure = 2.0 + status = bmif_set_value(id, "Pressure", pressure) + temperature = 20.0 + status = bmif_set_value(id, "Temperature", temperature) + ! -------------------------------------------------------------------------- + ! Set boundary condition + ! -------------------------------------------------------------------------- + nbound = 1 + allocate(bc1(nbound), bc2(nbound), bc_f1(nbound)) + allocate(bc_conc(nbound, ncomps)) + bc1 = 0 ! solution 0 from Initial IPhreeqc instance + bc2 = -1 ! no bc2 solution for mixing + bc_f1 = 1.0 ! mixing fraction for bc1 + status = RM_InitialPhreeqc2Concentrations(id, bc_conc, nbound, bc1, bc2, bc_f1) + ! -------------------------------------------------------------------------- + ! Transient loop + ! -------------------------------------------------------------------------- + nsteps = 10 + time = 0.0 + status = bmif_set_value(id, "Time", time) + time_step = 86400.0 + status = bmif_set_value(id, "TimeStep", time_step) + do isteps = 1, nsteps + write(string, "(A32,F15.1,A)") "Beginning transport calculation ", & + time/86400., " days" + status = RM_LogMessage(id, string) + status = RM_SetScreenOn(id, 1) + status = RM_ScreenMessage(id, string) + write(string, "(A32,F15.1,A)") " Time step ", & + time_step / 86400., " days" + status = RM_LogMessage(id, string) + status = RM_ScreenMessage(id, string) + ! Transport calculation here, changes c + call advectionbmi_f90(c, bc_conc, ncomps, nxyz) + + ! print at last time step + if (isteps == nsteps) then + status = bmif_set_value(id, "SelectedOutputOn", .true.) ! enable selected output + status = RM_SetPrintChemistryOn(id, 1, 0, 0) ! workers, initial_phreeqc, utility + else + status = bmif_set_value(id, "SelectedOutputOn", .false.) ! disable selected output + status = RM_SetPrintChemistryOn(id, 0, 0, 0) ! workers, initial_phreeqc, utility + endif + ! Transfer data to PhreeqcRM after transport + status = bmif_set_value(id, "Concentrations", c) ! Transported concentrations + ! Optionally, if values changed during transport + status = bmif_set_value(id, "Porosity", por) + status = bmif_set_value(id, "Saturation", sat) + status = bmif_set_value(id, "Temperature", temperature) + status = bmif_set_value(id, "Pressure", pressure) + status = bmif_set_value(id, "TimeStep", time_step) + ! Set new time + time = time + time_step + status = bmif_set_value(id, "Time", time) ! Current time + ! Run cells with transported conditions + write(string, "(A32,F15.1,A)") "Beginning reaction calculation ", & + time / 86400., " days" + status = RM_LogMessage(id, string) + status = RM_ScreenMessage(id, string) + ! Demonstration of state + status = RM_StateSave(id, 1) + status = RM_StateApply(id, 1) + status = RM_StateDelete(id, 1) + ! Run chemistry + status = bmif_update(id) + ! Get new data calculated by PhreeqcRM for transport + status = bmif_get_value(id, "Concentrations", c) + status = bmif_get_value(id, "Density", density) + status = bmif_get_value(id, "SolutionVolume", volume) + ! Print results at last time step + if (isteps == nsteps) then + write(*,*) "Current distribution of cells for workers" + write(*,*) "Worker First cell Last Cell" + n = RM_GetThreadCount(id) * RM_GetMpiTasks(id) + allocate(sc(n), ec(n)) + status = RM_GetStartCell(id, sc) + status = RM_GetEndCell(id, ec) + do i = 1, n + write(*,*) i," ", sc(i)," ",ec(i) + enddo + ! Loop through possible multiple selected output definitions + status = bmif_get_value(id, "SelectedOutputCount", n) + do isel = 1, n ! one based + i = isel + status = bmif_set_value(id, "NthSelectedOutput", i) + status = bmif_get_value(id, "CurrentSelectedOutputUserNumber", n_user) + write(*,*) "Selected output sequence number: ", isel + write(*,*) "Selected output user number: ", n_user + ! Get 2D array of selected output values + status = bmif_get_value(id, "SelectedOutputColumnCount", col) + status = bmif_get_value(id, "SelectedOutputRowCount", rows) + allocate(selected_out(rows,col)) + ! Get headings + status = bmif_get_var_itemsize(id, "SelectedOutputHeadings", bytes) + allocate(character(len=bytes) :: headings(col)) + status = bmif_get_value(id, "SelectedOutputHeadings", headings) + ! Get selected output + status = bmif_get_value(id, "SelectedOutput", selected_out) + ! Print results + do i = 1, rows/2 + write(*,*) "Cell number ", i + write(*,*) " Density: ", density(i) + write(*,*) " Volume: ", volume(i) + write(*,*) " Components: " + do j = 1, ncomps + write(*,'(10x,i2,A2,A10,A2,f10.4)') j, " ",trim(components(j)), ": ", c(i,j) + enddo + write(*,*) " Selected output: " + do j = 1, col + write(*,'(10x,i3,A2,A20,A2,1pe15.4)') j, " ", trim(headings(j)),": ", selected_out(i,j) + enddo + enddo + deallocate(selected_out) + enddo + endif + enddo + call BMI_testing(id) + ! -------------------------------------------------------------------------- + ! Additional features and finalize + ! -------------------------------------------------------------------------- + ! Use utility instance of PhreeqcRM to calculate pH of a mixture + allocate (c_well(1,ncomps)) + do i = 1, ncomps + c_well(1,i) = 0.5 * c(1,i) + 0.5 * c(10,i) + enddo + allocate(tc(1), p_atm(1)) + tc(1) = 15.0 + p_atm(1) = 3.0 + iphreeqc_id = RM_Concentrations2Utility(id, c_well, 1, tc, p_atm) + string = "SELECTED_OUTPUT 5; -pH;RUN_CELLS; -cells 1" + ! Alternatively, utility pointer is worker number nthreads + 1 + iphreeqc_id1 = RM_GetIPhreeqcId(id, RM_GetThreadCount(id) + 1) + status = SetOutputFileName(iphreeqc_id, "Advect_f90_utility.txt") + status = SetOutputFileOn(iphreeqc_id, .true.) + status = RunString(iphreeqc_id, string) + if (status .ne. 0) status = RM_Abort(id, status, "IPhreeqc RunString failed") + status = SetCurrentSelectedOutputUserNumber(iphreeqc_id, 5) + status = GetSelectedOutputValue(iphreeqc_id, 1, 1, vtype, pH, svalue) + ! Dump results + status = RM_SetDumpFileName(id, "AdvectBMI_f90.dmp") + dump_on = 1 + append = 0 + status = RM_DumpModule(id, dump_on, append) + ! Clean up + status = RM_CloseFiles(id) + status = RM_MpiWorkerBreak(id) + status = bmif_finalize(id) + ! Deallocate + deallocate(por) + deallocate(sat) + deallocate(components) + deallocate(headings) + deallocate(bc1) + deallocate(bc2) + deallocate(bc_f1) + deallocate(bc_conc) + deallocate(c) + deallocate(density) + deallocate(temperature) + deallocate(c_well) + deallocate(pressure) + deallocate(tc) + deallocate(p_atm) + + return + end subroutine AdvectBMI_f90 + + SUBROUTINE advectionbmi_f90(c, bc_conc, ncomps, nxyz) + implicit none + real(kind=8), dimension(:,:), allocatable, intent(inout) :: c + real(kind=8), dimension(:,:), allocatable, intent(in) :: bc_conc + integer, intent(in) :: ncomps, nxyz + integer :: i, j + ! Advect + do i = nxyz/2, 2, -1 + do j = 1, ncomps + c(i,j) = c(i-1,j) + enddo + enddo + ! Cell 1 gets boundary condition + do j = 1, ncomps + c(1,j) = bc_conc(1,j) + enddo + END SUBROUTINE advectionbmi_f90 + +#ifdef USE_MPI + integer(kind=C_INT) function worker_tasks_f(method_number) BIND(C, NAME='worker_tasks_f') + USE ISO_C_BINDING + implicit none + interface + integer function do_something() + end function do_something + + SUBROUTINE register_basic_callback_fortran() + implicit none + END SUBROUTINE register_basic_callback_fortran + end interface + integer(kind=c_int), intent(in) :: method_number + integer :: status + if (method_number .eq. 1000) then + status = do_something() + else if (method_number .eq. 1001) then + call register_basic_callback_fortran() + endif + worker_tasks_f = 0 + end function worker_tasks_f + + integer function do_something() + implicit none + INCLUDE 'mpif.h' + integer status + integer i, method_number, mpi_myself, mpi_task, mpi_tasks, worker_number + method_number = 1000 + call MPI_Comm_size(MPI_COMM_WORLD, mpi_tasks, status) + call MPI_Comm_rank(MPI_COMM_WORLD, mpi_myself, status) + if (mpi_myself .eq. 0) then + CALL MPI_Bcast(method_number, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, status) + write(*,*) "I am root." + do i = 1, mpi_tasks-1 + CALL MPI_Recv(worker_number, 1, MPI_INTEGER, i, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE, status) + write(*,*) "Recieved data from worker number ", worker_number, "." + enddo + else + CALL MPI_Send(mpi_myself, 1, MPI_INTEGER, 0, 0, MPI_COMM_WORLD, status) + endif + do_something = 0 + end function do_something +#endif + +subroutine BMI_testing(id) +USE, intrinsic :: ISO_C_BINDING + USE BMIPhreeqcRM + USE IPhreeqc + implicit none + interface + integer function assert(tf) + logical, intent(in) :: tf + end function assert + end interface + integer, intent(in) :: id + character(100) :: string + integer :: status, dim, isel + integer :: i, j, n, bytes, nbytes + integer :: nxyz, rm_nxyz + integer :: ncomps, rm_ncomps + character(len=:), dimension(:), allocatable :: components, rm_components + character(len=:), allocatable :: component + character(len=:), dimension(:), allocatable :: inputvars + character(len=:), dimension(:), allocatable :: outputvars + character(len=:), dimension(:), allocatable :: pointablevars + character(len=:), allocatable :: prefix, rm_prefix + real(kind=8), dimension(:), allocatable :: gfw, rm_gfw + real(kind=8), dimension(:,:), allocatable :: c, c_rm + integer :: so_count, rm_so_count + integer :: nuser, rm_nuser + integer :: col_count, rm_col_count + integer :: row_count, rm_row_count + integer :: itemsize + real(kind=8), dimension(:,:), allocatable :: so, rm_so + character(LEN=:), dimension(:), allocatable :: headings, rm_headings + character(LEN=:), allocatable :: heading + real(kind=8) :: time, rm_time + real(kind=8) :: time_step, rm_time_step + real(kind=8), dimension(:), allocatable :: density, rm_density + real(kind=8), dimension(:), allocatable :: porosity, rm_porosity + real(kind=8), dimension(:), allocatable :: pressure, rm_pressure + real(kind=8), dimension(:), allocatable :: saturation, rm_saturation + real(kind=8), dimension(:), allocatable :: temperature, rm_temperature + real(kind=8), dimension(:), allocatable :: volume, rm_volume + logical :: tf + character(LEN=:), allocatable :: alloc_string + real(kind=8), pointer :: real_ptr + real(kind=c_double), pointer :: real_dim_ptr(:) + integer, pointer :: integer_ptr + logical, pointer :: logical_ptr + + status = bmif_get_component_name(id, string) + write(*,*) trim(string) + time = bmif_get_current_time(id, time) + write(*,*) time + time = bmif_get_end_time(id, time) + write(*,*) time + status = bmif_get_time_units(id, string) + write(*,*) string + time = bmif_get_time_step(id, time) + write(*,*) time + ! Time + rm_time = 3600 + status = bmif_set_value(id, "Time", rm_time) + status = bmif_get_value(id, "Time", time) + status = assert(rm_time .eq. time) + rm_time = RM_GetTime(id) + status = bmif_get_value_ptr(id, "Time", real_ptr) + status = assert(time .eq. rm_time) + status = bmif_get_current_time(id, time) + status = assert(time .eq. rm_time) + ! TimeStep + rm_time_step = 60 + status = bmif_set_value(id, "TimeStep", rm_time_step) + status = bmif_get_value(id, "TimeStep", time_step) + status = assert(time_step .eq. rm_time_step) + rm_time_step = RM_GetTimeStep(id) + status = assert(time_step .eq. rm_time_step) + status = bmif_get_time_step(id, time_step) + status = assert(time_step .eq. rm_time_step) + ! InputVarNames + status = bmif_get_input_var_names(id, inputvars) + write(*,*) "Input variables (setters)" + do i = 1, size(inputvars) + write(*,"(1x, I4, A60)") i, trim(inputvars(i)) + status = bmif_get_var_units(id, inputvars(i), string) + write(*,"(5x, A60)") trim(string) + status = bmif_get_var_type(id, inputvars(i), string) + write(*,"(5x, A60)") trim(string) + status = bmif_get_var_itemsize(id, inputvars(i), itemsize) + write(*, "(5x, I60)") itemsize + status = bmif_get_var_nbytes(id, inputvars(i), nbytes) + write(*, "(5x, I60)") nbytes + enddo + ! OutputVarNames + status = bmif_get_output_var_names(id, outputvars) + write(*,*) "Output variables (getters)" + do i = 1, size(outputvars) + write(*,"(1x, I4, A60)") i, trim(outputvars(i)) + status = bmif_get_var_units(id, outputvars(i), string) + write(*,"(5x, A60)") trim(string) + status = bmif_get_var_type(id, outputvars(i), string) + write(*,"(5x, A60)") trim(string) + status = bmif_get_var_itemsize(id, outputvars(i), itemsize) + write(*, "(5x, I60)") itemsize + status = bmif_get_var_nbytes(id, outputvars(i), nbytes) + write(*, "(5x, I60)") nbytes + enddo + ! PointableVarNames + status = bmif_get_pointable_var_names(id, pointablevars) + write(*,*) "Pointable variables (GetValuePtr)" + do i = 1, size(pointablevars) + write(*,"(1x, I4, A60)") i, trim(pointablevars(i)) + enddo + ! ComponentCount + status = bmif_get_value(id, "ComponentCount", ncomps) + rm_ncomps = RM_GetComponentCount(id) + status = assert(ncomps .eq. rm_ncomps) + ! Components + status = bmif_get_value(id, "Components", components) + status = bmif_get_var_itemsize(id, "Components", itemsize) + status = bmif_get_var_nbytes(id, "Components", nbytes) + dim = nbytes / itemsize + status = assert(dim .eq. size(components)) + allocate(character(len=itemsize) :: component) + do i = 1, dim + j = i + status = RM_GetComponent(id, j, component) + status = assert(component .eq. components(i)) + enddo + status = RM_GetComponents(id, rm_components) + do i = 1, dim + status = assert(components(i) .eq. rm_components(i)) + enddo + + status = bmif_get_value(id, "Gfw", gfw) + do i = 1, size(components) + write(*,"(A10, F15.4)") trim(components(i)), gfw(i) + enddo + write(*,*) + + ! Concentrations + status = bmif_get_value(id, "GridCellCount", nxyz) + status = assert(nxyz .eq. RM_GetGridCellCount(id)) + status = bmif_get_value(id, "Concentrations", c) + allocate(c_rm(nxyz, ncomps)) + status = RM_GetConcentrations(id, c_rm) + do j = 1, ncomps + do i = 1, nxyz + if (c(i,j) .ne. c_rm(i,j)) then + status = assert(.false.) + exit + endif + enddo + enddo + + ! GetValue("Density") + ! RM_GetDensity and bmif_get_value("Density) always return + ! the calculated solution density + status = bmif_get_var_itemsize(id, "Density", itemsize) + status = bmif_get_var_nbytes(id, "Density", nbytes) + dim = nbytes / itemsize + allocate(rm_density(dim)) + status = RM_GetDensity(id, rm_density) + status = bmif_get_value(id, "Density", density) + do i = 1, nxyz + if (density(i) .ne. rm_density(i)) then + status = assert(.false.) + exit + endif + enddo + + ! FilePrefix + string = "NewPrefix" + status = bmif_set_value(id, "FilePrefix", string) + status = bmif_get_var_itemsize(id, "FilePrefix", itemsize) + status = bmif_get_var_nbytes(id, "FilePrefix", nbytes) + allocate(character(len=itemsize) :: rm_prefix) + status = assert(itemsize .eq. nbytes) + status = RM_GetFilePrefix(id, rm_prefix) + status = assert(string .eq. rm_prefix) + allocate(character(len=itemsize) :: prefix) + status = bmif_get_value(id, "FilePrefix", prefix) + status = assert(prefix .eq. rm_prefix) + + ! GetValue("Gfw") + status = bmif_get_value(id, "Gfw", gfw) + status = bmif_get_var_itemsize(id, "Gfw", itemsize) + status = bmif_get_var_nbytes(id, "Gfw", nbytes) + dim = nbytes / itemsize + allocate(rm_gfw(dim)) + status = RM_GetGfw(id, rm_gfw); + do i = 1, ncomps + if (gfw(i) .ne. rm_gfw(i)) then + status = assert(.false.) + exit + endif + enddo + + ! GridCellCount + status = bmif_get_value(id, "GridCellCount", nxyz) + rm_nxyz = RM_GetGridCellCount(id) + status = assert(nxyz .eq. rm_nxyz) + + ! GetValue("Porosity") + status = bmif_get_value_ptr(id, "Porosity", real_dim_ptr) + status = bmif_get_var_itemsize(id, "Porosity", itemsize) + status = bmif_get_var_nbytes(id, "Porosity", nbytes) + dim = nbytes / itemsize + allocate(rm_porosity(dim)) + rm_porosity = 0.25 + status = bmif_set_value(id, "Porosity", rm_porosity) + status = bmif_get_value(id, "Porosity", porosity) + do i = 1, nxyz + status = assert(porosity(i) .eq. rm_porosity(i)) + status = assert(porosity(i) .eq. real_dim_ptr(i)) + enddo + status = RM_GetPorosity(id, rm_porosity); + do i = 1, nxyz + if (porosity(i) .ne. rm_porosity(i)) then + status = assert(.false.) + exit + endif + enddo + + ! GetValue("Pressure") + status = bmif_get_var_itemsize(id, "Pressure", itemsize) + status = bmif_get_var_nbytes(id, "Pressure", nbytes) + dim = nbytes / itemsize + allocate(rm_pressure(dim)) + rm_pressure = 10. + status = bmif_set_value(id, "Pressure", rm_pressure) + status = bmif_get_value(id, "Pressure", pressure) + do i = 1, nxyz + if (pressure(i) .ne. rm_pressure(i)) then + status = assert(.false.) + exit + endif + enddo + status = RM_GetPressure(id, rm_pressure); + do i = 1, nxyz + if (pressure(i) .ne. rm_pressure(i)) then + status = assert(.false.) + exit + endif + enddo + + ! GetValue("Saturation") + ! Always returns solution_volume/(rv * porosity) for each cell + status = bmif_get_var_itemsize(id, "Saturation", itemsize) + status = bmif_get_var_nbytes(id, "Saturation", nbytes) + dim = nbytes / itemsize + allocate(rm_saturation(dim)) + status = bmif_get_value(id, "Saturation", saturation) + status = RM_GetSaturation(id, rm_saturation); + do i = 1, nxyz + if (saturation(i) .ne. rm_saturation(i)) then + status = assert(.false.) + exit + endif + enddo + + ! GetValue("SolutionVolume") + status = bmif_get_var_itemsize(id, "SolutionVolume", itemsize) + status = bmif_get_var_nbytes(id, "SolutionVolume", nbytes) + dim = nbytes / itemsize + allocate(rm_volume(dim)) + status = bmif_get_value(id, "SolutionVolume", volume) + status = RM_GetSolutionVolume(id, rm_volume); + do i = 1, nxyz + if (volume(i) .ne. rm_volume(i)) then + status = assert(.false.) + exit + endif + enddo + + ! GetValue("Temperature") + status = bmif_get_var_itemsize(id, "Temperature", itemsize) + status = bmif_get_var_nbytes(id, "Temperature", nbytes) + dim = nbytes / itemsize + allocate(rm_temperature(dim)) + rm_temperature = 11. + status = bmif_set_value(id, "Temperature", rm_temperature) + status = bmif_get_value(id, "Temperature", temperature) + do i = 1, nxyz + if (temperature(i) .ne. rm_temperature(i)) then + status = assert(.false.) + exit + endif + enddo + status = RM_GetTemperature(id, rm_temperature); + do i = 1, nxyz + if (temperature(i) .ne. rm_temperature(i)) then + status = assert(.false.) + exit + endif + enddo + + ! GetValue("SelectedOutput") + status = bmif_get_value(id, "SelectedOutputCount", so_count); + rm_so_count = RM_GetSelectedOutputCount(id); + status = assert(so_count .eq. rm_so_count) + do isel = 1, so_count ! one based + i = isel + status = bmif_set_value(id, "NthSelectedOutput", i) + status = bmif_get_value(id, "CurrentSelectedOutputUserNumber", nuser) + rm_nuser = RM_GetCurrentSelectedOutputUserNumber(id) + status = assert(nuser .eq. rm_nuser) + i = isel + rm_nuser = RM_GetNthSelectedOutputUserNumber(id, i) + status = assert(nuser .eq. rm_nuser) + + status = bmif_get_value(id, "SelectedOutputColumnCount", col_count) + rm_col_count =RM_GetSelectedOutputColumnCount(id) + status = assert(col_count .eq. rm_col_count) + + status = bmif_get_value(id, "SelectedOutputRowCount", row_count) + rm_row_count = RM_GetSelectedOutputRowCount(id) + status = assert(row_count .eq. rm_row_count) + + status = bmif_get_var_nbytes(id, "SelectedOutput", nbytes); + status = bmif_get_var_itemsize(id, "SelectedOutput", itemsize); + dim = nbytes / itemsize; + status = assert(dim .eq. rm_row_count*rm_col_count) + status = bmif_get_value(id, "SelectedOutput", so) + allocate(rm_so(rm_row_count, rm_col_count)) + status = RM_GetSelectedOutput(id, rm_so); + do j = 1, col_count + do i = 1, row_count + if (so(i,j) .ne. rm_so(i,j)) then + status = assert(.false.) + exit + endif + enddo + enddo + ! check headings + status = bmif_get_var_nbytes(id, "SelectedOutputHeadings", nbytes) + status = bmif_get_var_itemsize(id, "SelectedOutputHeadings", itemsize) + dim = nbytes / itemsize + status = assert(dim .eq. RM_GetSelectedOutputColumnCount(id)) + status = bmif_get_value(id, "SelectedOutputHeadings", headings) + !allocate(character(len=itemsize) :: rm_headings(dim)) + status = RM_GetSelectedOutputHeadings(id, rm_headings) + do j = 1, col_count + if (headings(j) .ne. rm_headings(j)) then + status = assert(.false.) + endif + enddo + status = bmif_get_var_itemsize(id, "SelectedOutputHeadings", itemsize) + allocate(character(len=itemsize) :: heading) + do j = 1, col_count + status = RM_GetSelectedOutputHeading(id, j, heading) + if (heading .ne. rm_headings(j)) then + status = assert(.false.) + endif + enddo + enddo + +END subroutine BMI_testing +integer function assert(tf) +logical, intent(in) :: tf +if(tf) then + assert = 0 + return +endif +stop "Assert failed" +end function assert + +#endif diff --git a/Tests/Advect_f90.F90 b/Tests/Advect_f90.F90 index 7e7891be8..28cfd863d 100644 --- a/Tests/Advect_f90.F90 +++ b/Tests/Advect_f90.F90 @@ -1,7 +1,7 @@ module mydata - double precision, dimension(:), pointer :: K_ptr + real(kind=8), dimension(:), pointer :: K_ptr integer :: rm_id end module mydata @@ -17,8 +17,8 @@ subroutine Advect_f90() BIND(C, NAME='Advect_f90') interface subroutine advection_f90(c, bc_conc, ncomps, nxyz) implicit none - double precision, dimension(:,:), allocatable, intent(inout) :: c - double precision, dimension(:,:), allocatable, intent(in) :: bc_conc + real(kind=8), dimension(:,:), allocatable, intent(inout) :: c + real(kind=8), dimension(:,:), allocatable, intent(in) :: bc_conc integer, intent(in) :: ncomps, nxyz end subroutine advection_f90 integer function do_something() @@ -41,10 +41,10 @@ END SUBROUTINE register_basic_callback_fortran integer :: nthreads integer :: id integer :: status - double precision, dimension(:), allocatable, target :: hydraulic_K - double precision, dimension(:), allocatable :: rv - double precision, dimension(:), allocatable :: por - double precision, dimension(:), allocatable :: sat + real(kind=8), dimension(:), allocatable, target :: hydraulic_K + real(kind=8), dimension(:), allocatable :: rv + real(kind=8), dimension(:), allocatable :: por + real(kind=8), dimension(:), allocatable :: sat integer, dimension(:), allocatable :: print_chemistry_mask integer, dimension(:), allocatable :: grid2chem integer :: nchem @@ -52,29 +52,29 @@ END SUBROUTINE register_basic_callback_fortran character(200) :: string1 integer :: ncomps, ncomps1 character(100), dimension(:), allocatable :: components - double precision, dimension(:), allocatable :: gfw + real(kind=8), dimension(:), allocatable :: gfw integer, dimension(:,:), allocatable :: ic1, ic2 - double precision, dimension(:,:), allocatable :: f1 + real(kind=8), dimension(:,:), allocatable :: f1 integer :: nbound integer, dimension(:), allocatable :: bc1, bc2 - double precision, dimension(:), allocatable :: bc_f1 + real(kind=8), dimension(:), allocatable :: bc_f1 integer, dimension(:), allocatable :: module_cells - double precision, dimension(:,:), allocatable :: bc_conc - double precision, dimension(:,:), allocatable :: c - double precision :: time, time_step - double precision, dimension(:), allocatable :: density - double precision, dimension(:), allocatable :: sat_calc - double precision, dimension(:), allocatable :: volume - double precision, dimension(:), allocatable :: temperature - double precision, dimension(:), allocatable :: pressure + real(kind=8), dimension(:,:), allocatable :: bc_conc + real(kind=8), dimension(:,:), allocatable :: c + real(kind=8) :: time, time_step + real(kind=8), dimension(:), allocatable :: density + real(kind=8), dimension(:), allocatable :: sat_calc + real(kind=8), dimension(:), allocatable :: volume + real(kind=8), dimension(:), allocatable :: temperature + real(kind=8), dimension(:), allocatable :: pressure integer :: isteps, nsteps - double precision, dimension(:,:), allocatable :: selected_out + real(kind=8), dimension(:,:), allocatable :: selected_out integer :: col, isel, n_user character(100) :: heading - double precision, dimension(:,:), allocatable :: c_well - double precision, dimension(:), allocatable :: tc, p_atm + real(kind=8), dimension(:,:), allocatable :: c_well + real(kind=8), dimension(:), allocatable :: tc, p_atm integer :: vtype - double precision :: pH + real(kind=8) :: pH character(100) :: svalue integer :: iphreeqc_id, iphreeqc_id1 integer :: dump_on, append @@ -444,8 +444,8 @@ end subroutine Advect_f90 SUBROUTINE advection_f90(c, bc_conc, ncomps, nxyz) implicit none - double precision, dimension(:,:), allocatable, intent(inout) :: c - double precision, dimension(:,:), allocatable, intent(in) :: bc_conc + real(kind=8), dimension(:,:), allocatable, intent(inout) :: c + real(kind=8), dimension(:,:), allocatable, intent(in) :: bc_conc integer, intent(in) :: ncomps, nxyz integer :: i, j ! Advect diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 2cc859ea9..817fe685d 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -1,5 +1,22 @@ +cmake_minimum_required(VERSION 3.20) ### tests -if (PHREEQCRM_FORTRAN_TESTING) + +if(_PHREEQCRM_TEST_INSTALL) + project(TestInstall + LANGUAGES CXX C + ) + option(PHREEQCRM_FORTRAN_TESTING "Build Fortran test" OFF) + if(PHREEQCRM_FORTRAN_TESTING) + enable_language(Fortran) + endif() + find_package(PhreeqcRM REQUIRED) # sets PhreeqcRM_DIR if found + if(yaml-cpp_FOUND) + set(PHREEQCRM_WITH_YAML_CPP ON) + endif() + enable_testing() +endif() + +if(PHREEQCRM_FORTRAN_TESTING) project(FortranAdvect Fortran) # TestRM Fortran library @@ -7,21 +24,63 @@ if (PHREEQCRM_FORTRAN_TESTING) # TestRM Fortran source target_sources(FortranAdvect PRIVATE + ../src/BMI_interface.F90 ../src/IPhreeqcPhast/IPhreeqc/IPhreeqc_interface.F90 ../src/RM_interface.F90 Advect_f90.F90 + AdvectBMI_f90.F90 Gas_f90.F90 - SimpleAdvect_f90.F90 + SimpleAdvect_f90.F90 Species_f90.F90 ) # place [*.F[90]] files into "Source Files" + source_group("Source Files" FILES "../src/BMI_interface.F90") + source_group("Source Files" FILES "../src/BMI_not_implemented.inc") source_group("Source Files" FILES "../src/IPhreeqcPhast/IPhreeqc/IPhreeqc_interface.F90") source_group("Source Files" FILES "../src/RM_interface.F90") source_group("Source Files" FILES "Advect_f90.F90") + source_group("Source Files" FILES "AdvectBMI_f90.F90") source_group("Source Files" FILES "Gas_f90.F90") source_group("Source Files" FILES "SimpleAdvect_f90.F90") source_group("Source Files" FILES "Species_f90.F90") + + if(_PHREEQCRM_TEST_INSTALL) + target_sources(FortranAdvect PRIVATE + ${PhreeqcRM_DIR}/src/IPhreeqc_interface.F90 + ${PhreeqcRM_DIR}/src/RM_interface.F90 + ) + source_group("Source Files" FILES "${PhreeqcRM_DIR}/src/IPhreeqcPhast/IPhreeqc/IPhreeqc_interface.F90") + source_group("Source Files" FILES "${PhreeqcRM_DIR}/src/RM_interface.F90") + else() + target_sources(FortranAdvect PRIVATE + ../src/IPhreeqcPhast/IPhreeqc/IPhreeqc_interface.F90 + ../src/RM_interface.F90 + ) + source_group("Source Files" FILES "../src/IPhreeqcPhast/IPhreeqc/IPhreeqc_interface.F90") + source_group("Source Files" FILES "../src/RM_interface.F90") + endif() + + + if(PHREEQCRM_WITH_YAML_CPP) + target_sources(FortranAdvect PRIVATE + WriteYAMLFile_f90.F90 + ) + source_group("Source Files" FILES "WriteYAMLFile_f90.F90") + + if(_PHREEQCRM_TEST_INSTALL) + target_sources(FortranAdvect PRIVATE + ${PhreeqcRM_DIR}/src/YAML_interface.F90 + ) + source_group("Source Files" FILES "${PhreeqcRM_DIR}/src/YAML_interface.F90") + else() + target_sources(FortranAdvect PRIVATE + ../src/YAML_interface.F90 + ) + source_group("Source Files" FILES "../src/YAML_interface.F90") + endif() + endif() + # The next line sets defines/includes/libraries # for compiling and linking the FortranAdvect library @@ -57,14 +116,21 @@ target_sources(TestRM PRIVATE SimpleAdvect_cpp.cpp Species_c.c Species_cpp.cpp - WriteYAMLFile_cpp.cpp ) +if(PHREEQCRM_WITH_YAML_CPP) + target_sources(TestRM PRIVATE + WriteYAMLFile_cpp.cpp + ) +endif() + if(PHREEQCRM_FORTRAN_TESTING) target_compile_definitions(TestRM PRIVATE TEST_FORTRAN) endif() # library dependencies +target_link_libraries(TestRM PhreeqcRM::PhreeqcRM) + if(PHREEQCRM_FORTRAN_TESTING) # Override bug reported on: # http://www.cmake.org/pipermail/cmake/2009-July/030954.html @@ -73,10 +139,7 @@ if(PHREEQCRM_FORTRAN_TESTING) set(CMAKE_Fortran_FLAGS_DEBUG "/Od ${CMAKE_Fortran_FLAGS_DEBUG}") endif() endif() - - target_link_libraries(TestRM PhreeqcRM::PhreeqcRM FortranAdvect) -else() - target_link_libraries(TestRM PhreeqcRM::PhreeqcRM) + target_link_libraries(TestRM FortranAdvect) endif() # test compile and run @@ -84,45 +147,69 @@ add_test(TestCompileAndRun TestRM) set_property(TARGET TestRM APPEND PROPERTY ADDITIONAL_CLEAN_FILES - $/AdvectBMI_cpp.chem.txt - $/AdvectBMI_cpp.dmp - $/AdvectBMI_cpp.log.txt - $/AdvectBMI_cpp_utility.txt - $/AdvectBMI_cpp.yaml - $/Advect_c.chem.txt - $/Advect_c.dmp - $/Advect_c.log.txt - $/Advect_cpp.chem.txt - $/Advect_cpp.dmp - $/Advect_cpp.log.txt - $/Advect_cpp_units_utility.txt - $/Advect_cpp_units_worker.chem.txt - $/Advect_cpp_units_worker.log.txt - $/Advect_cpp_utility.txt - $/Advect_c_utility.txt - $/Gas_c.chem.txt - $/Gas_c.log.txt - $/Gas_cpp.chem.txt - $/Gas_cpp.log.txt - $/SimpleAdvect_c.chem.txt - $/SimpleAdvect_c.log.txt - $/SimpleAdvect_cpp.chem.txt - $/SimpleAdvect_cpp.log.txt - $/Species_c.chem.txt - $/Species_c.dmp - $/Species_c.log.txt - $/Species_cpp.chem.txt - $/Species_cpp.dmp - $/Species_cpp.log.txt - $/Species_cpp_utility.txt - $/Species_c_utility.txt + Advect_c_utility.txt + Advect_c.chem.txt + Advect_c.dmp + Advect_c.log.txt + Advect_cpp_units_utility.txt + Advect_cpp_units_worker.chem.txt + Advect_cpp_units_worker.log.txt + Advect_cpp_utility.txt + Advect_cpp.chem.txt + Advect_cpp.dmp + Advect_cpp.log.txt + Advect_f90_utility.txt + Advect_f90.chem.txt + Advect_f90.dmp + Advect_f90.log.txt + AdvectBMI_cpp_utility.txt + AdvectBMI_cpp.chem.txt + AdvectBMI_cpp.dmp + AdvectBMI_cpp.log.txt + AdvectBMI_cpp.yaml + AdvectBMI_f90.chem.txt + AdvectBMI_f90.dmp + AdvectBMI_f90.log.txt + AdvectBMI_f90.yaml + Advectcpp_utility.txt + Advectcpp.dmp + Gas_c.chem.txt + Gas_c.log.txt + Gas_cpp.chem.txt + Gas_cpp.log.txt + Gas_f90.chem.txt + Gas_f90.log.txt + SimpleAdvect_c.chem.txt + SimpleAdvect_c.log.txt + SimpleAdvect_cpp.chem.txt + SimpleAdvect_cpp.log.txt + SimpleAdvect_f90.chem.txt + SimpleAdvect_f90.log.txt + Species_c_utility.txt + Species_c.chem.txt + Species_c.dmp + Species_c.log.txt + Species_cpp_utility.txt + Species_cpp.chem.txt + Species_cpp.dmp + Species_cpp.log.txt + Species_f90_utility.txt + Species_f90.chem.txt + Species_f90.dmp + Species_f90.log.txt ) if(MSVC AND BUILD_SHARED_LIBS) - # copy dll + # copy PhreeqcRM dll add_custom_command(TARGET TestRM POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy $ $ ) + if(PHREEQCRM_WITH_YAML_CPP) + # copy yaml-cpp dll + add_custom_command(TARGET TestRM POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy $ $ + ) + endif() endif() # MPI test @@ -136,3 +223,9 @@ if(PHREEQCRM_BUILD_MPI) ${MPIEXEC_POSTFLAGS} ) endif() + +# get_cmake_property(_variableNames VARIABLES) +# list (SORT _variableNames) +# foreach (_variableName ${_variableNames}) +# message(STATUS "${_variableName}=${${_variableName}}") +# endforeach() diff --git a/Tests/Gas_f90.F90 b/Tests/Gas_f90.F90 index ea7480edb..b76333fbe 100644 --- a/Tests/Gas_f90.F90 +++ b/Tests/Gas_f90.F90 @@ -10,9 +10,9 @@ subroutine Gas_f90() BIND(C, NAME='Gas_f90') interface subroutine PrintCells(gas_comps, gas_moles, gas_p, gas_phi, str) character(*), dimension(:), allocatable, intent(in) :: gas_comps - double precision, dimension(:,:), allocatable, intent(in) :: gas_moles - double precision, dimension(:,:), allocatable, intent(in) :: gas_p - double precision, dimension(:,:), allocatable, intent(in) :: gas_phi + real(kind=8), dimension(:,:), allocatable, intent(in) :: gas_moles + real(kind=8), dimension(:,:), allocatable, intent(in) :: gas_p + real(kind=8), dimension(:,:), allocatable, intent(in) :: gas_phi character(*), intent(in) :: str end subroutine PrintCells end interface @@ -27,14 +27,14 @@ end subroutine PrintCells integer :: status integer :: ncomps integer :: ngas - double precision, dimension(:), allocatable :: por - double precision, dimension(:), allocatable :: sat + real(kind=8), dimension(:), allocatable :: por + real(kind=8), dimension(:), allocatable :: sat character(100), dimension(:), allocatable :: gas_comps character(100), dimension(:), allocatable :: components integer, dimension(:,:), allocatable :: ic1, ic2 - double precision, dimension(:,:), allocatable :: f1 - double precision, dimension(:,:), allocatable :: gas_moles, gas_p, gas_phi - double precision, dimension(:), allocatable :: gas_volume + real(kind=8), dimension(:,:), allocatable :: f1 + real(kind=8), dimension(:,:), allocatable :: gas_moles, gas_p, gas_phi + real(kind=8), dimension(:), allocatable :: gas_volume !character(LEN=1), dimension(:), allocatable :: errstr #ifdef FORTRAN_2003 character(LEN=:), allocatable :: errstr @@ -198,9 +198,9 @@ end subroutine gas_f90 subroutine PrintCells(gas_comps, gas_moles, gas_p, gas_phi, str) implicit none character(*), dimension(:), allocatable, intent(in) :: gas_comps - double precision, dimension(:,:), allocatable, intent(in) :: gas_moles - double precision, dimension(:,:), allocatable, intent(in) :: gas_p - double precision, dimension(:,:), allocatable, intent(in) :: gas_phi + real(kind=8), dimension(:,:), allocatable, intent(in) :: gas_moles + real(kind=8), dimension(:,:), allocatable, intent(in) :: gas_p + real(kind=8), dimension(:,:), allocatable, intent(in) :: gas_phi integer :: n character(*), intent(in) :: str integer :: i,j diff --git a/Tests/Makefile.am b/Tests/Makefile.am index a2a137c86..bdf98e9f7 100644 --- a/Tests/Makefile.am +++ b/Tests/Makefile.am @@ -21,7 +21,7 @@ test_SOURCES =\ # Ubuntu 22.04.1 # sudo apt install libyaml-cpp-dev -test_LDADD = $(top_builddir)/libphreeqcrm.la -lyaml-cpp +test_LDADD = $(top_builddir)/libphreeqcrm.la test_LINK = $(CXXLINK) CLEANFILES =\ @@ -37,6 +37,10 @@ CLEANFILES =\ Advect_cpp.chem.txt\ Advect_cpp.dmp\ Advect_cpp.log.txt\ + Advect_f90_utility.txt\ + Advect_f90.chem.txt\ + Advect_f90.dmp\ + Advect_f90.log.txt\ AdvectBMI_cpp_units_utility.txt\ AdvectBMI_cpp_units_worker.txt\ AdvectBMI_cpp_utility.txt\ @@ -44,6 +48,12 @@ CLEANFILES =\ AdvectBMI_cpp.dmp\ AdvectBMI_cpp.log.txt\ AdvectBMI_cpp.yaml\ + AdvectBMI_f90.chem.txt\ + AdvectBMI_f90.dmp\ + AdvectBMI_f90.log.txt\ + AdvectBMI_f90.yaml\ + Advectcpp_utility.txt\ + Advectcpp.dmp\ Gas_c_utility.txt\ Gas_c.chem.txt\ Gas_c.dmp\ @@ -52,10 +62,14 @@ CLEANFILES =\ Gas_cpp.chem.txt\ Gas_cpp.dmp\ Gas_cpp.log.txt\ + Gas_f90.chem.txt\ + Gas_f90.log.txt\ SimpleAdvect_c.chem.txt\ SimpleAdvect_c.log.txt\ SimpleAdvect_cpp.chem.txt\ SimpleAdvect_cpp.log.txt\ + SimpleAdvect_f90.chem.txt\ + SimpleAdvect_f90.log.txt\ Species_c_utility.txt\ Species_c.chem.txt\ Species_c.dmp\ @@ -64,20 +78,33 @@ CLEANFILES =\ Species_cpp.chem.txt\ Species_cpp.dmp\ Species_cpp.log.txt\ + Species_f90_utility.txt\ + Species_f90.chem.txt\ + Species_f90.dmp\ + Species_f90.log.txt\ Units_Worker.chem.txt\ Units_Worker.log.txt\ Utility_c.txt\ Utility_cpp.out +FCDEFS= + if PHREEQCRM_TEST_FORTRAN +DEFS+=-DTEST_FORTRAN +FCDEFS+=-DTEST_FORTRAN + test_SOURCES+=\ + ../src/BMI_interface.F90\ + ../src/IPhreeqcPhast/IPhreeqc/IPhreeqc_interface.F90\ + ../src/RM_interface.F90\ + ../src/YAML_interface.F90\ Advect_f90.F90\ + AdvectBMI_f90.F90\ Gas_f90.F90\ SimpleAdvect_f90.F90\ Species_f90.F90\ - ../src/RM_interface.F90\ - ../src/IPhreeqcPhast/IPhreeqc/IPhreeqc_interface.F90 + WriteYAMLFile_f90.F90 test_LDADD+=$(FCLIBS) @@ -86,12 +113,30 @@ mostlyclean-local: clean-modules clean-modules: -test -z $(FC_MODEXT) || $(RM) *.$(FC_MODEXT) -advection_f90.$(OBJEXT) : ../src/RM_interface.$(OBJEXT) ../src/IPhreeqcPhast/IPhreeqc/IPhreeqc_interface.$(OBJEXT) +AdvectBMI_f90.$(OBJEXT) : AdvectBMI_f90.F90 Advect_f90.$(OBJEXT) ../src/IPhreeqcPhast/IPhreeqc/IPhreeqc_interface.$(OBJEXT) ../src/BMI_interface.$(OBJEXT) + +# mydata.mod +Advect_f90.$(OBJEXT) : Advect_f90.F90 ../src/IPhreeqcPhast/IPhreeqc/IPhreeqc_interface.$(OBJEXT) ../src/RM_interface.$(OBJEXT) + +Gas_f90.$(OBJEXT) : Gas_f90.F90 Advect_f90.$(OBJEXT) ../src/IPhreeqcPhast/IPhreeqc/IPhreeqc_interface.$(OBJEXT) ../src/RM_interface.$(OBJEXT) -species_f90.$(OBJEXT) : ../src/RM_interface.$(OBJEXT) +SimpleAdvect_f90.$(OBJEXT) : SimpleAdvect_f90.F90 Advect_f90.$(OBJEXT) ../src/IPhreeqcPhast/IPhreeqc/IPhreeqc_interface.$(OBJEXT) ../src/RM_interface.$(OBJEXT) -gas_f90.$(OBJEXT) : ../src/RM_interface.$(OBJEXT) +Species_f90.$(OBJEXT) : Species_f90.F90 ../src/IPhreeqcPhast/IPhreeqc/IPhreeqc_interface.$(OBJEXT) ../src/RM_interface.$(OBJEXT) +# BMIPhreeqcRM.mod +../src/BMI_interface.$(OBJEXT) : ../src/BMI_interface.F90 ../src/RM_interface.$(OBJEXT) + +# IPhreeqc.mod +../src/IPhreeqcPhast/IPhreeqc/IPhreeqc_interface.$(OBJEXT) : ../src/IPhreeqcPhast/IPhreeqc/IPhreeqc_interface.F90 + +# PhreeqcRM.mod +../src/RM_interface.$(OBJEXT) : ../src/RM_interface.F90 + +# YAML_interface.mod +../src/YAML_interface.$(OBJEXT) : ../src/YAML_interface.F90 + +WriteYAMLFile_f90.$(OBJEXT) : WriteYAMLFile_f90.F90 ../src/YAML_interface.$(OBJEXT) endif @@ -99,6 +144,9 @@ endif # handle the FC_FUNC define correctly so $(DEFS) is replaced # by $(FCDEFS) # +if PHREEQCRM_WITH_YAMLCPP +FCDEFS+=-DUSE_YAML +endif PPFCCOMPILE = $(FC) $(FCDEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_FCFLAGS) $(FCFLAGS) LTPPFCCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=FC $(AM_LIBTOOLFLAGS) \ diff --git a/Tests/Output/AdvectBMI_cpp.chem.txt b/Tests/Output/AdvectBMI_cpp.chem.txt index fa8b4d136..c40df3119 100644 --- a/Tests/Output/AdvectBMI_cpp.chem.txt +++ b/Tests/Output/AdvectBMI_cpp.chem.txt @@ -196,7 +196,7 @@ Reading input data for simulation 4. ------------------------------------ ------------------------------- -End of Run after 3.687 Seconds. +End of Run after 0.512 Seconds. ------------------------------- Database: phreeqc.dat @@ -273,10 +273,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.800e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = -4.978e-22 + Total alkalinity (eq/kg) = 1.157e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = 1.075e-18 + Electrical balance (eq) = 1.051e-18 Percent error, 100*(Cat-|An|)/(Cat+|An|) = 0.00 Iterations = 2 Total H = 2.213642e+01 @@ -327,7 +327,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 4.175 Seconds. +End of Run after 0.539 Seconds. ------------------------------- Time: 10 @@ -385,10 +385,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.800e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = -1.954e-19 + Total alkalinity (eq/kg) = 3.051e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = 8.407e-19 + Electrical balance (eq) = 7.408e-19 Percent error, 100*(Cat-|An|)/(Cat+|An|) = 0.00 Iterations = 5 Total H = 2.213642e+01 @@ -438,9 +438,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 4.18 Seconds. ------------------------------- +------------------------------- +End of Run after 0.539 Seconds. +------------------------------- Time: 10 Chemistry cell: 2 @@ -497,10 +497,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.800e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = 1.656e-19 + Total alkalinity (eq/kg) = -2.928e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = 8.968e-19 + Electrical balance (eq) = 1.087e-18 Percent error, 100*(Cat-|An|)/(Cat+|An|) = 0.00 Iterations = 6 Total H = 2.213642e+01 @@ -551,7 +551,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 4.184 Seconds. +End of Run after 0.539 Seconds. ------------------------------- Time: 10 @@ -609,10 +609,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.800e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = 1.009e-18 + Total alkalinity (eq/kg) = -2.019e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = 5.877e-18 + Electrical balance (eq) = 6.299e-18 Percent error, 100*(Cat-|An|)/(Cat+|An|) = 0.00 Iterations = 6 Total H = 2.213642e+01 @@ -662,9 +662,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ -------------------------------- -End of Run after 4.188 Seconds. -------------------------------- +------------------------------ +End of Run after 0.54 Seconds. +------------------------------ Time: 10 Chemistry cell: 4 @@ -721,10 +721,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.758e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = 5.691e-19 + Total alkalinity (eq/kg) = 2.447e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = 2.786e-16 + Electrical balance (eq) = 2.790e-16 Percent error, 100*(Cat-|An|)/(Cat+|An|) = 0.00 Iterations = 7 Total H = 2.213642e+01 @@ -774,9 +774,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ -------------------------------- -End of Run after 4.192 Seconds. -------------------------------- +------------------------------ +End of Run after 0.54 Seconds. +------------------------------ Time: 10 Chemistry cell: 5 @@ -833,7 +833,7 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.211e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = -4.274e-19 + Total alkalinity (eq/kg) = 1.542e-18 Temperature (°C) = 20.00 Pressure (atm) = 2.00 Electrical balance (eq) = 9.176e-14 @@ -887,7 +887,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 4.195 Seconds. +End of Run after 0.541 Seconds. ------------------------------- Time: 10 @@ -945,10 +945,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.200e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = -1.274e-19 + Total alkalinity (eq/kg) = 3.336e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = -7.020e-16 + Electrical balance (eq) = -7.013e-16 Percent error, 100*(Cat-|An|)/(Cat+|An|) = -0.00 Iterations = 6 Total H = 2.213642e+01 @@ -999,7 +999,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 4.173 Seconds. +End of Run after 0.541 Seconds. ------------------------------- Time: 10 @@ -1057,7 +1057,7 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.200e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = 4.509e-18 + Total alkalinity (eq/kg) = 3.137e-18 Temperature (°C) = 20.00 Pressure (atm) = 2.00 Electrical balance (eq) = 7.519e-13 @@ -1111,7 +1111,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 4.176 Seconds. +End of Run after 0.539 Seconds. ------------------------------- Time: 10 @@ -1169,7 +1169,7 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.200e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = 1.023e-18 + Total alkalinity (eq/kg) = 2.785e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 Electrical balance (eq) = 1.445e-13 @@ -1222,9 +1222,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 4.18 Seconds. ------------------------------- +------------------------------- +End of Run after 0.539 Seconds. +------------------------------- Time: 10 Chemistry cell: 9 @@ -1279,10 +1279,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.200e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = -9.905e-19 + Total alkalinity (eq/kg) = -5.725e-21 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = -1.555e-17 + Electrical balance (eq) = -1.575e-17 Percent error, 100*(Cat-|An|)/(Cat+|An|) = -0.00 Iterations = 2 Total H = 2.213642e+01 @@ -1330,7 +1330,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 4.184 Seconds. +End of Run after 0.539 Seconds. ------------------------------- Time: 10 @@ -1387,10 +1387,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.200e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = -3.806e-18 + Total alkalinity (eq/kg) = -3.398e-18 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = -6.790e-17 + Electrical balance (eq) = -6.800e-17 Percent error, 100*(Cat-|An|)/(Cat+|An|) = -0.00 Iterations = 2 Total H = 2.213587e+01 @@ -1445,7 +1445,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------ -End of Run after 4.19 Seconds. +End of Run after 0.54 Seconds. ------------------------------ Time: 10 @@ -1502,10 +1502,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.200e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = -3.806e-18 + Total alkalinity (eq/kg) = -3.398e-18 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = -6.790e-17 + Electrical balance (eq) = -6.800e-17 Percent error, 100*(Cat-|An|)/(Cat+|An|) = -0.00 Iterations = 2 Total H = 2.213587e+01 @@ -1560,7 +1560,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 4.193 Seconds. +End of Run after 0.539 Seconds. ------------------------------- Time: 10 @@ -1617,10 +1617,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.200e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = -3.806e-18 + Total alkalinity (eq/kg) = -3.398e-18 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = -6.790e-17 + Electrical balance (eq) = -6.800e-17 Percent error, 100*(Cat-|An|)/(Cat+|An|) = -0.00 Iterations = 2 Total H = 2.213587e+01 @@ -1675,7 +1675,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 4.176 Seconds. +End of Run after 0.539 Seconds. ------------------------------- Time: 10 @@ -1732,10 +1732,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.200e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = -3.806e-18 + Total alkalinity (eq/kg) = -3.398e-18 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = -6.790e-17 + Electrical balance (eq) = -6.800e-17 Percent error, 100*(Cat-|An|)/(Cat+|An|) = -0.00 Iterations = 2 Total H = 2.213587e+01 @@ -1789,9 +1789,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 4.18 Seconds. ------------------------------- +------------------------------- +End of Run after 0.539 Seconds. +------------------------------- Time: 10 Chemistry cell: 14 @@ -1847,10 +1847,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.200e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = -3.806e-18 + Total alkalinity (eq/kg) = -3.398e-18 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = -6.790e-17 + Electrical balance (eq) = -6.800e-17 Percent error, 100*(Cat-|An|)/(Cat+|An|) = -0.00 Iterations = 2 Total H = 2.213587e+01 @@ -1904,9 +1904,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ -------------------------------- -End of Run after 4.184 Seconds. -------------------------------- +------------------------------ +End of Run after 0.54 Seconds. +------------------------------ Time: 10 Chemistry cell: 15 @@ -1962,10 +1962,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.200e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = -3.806e-18 + Total alkalinity (eq/kg) = -3.398e-18 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = -6.790e-17 + Electrical balance (eq) = -6.800e-17 Percent error, 100*(Cat-|An|)/(Cat+|An|) = -0.00 Iterations = 2 Total H = 2.213587e+01 @@ -2019,9 +2019,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ -------------------------------- -End of Run after 4.188 Seconds. -------------------------------- +------------------------------ +End of Run after 0.54 Seconds. +------------------------------ Time: 10 Chemistry cell: 16 @@ -2077,10 +2077,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.200e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = -3.806e-18 + Total alkalinity (eq/kg) = -3.398e-18 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = -6.790e-17 + Electrical balance (eq) = -6.800e-17 Percent error, 100*(Cat-|An|)/(Cat+|An|) = -0.00 Iterations = 2 Total H = 2.213587e+01 @@ -2135,7 +2135,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 4.191 Seconds. +End of Run after 0.541 Seconds. ------------------------------- Time: 10 @@ -2192,10 +2192,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.200e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = -3.806e-18 + Total alkalinity (eq/kg) = -3.398e-18 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = -6.790e-17 + Electrical balance (eq) = -6.800e-17 Percent error, 100*(Cat-|An|)/(Cat+|An|) = -0.00 Iterations = 2 Total H = 2.213587e+01 @@ -2250,7 +2250,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 4.195 Seconds. +End of Run after 0.541 Seconds. ------------------------------- Time: 10 @@ -2307,10 +2307,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.200e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = -3.806e-18 + Total alkalinity (eq/kg) = -3.398e-18 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = -6.790e-17 + Electrical balance (eq) = -6.800e-17 Percent error, 100*(Cat-|An|)/(Cat+|An|) = -0.00 Iterations = 2 Total H = 2.213587e+01 @@ -2365,7 +2365,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 4.197 Seconds. +End of Run after 0.542 Seconds. ------------------------------- Time: 10 @@ -2422,10 +2422,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.200e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = -3.806e-18 + Total alkalinity (eq/kg) = -3.398e-18 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = -6.790e-17 + Electrical balance (eq) = -6.800e-17 Percent error, 100*(Cat-|An|)/(Cat+|An|) = -0.00 Iterations = 2 Total H = 2.213587e+01 @@ -2480,7 +2480,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 4.203 Seconds. +End of Run after 0.542 Seconds. ------------------------------- Current distribution of cells for workers @@ -2496,7 +2496,7 @@ Cell number 0 Components: 0 H: 110.682 1 O: 55.3416 - 2 Charge: 5.37565e-18 + 2 Charge: 5.25387e-18 3 Ca: 0.000598214 4 Cl: 0.00119643 5 K: 2.93754e-13 @@ -2516,7 +2516,7 @@ Cell number 1 Components: 0 H: 110.682 1 O: 55.3416 - 2 Charge: 4.20355e-18 + 2 Charge: 3.70378e-18 3 Ca: 0.000598214 4 Cl: 0.00119643 5 K: 6.4971e-11 @@ -2536,7 +2536,7 @@ Cell number 2 Components: 0 H: 110.682 1 O: 55.3416 - 2 Charge: 4.48418e-18 + 2 Charge: 5.43731e-18 3 Ca: 0.00059821 4 Cl: 0.00119643 5 K: 8.49904e-09 @@ -2556,7 +2556,7 @@ Cell number 3 Components: 0 H: 110.682 1 O: 55.3416 - 2 Charge: 2.93827e-17 + 2 Charge: 3.14967e-17 3 Ca: 0.000597767 4 Cl: 0.00119643 5 K: 8.94576e-07 @@ -2576,7 +2576,7 @@ Cell number 4 Components: 0 H: 110.682 1 O: 55.3416 - 2 Charge: 1.39302e-15 + 2 Charge: 1.39497e-15 3 Ca: 0.000556681 4 Cl: 0.00119643 5 K: 8.23713e-05 @@ -2596,7 +2596,7 @@ Cell number 5 Components: 0 H: 110.682 1 O: 55.3416 - 2 Charge: 4.58803e-13 + 2 Charge: 4.58801e-13 3 Ca: 1.0618e-05 4 Cl: 0.00119643 5 K: 0.00106014 @@ -2616,7 +2616,7 @@ Cell number 6 Components: 0 H: 110.682 1 O: 55.3416 - 2 Charge: -3.51016e-15 + 2 Charge: -3.50659e-15 3 Ca: 1.49424e-10 4 Cl: 0.00119643 5 K: 0.000570961 @@ -2656,7 +2656,7 @@ Cell number 8 Components: 0 H: 110.682 1 O: 55.3416 - 2 Charge: 7.22344e-13 + 2 Charge: 7.22343e-13 3 Ca: 1.77958e-23 4 Cl: 0.00119643 5 K: 0.000198915 @@ -2676,7 +2676,7 @@ Cell number 9 Components: 0 H: 110.682 1 O: 55.3416 - 2 Charge: -7.77362e-17 + 2 Charge: -7.87692e-17 3 Ca: 0 4 Cl: 0.00119643 5 K: 0.000196389 @@ -2696,7 +2696,7 @@ Cell number 10 Components: 0 H: 110.679 1 O: 55.3438 - 2 Charge: -3.39513e-16 + 2 Charge: -3.39988e-16 3 Ca: 0 4 Cl: 0 5 K: 0.000196302 @@ -2716,7 +2716,7 @@ Cell number 11 Components: 0 H: 110.679 1 O: 55.3438 - 2 Charge: -3.39513e-16 + 2 Charge: -3.39988e-16 3 Ca: 0 4 Cl: 0 5 K: 0.000196302 @@ -2736,7 +2736,7 @@ Cell number 12 Components: 0 H: 110.679 1 O: 55.3438 - 2 Charge: -3.39513e-16 + 2 Charge: -3.39988e-16 3 Ca: 0 4 Cl: 0 5 K: 0.000196302 @@ -2756,7 +2756,7 @@ Cell number 13 Components: 0 H: 110.679 1 O: 55.3438 - 2 Charge: -3.39513e-16 + 2 Charge: -3.39988e-16 3 Ca: 0 4 Cl: 0 5 K: 0.000196302 @@ -2776,7 +2776,7 @@ Cell number 14 Components: 0 H: 110.679 1 O: 55.3438 - 2 Charge: -3.39513e-16 + 2 Charge: -3.39988e-16 3 Ca: 0 4 Cl: 0 5 K: 0.000196302 @@ -2796,7 +2796,7 @@ Cell number 15 Components: 0 H: 110.679 1 O: 55.3438 - 2 Charge: -3.39513e-16 + 2 Charge: -3.39988e-16 3 Ca: 0 4 Cl: 0 5 K: 0.000196302 @@ -2816,7 +2816,7 @@ Cell number 16 Components: 0 H: 110.679 1 O: 55.3438 - 2 Charge: -3.39513e-16 + 2 Charge: -3.39988e-16 3 Ca: 0 4 Cl: 0 5 K: 0.000196302 @@ -2836,7 +2836,7 @@ Cell number 17 Components: 0 H: 110.679 1 O: 55.3438 - 2 Charge: -3.39513e-16 + 2 Charge: -3.39988e-16 3 Ca: 0 4 Cl: 0 5 K: 0.000196302 @@ -2856,7 +2856,7 @@ Cell number 18 Components: 0 H: 110.679 1 O: 55.3438 - 2 Charge: -3.39513e-16 + 2 Charge: -3.39988e-16 3 Ca: 0 4 Cl: 0 5 K: 0.000196302 @@ -2876,7 +2876,7 @@ Cell number 19 Components: 0 H: 110.679 1 O: 55.3438 - 2 Charge: -3.39513e-16 + 2 Charge: -3.39988e-16 3 Ca: 0 4 Cl: 0 5 K: 0.000196302 @@ -2891,87 +2891,183 @@ Cell number 19 5 Pressure: 2 6 Hyd_K: 0 PhreeqcRM -BMI_GetCurrentTime: 864000 -BMI_GetEndTime: 950400 +BMI_GetEndTime: 3660 BMI_GetTimeUnits: seconds -BMI_GetTimeStep: 86400 +BMI_GetTimeStep: 60 BMI_SetValues variables: 0 Concentrations - Type: double + Type: double,2d Units: mol L-1 + Itemsize: 8 + NBytes: 2560 1 Density - Type: double + Type: double,1d Units: kg L-1 - 2 NthSelectedOutput - Type: int + Itemsize: 8 + NBytes: 320 + 2 FilePrefix + Type: character + Units: name + Itemsize: 13 + NBytes: 13 + 3 NthSelectedOutput + Type: integer Units: id - 3 Porosity - Type: double + Itemsize: 4 + NBytes: 4 + 4 Porosity + Type: double,1d Units: unitless - 4 Pressure - Type: double + Itemsize: 8 + NBytes: 320 + 5 Pressure + Type: double,1d Units: atm - 5 Saturation - Type: double + Itemsize: 8 + NBytes: 320 + 6 Saturation + Type: double,1d Units: unitless - 6 SelectedOutputOn - Type: int + Itemsize: 8 + NBytes: 320 + 7 SelectedOutputOn + Type: logical Units: flag - 7 Temperature - Type: double + Itemsize: 4 + NBytes: 4 + 8 Temperature + Type: double,1d Units: C - 8 Time + Itemsize: 8 + NBytes: 320 + 9 Time Type: double Units: s - 9 TimeStep + Itemsize: 8 + NBytes: 8 + 10 TimeStep Type: double Units: s + Itemsize: 8 + NBytes: 8 BMI_GetValues variables: 0 ComponentCount - Type: int + Type: integer Units: names + Itemsize: 4 + NBytes: 8 1 Components - Type: string + Type: character,1d Units: names + Itemsize: 6 + NBytes: 48 2 Concentrations - Type: double + Type: double,2d Units: mol L-1 + Itemsize: 8 + NBytes: 2560 3 CurrentSelectedOutputUserNumber - Type: int + Type: integer Units: id + Itemsize: 4 + NBytes: 4 4 Density - Type: double + Type: double,1d Units: kg L-1 + Itemsize: 8 + NBytes: 320 5 ErrorString - Type: string + Type: character Units: error - 6 Gfw - Type: double + Itemsize: 0 + NBytes: 0 + 6 FilePrefix + Type: character + Units: name + Itemsize: 13 + NBytes: 13 + 7 Gfw + Type: double,1d Units: g mol-1 - 7 GridCellCount - Type: int + Itemsize: 8 + NBytes: 64 + 8 GridCellCount + Type: integer Units: count - 8 Pressure - Type: double + Itemsize: 4 + NBytes: 4 + 9 InputVarNames + Type: character,1d + Units: string + Itemsize: 17 + NBytes: 187 + 10 OutputVarNames + Type: character,1d + Units: string + Itemsize: 31 + NBytes: 744 + 11 Porosity + Type: double,1d + Units: unitless + Itemsize: 8 + NBytes: 320 + 12 Pressure + Type: double,1d Units: atm - 9 Saturation - Type: double + Itemsize: 8 + NBytes: 320 + 13 Saturation + Type: double,1d Units: unitless - 10 SelectedOutput - Type: double + Itemsize: 8 + NBytes: 320 + 14 SelectedOutput + Type: double,2d Units: user - 11 SelectedOutputColumnCount - Type: int + Itemsize: 8 + NBytes: 2240 + 15 SelectedOutputColumnCount + Type: integer Units: count - 12 SelectedOutputCount - Type: int + Itemsize: 4 + NBytes: 4 + 16 SelectedOutputCount + Type: integer Units: count - 13 SelectedOutputHeadings - Type: string + Itemsize: 4 + NBytes: 4 + 17 SelectedOutputHeadings + Type: character,1d Units: names - 14 SelectedOutputRowCount - Type: int + Itemsize: 11 + NBytes: 77 + 18 SelectedOutputOn + Type: logical + Units: flag + Itemsize: 4 + NBytes: 4 + 19 SelectedOutputRowCount + Type: integer Units: count - 15 Temperature - Type: double + Itemsize: 4 + NBytes: 4 + 20 SolutionVolume + Type: double,1d + Units: L + Itemsize: 8 + NBytes: 320 + 21 Temperature + Type: double,1d Units: C + Itemsize: 8 + NBytes: 320 + 22 Time + Type: double + Units: s + Itemsize: 8 + NBytes: 8 + 23 TimeStep + Type: double + Units: s + Itemsize: 8 + NBytes: 8 diff --git a/Tests/Output/AdvectBMI_cpp.dmp b/Tests/Output/AdvectBMI_cpp.dmp index 7df85b548..e57d0c089 100644 --- a/Tests/Output/AdvectBMI_cpp.dmp +++ b/Tests/Output/AdvectBMI_cpp.dmp @@ -1,176 +1,176 @@ SOLUTION_RAW 0 Solution after simulation 1. - -temp 20 - -pressure 2 + -temp 50 + -pressure 1.1 -potential 0 - -total_h 22.136415505852 - -total_o 11.068314447308 - -cb 1.075129655527e-18 + -total_h 22.136415505711 + -total_o 11.068314447237 + -cb 1.050774149571e-18 -density 0.99830524784931 -totals - Ca 0.0001196428982687 - Cl 0.00023928579659614 - K 5.8750816835178e-14 - Na 5.0285660774941e-20 - -pH 7.0787960497097 + Ca 0.00011964289826793 + Cl 0.00023928579659462 + K 5.8750816837893e-14 + Na 5.0285660777464e-20 + -pH 7.07879604971 -pe 13.969354457422 -mu 0.0018000850694612 -ah2o 0.99996484900903 - -mass_water 0.19940483056363 - -soln_vol 0.19975835757967 - -total_alkalinity -9.9261673506363e-23 + -mass_water 0.19940483056236 + -soln_vol 0.19975835757839 + -total_alkalinity 2.3078339090229e-20 -activities Ca -3.3018013654974 Cl -2.9412141501733 E -13.969354457422 - H(0) -45.224826771491 - K -12.551155967556 - Na -18.618448968462 - O(0) -3.5724441104573 + H(0) -45.224826771493 + K -12.551155967533 + Na -18.618448968438 + O(0) -3.5724441104545 -gammas SOLUTION_RAW 1 Solution after simulation 1. - -temp 20 - -pressure 2 + -temp 50 + -pressure 1.1 -potential 0 - -total_h 22.136415505852 - -total_o 11.068314447308 - -cb 8.4070997865194e-19 + -total_h 22.136415505711 + -total_o 11.068314447237 + -cb 7.4075678215349e-19 -density 0.9983052478494 -totals - Ca 0.00011964289180093 - Cl 0.00023928579659614 - K 1.2994194764655e-11 - Na 8.48195644157e-17 - -pH 7.078796049857 - -pe 13.969354457274 + Ca 0.00011964289180017 + Cl 0.00023928579659462 + K 1.2994194765224e-11 + Na 8.4819564419848e-17 + -pH 7.0787960498582 + -pe 13.969354457273 -mu 0.0018000850370259 -ah2o 0.99996484900848 - -mass_water 0.19940483056363 - -soln_vol 0.19975835757989 - -total_alkalinity -3.8966824296148e-20 + -mass_water 0.19940483056236 + -soln_vol 0.19975835757862 + -total_alkalinity 6.083086224715e-20 -activities Ca -3.3018013883042 Cl -2.9412141499986 - E -13.969354457274 - H(0) -45.22482677149 - K -10.206420504589 - Na -15.391397091764 - O(0) -3.5724441104603 + E -13.969354457273 + H(0) -45.224826771491 + K -10.206420504568 + Na -15.39139709174 + O(0) -3.5724441104576 -gammas SOLUTION_RAW 2 Solution after simulation 1. - -temp 20 - -pressure 2 + -temp 50 + -pressure 1.1 -potential 0 - -total_h 22.136415505852 - -total_o 11.068314447308 - -cb 8.9683583757489e-19 + -total_h 22.136415505711 + -total_o 11.068314447237 + -cb 1.087461264099e-18 -density 0.99830524786079 -totals - Ca 0.00011964204834122 - Cl 0.00023928579659614 - K 1.6998083051542e-09 - Na 1.0538874982917e-13 - -pH 7.0787960691285 - -pe 13.96935443791 + Ca 0.00011964204834046 + Cl 0.00023928579659462 + K 1.6998083052281e-09 + Na 1.0538874983484e-13 + -pH 7.0787960691273 + -pe 13.969354437912 -mu 0.0018000808071463 -ah2o 0.99996484893657 - -mass_water 0.19940483056363 - -soln_vol 0.19975835760982 - -total_alkalinity 3.3030976220468e-20 + -mass_water 0.19940483056236 + -soln_vol 0.19975835760855 + -total_alkalinity -5.8375790189092e-20 -activities Ca -3.3018043625499 Cl -2.9412141272248 - E -13.96935443791 - H(0) -45.224826771306 - K -8.0897699068241 - Na -12.297098854641 - O(0) -3.5724441108906 + E -13.969354437912 + H(0) -45.224826771308 + K -8.0897699068024 + Na -12.297098854615 + O(0) -3.5724441108878 -gammas SOLUTION_RAW 3 Solution after simulation 1. - -temp 20 - -pressure 2 + -temp 50 + -pressure 1.1 -potential 0 - -total_h 22.136415505852 - -total_o 11.068314447308 - -cb 5.876535917038e-18 + -total_h 22.136415505711 + -total_o 11.068314447237 + -cb 6.2993443240608e-18 -density 0.99830524888929 -totals - Ca 0.00011955337889516 - Cl 0.00023928579659614 - K 1.7891515852047e-07 - Na 1.2364729922871e-10 - -pH 7.0787980954878 - -pe 13.969352402078 + Ca 0.0001195533788944 + Cl 0.00023928579659462 + K 1.7891515852859e-07 + Na 1.2364729923646e-10 + -pH 7.0787980954847 + -pe 13.969352402081 -mu 0.0017996361373178 -ah2o 0.99996484137719 - -mass_water 0.19940483056363 - -soln_vol 0.1997583607882 - -total_alkalinity 2.012894389811e-19 + -mass_water 0.19940483056236 + -soln_vol 0.19975836078693 + -total_alkalinity -4.025060860683e-20 -activities Ca -3.3021171525641 Cl -2.9412117329418 - E -13.969352402078 - H(0) -45.224826752359 - K -6.0675203126446 - Na -9.2277061356486 - O(0) -3.5724441553503 + E -13.969352402081 + H(0) -45.224826752361 + K -6.0675203126222 + Na -9.2277061356187 + O(0) -3.5724441553476 -gammas SOLUTION_RAW 4 Solution after simulation 1. - -temp 20 - -pressure 2 + -temp 50 + -pressure 1.1 -potential 0 - -total_h 22.136415505852 - -total_o 11.068314447308 - -cb 2.7860479322657e-16 + -total_h 22.136415505711 + -total_o 11.068314447237 + -cb 2.7899452433526e-16 -density 0.99830534209357 -totals - Ca 0.00011133610379508 - Cl 0.00023928579659616 - K 1.6474256035745e-05 - Na 1.3933297053804e-07 - -pH 7.0789862884294 - -pe 13.969163331037 - -mu 0.0017584271924268 + Ca 0.00011133610379392 + Cl 0.00023928579659464 + K 1.6474256036527e-05 + Na 1.3933297054804e-07 + -pH 7.0789862884286 + -pe 13.969163331038 + -mu 0.0017584271924245 -ah2o 0.9999641408255 - -mass_water 0.19940483056391 - -soln_vol 0.19975865369868 - -total_alkalinity 1.1347594515247e-19 + -mass_water 0.19940483056264 + -soln_vol 0.19975865369741 + -total_alkalinity 4.8800347418178e-20 -activities - Ca -3.3321851919421 + Ca -3.3321851919438 Cl -2.9409884191375 - E -13.969163331037 - H(0) -45.224824996161 - K -4.1031374741382 - Na -6.1756188689826 - O(0) -3.5724482762599 + E -13.969163331038 + H(0) -45.224824996163 + K -4.1031374741148 + Na -6.1756188689487 + O(0) -3.5724482762571 -gammas SOLUTION_RAW 5 Solution after simulation 1. - -temp 20 - -pressure 2 + -temp 50 + -pressure 1.1 -potential 0 - -total_h 22.136415505852 - -total_o 11.068314447308 - -cb 9.1760637207138e-14 + -total_h 22.136415505711 + -total_o 11.068314447237 + -cb 9.1760133444219e-14 -density 0.99830599410147 -totals - Ca 2.1235996941319e-06 - Cl 0.00023928579659881 - K 0.00021202857277487 - Na 2.3010024527435e-05 - -pH 7.0815725817844 - -pe 13.966565367281 - -mu 0.0012107356299958 + Ca 2.1235996938492e-06 + Cl 0.00023928579659728 + K 0.00021202857277338 + Na 2.3010024527965e-05 + -pH 7.0815725817894 + -pe 13.966565367277 + -mu 0.0012107356299945 -ah2o 0.9999548300763 - -mass_water 0.19940483056784 - -soln_vol 0.19976232479367 - -total_alkalinity -8.5219455427663e-20 + -mass_water 0.19940483056657 + -soln_vol 0.1997623247924 + -total_alkalinity 3.0744979879616e-19 -activities - Ca -5.0390564336998 - Cl -2.9376960035395 - E -13.966565367281 - H(0) -45.22480165536 - K -2.9902450425097 - Na -3.9545342945889 - O(0) -3.572503045403 + Ca -5.0390564337549 + Cl -2.9376960035394 + E -13.966565367277 + H(0) -45.224801655362 + K -2.99024504251 + Na -3.9545342945762 + O(0) -3.5725030454002 -gammas EXCHANGE_RAW 0 Exchange assemblage after simulation 1. # EXCHANGE_MODIFY candidate identifiers # @@ -179,8 +179,8 @@ # EXCHANGE_MODIFY candidate identifiers # -totals Ca 0.00011000000007735 - K 5.5789786827676e-15 - Na 9.2458165879821e-22 + K 5.578978683061e-15 + Na 9.2458165885048e-22 X 0.00022000000016027 -charge_balance 0 -la 1.2218455551817 @@ -199,8 +199,8 @@ # EXCHANGE_MODIFY candidate identifiers # -totals Ca 0.00010999999941902 - K 1.2339290111171e-12 - Na 1.5595423074247e-18 + K 1.233929011179e-12 + Na 1.5595423075109e-18 X 0.00022000000007198 -charge_balance 0 -la 1.2218455657082 @@ -219,8 +219,8 @@ # EXCHANGE_MODIFY candidate identifiers # -totals Ca 0.00010999991932863 - K 1.6141434300872e-10 - Na 1.9377455512095e-15 + K 1.6141434301678e-10 + Na 1.9377455513261e-15 X 0.00022000000007354 -charge_balance 0 -la 1.2218469384705 @@ -239,8 +239,8 @@ # EXCHANGE_MODIFY candidate identifiers # -totals Ca 0.00010999150115391 - K 1.6995489880192e-08 - Na 2.2742149190083e-12 + K 1.6995489881071e-08 + Na 2.2742149191652e-12 X 0.00022000000007192 -charge_balance 0 -la 1.2219913122299 @@ -258,12 +258,12 @@ -component X # EXCHANGE_MODIFY candidate identifiers # -totals - Ca 0.00010919081226408 - K 1.6157299306806e-06 - Na 2.6459228051296e-09 + Ca 0.00010919081226404 + K 1.6157299307705e-06 + Na 2.6459228053411e-09 X 0.00022000000038165 -charge_balance 0 - -la 1.2358677284194 + -la 1.2358677284202 -phase_proportion 0 -formula_z 0 # EXCHANGE_MODIFY candidates with new_def=true # @@ -278,12 +278,12 @@ -component X # EXCHANGE_MODIFY candidate identifiers # -totals - Ca 5.5298103954097e-05 - K 0.0001071522289845 - Na 2.2515631794498e-06 + Ca 5.5298103951778e-05 + K 0.00010715222898898 + Na 2.2515631796115e-06 X 0.00022000000007215 -charge_balance 0 - -la 1.9479117008937 + -la 1.9479117009121 -phase_proportion 0 -formula_z 0 # EXCHANGE_MODIFY candidates with new_def=true # @@ -293,174 +293,174 @@ # Exchange workspace variables # -totals SOLUTION_RAW 6 Solution after simulation 1. - -temp 20 - -pressure 2 + -temp 50 + -pressure 1.1 -potential 0 - -total_h 22.136415505852 - -total_o 11.068314447308 - -cb -7.0203244750827e-16 + -total_h 22.136415505711 + -total_o 11.068314447238 + -cb -7.0131871306237e-16 -density 0.99830319084416 -totals - Ca 2.9884729799544e-11 - Cl 0.00023928579659614 - K 0.00011419229852628 - Na 0.0001250934382997 - -pH 7.081624629655 - -pe 13.966513092484 + Ca 2.9884729795162e-11 + Cl 0.00023928579659462 + K 0.00011419229852425 + Na 0.0001250934383002 + -pH 7.0816246296562 + -pe 13.966513092483 -mu 0.001200086104411 -ah2o 0.99995464903458 - -mass_water 0.19940483056793 - -soln_vol 0.19976131924323 - -total_alkalinity -2.5397753527828e-20 + -mass_water 0.19940483056666 + -soln_vol 0.19976131924196 + -total_alkalinity 6.6511938694164e-20 -activities - Ca -9.8904037600017 + Ca -9.8904037600626 Cl -2.9376246522544 - E -13.966513092484 - H(0) -45.224801201506 - K -3.2589310415102 - Na -3.2191468857418 - O(0) -3.5725041103702 + E -13.966513092483 + H(0) -45.224801201507 + K -3.2589310415151 + Na -3.2191468857373 + O(0) -3.5725041103674 -gammas SOLUTION_RAW 7 Solution after simulation 1. - -temp 20 - -pressure 2 + -temp 50 + -pressure 1.1 -potential 0 - -total_h 22.136415505852 - -total_o 11.068314447308 - -cb 7.519447178337e-13 + -total_h 22.136415505711 + -total_o 11.068314447238 + -cb 7.519440964854e-13 -density 0.99830135805566 -totals - Ca 1.7725778408102e-17 - Cl 0.00023928579659619 - K 4.8038347521371e-05 - Na 0.00019124744982673 - -pH 7.0816246304016 - -pe 13.966513091736 + Ca 1.7725778405703e-17 + Cl 0.00023928579659467 + K 4.8038347520833e-05 + Na 0.00019124744982574 + -pH 7.0816246303982 + -pe 13.96651309174 -mu 0.0012000859564291 -ah2o 0.99995464903197 - -mass_water 0.19940483056793 - -soln_vol 0.19976061828731 - -total_alkalinity 8.9918833923699e-19 + -mass_water 0.19940483056666 + -soln_vol 0.19976061828604 + -total_alkalinity 6.2549743560035e-19 -activities - Ca -16.117247773866 + Ca -16.117247773922 Cl -2.9376246512605 - E -13.966513091736 - H(0) -45.224801201503 - K -3.6349797956543 - Na -3.0347857616045 - O(0) -3.5725041103778 + E -13.96651309174 + H(0) -45.224801201505 + K -3.6349797956564 + Na -3.034785761604 + O(0) -3.572504110375 -gammas SOLUTION_RAW 8 Solution after simulation 1. - -temp 20 - -pressure 2 + -temp 50 + -pressure 1.1 -potential 0 - -total_h 22.136415505852 - -total_o 11.068314447308 - -cb 1.4446884162311e-13 + -total_h 22.136415505711 + -total_o 11.068314447237 + -cb 1.4446859131826e-13 -density 0.99830112934291 -totals - Ca 3.5591651400101e-24 - Cl 0.0002392857965962 - K 3.9783056143054e-05 - Na 0.00019950274059762 - -pH 7.0816246303934 - -pe 13.966513091746 + Ca 3.559165139662e-24 + Cl 0.00023928579659468 + K 3.9783056142788e-05 + Na 0.00019950274059636 + -pH 7.0816246303915 + -pe 13.966513091748 -mu 0.0012000859549058 -ah2o 0.99995464903202 - -mass_water 0.19940483056793 - -soln_vol 0.19976053081559 - -total_alkalinity 2.0394965183107e-19 + -mass_water 0.19940483056666 + -soln_vol 0.19976053081432 + -total_alkalinity 5.553690632681e-20 -activities - Ca -22.814504950571 + Ca -22.814504950611 Cl -2.9376246512502 - E -13.966513091746 - H(0) -45.224801201507 - K -3.7168697126013 + E -13.966513091748 + H(0) -45.224801201508 + K -3.7168697126014 Na -3.0164325483659 - O(0) -3.5725041103707 + O(0) -3.5725041103679 -gammas SOLUTION_RAW 9 Solution after simulation 1. - -temp 20 - -pressure 2 + -temp 50 + -pressure 1.1 -potential 0 -total_h 22.136415505852 -total_o 11.068314447393 - -cb -1.5547240116016e-17 + -cb -1.5753846671975e-17 -density 0.99830111534334 -totals Cl 0.00023928579659624 K 3.9277732064696e-05 Na 0.00020000806453153 - -pH 7.0816246303892 - -pe 13.966513177943 + -pH 7.0816246303917 + -pe 13.96651317794 -mu 0.0012000859545433 -ah2o 0.99995464902842 -mass_water 0.19940483056793 -soln_vol 0.19976052546253 - -total_alkalinity -1.9751087794296e-19 + -total_alkalinity -1.1415092453232e-21 -activities Cl -2.9376246512477 - E -13.966513177943 + E -13.96651317794 H(0) -45.224801382473 K -3.722421452022 Na -3.0153339071739 O(0) -3.5725037484386 -gammas SOLUTION_RAW 10 Solution after simulation 1. - -temp 20 - -pressure 2 + -temp 50 + -pressure 1.1 -potential 0 -total_h 22.135866361697 -total_o 11.068757726907 - -cb -6.7902654296992e-17 + -cb -6.7997561691754e-17 -density 0.99831968732863 -totals K 3.9260409219821e-05 N 0.00023927986057314 Na 0.00020001945135325 - -pH 7.0816246305178 - -pe 13.966528092736 + -pH 7.0816246305188 + -pe 13.966528092735 -mu 0.0012000859545714 -ah2o 0.99995464840361 -mass_water 0.19939988387738 -soln_vol 0.19975821827742 - -total_alkalinity -7.5900107774396e-19 + -total_alkalinity -6.7760981419119e-19 -activities - E -13.966528092736 + E -13.966528092735 H(0) -45.224831203736 K -3.7226022594356 N(-3) -64.071413252819 - N(0) -19.539412420617 + N(0) -19.539412420616 N(3) -15.917214058761 N(5) -2.9377614291833 Na -3.0152984089092 O(0) -3.5724441064573 -gammas SOLUTION_RAW 11 Solution after simulation 1. - -temp 20 - -pressure 2 + -temp 50 + -pressure 1.1 -potential 0 -total_h 22.135866361697 -total_o 11.068757726907 - -cb -6.7902654296992e-17 + -cb -6.7997561691754e-17 -density 0.99831968732863 -totals K 3.9260409219821e-05 N 0.00023927986057314 Na 0.00020001945135325 - -pH 7.0816246305178 - -pe 13.966528092736 + -pH 7.0816246305188 + -pe 13.966528092735 -mu 0.0012000859545714 -ah2o 0.99995464840361 -mass_water 0.19939988387738 -soln_vol 0.19975821827742 - -total_alkalinity -7.5900107774396e-19 + -total_alkalinity -6.7760981419119e-19 -activities - E -13.966528092736 + E -13.966528092735 H(0) -45.224831203736 K -3.7226022594356 N(-3) -64.071413252819 - N(0) -19.539412420617 + N(0) -19.539412420616 N(3) -15.917214058761 N(5) -2.9377614291833 Na -3.0152984089092 @@ -472,12 +472,12 @@ -component X # EXCHANGE_MODIFY candidate identifiers # -totals - Ca 7.6966419082244e-09 - K 0.00018148921301107 - Na 3.8495393844372e-05 + Ca 7.6966419072614e-09 + K 0.00018148921301038 + Na 3.8495393845064e-05 X 0.00022000000013926 -charge_balance 0 - -la 2.4455188861289 + -la 2.4455188861322 -phase_proportion 0 -formula_z 0 # EXCHANGE_MODIFY candidates with new_def=true # @@ -492,12 +492,12 @@ -component X # EXCHANGE_MODIFY candidate identifiers # -totals - Ca 1.2087506838853e-14 - K 0.00012423437998023 - Na 9.5765620067804e-05 + Ca 1.2087506837347e-14 + K 0.00012423437997991 + Na 9.5765620068131e-05 X 0.00022000000007221 -charge_balance 0 - -la 2.6569586208595 + -la 2.6569586208605 -phase_proportion 0 -formula_z 0 # EXCHANGE_MODIFY candidates with new_def=true # @@ -512,9 +512,9 @@ -component X # EXCHANGE_MODIFY candidate identifiers # -totals - Ca 2.8566435936872e-21 - K 0.00011161951512661 - Na 0.0001083804849455 + Ca 2.8566435934267e-21 + K 0.00011161951512659 + Na 0.00010838048494552 X 0.00022000000007212 -charge_balance 0 -la 2.6923468725498 @@ -551,9 +551,9 @@ -component X # EXCHANGE_MODIFY candidate identifiers # -totals - H 1.556973507194e-64 + H 1.5569735071866e-64 K 0.00011075000841372 - N 3.892433767985e-65 + N 3.8924337679664e-65 Na 0.0001092499916584 X 0.00022000000007212 -charge_balance 0 @@ -572,9 +572,9 @@ -component X # EXCHANGE_MODIFY candidate identifiers # -totals - H 1.556973507194e-64 + H 1.5569735071866e-64 K 0.00011075000841372 - N 3.892433767985e-65 + N 3.8924337679664e-65 Na 0.0001092499916584 X 0.00022000000007212 -charge_balance 0 @@ -588,240 +588,240 @@ # Exchange workspace variables # -totals SOLUTION_RAW 12 Solution after simulation 1. - -temp 20 - -pressure 2 + -temp 50 + -pressure 1.1 -potential 0 -total_h 22.135866361697 -total_o 11.068757726907 - -cb -6.7902654296992e-17 + -cb -6.7997561691754e-17 -density 0.99831968732863 -totals K 3.9260409219821e-05 N 0.00023927986057314 Na 0.00020001945135325 - -pH 7.0816246305178 - -pe 13.966528092736 + -pH 7.0816246305188 + -pe 13.966528092735 -mu 0.0012000859545714 -ah2o 0.99995464840361 -mass_water 0.19939988387738 -soln_vol 0.19975821827742 - -total_alkalinity -7.5900107774396e-19 + -total_alkalinity -6.7760981419119e-19 -activities - E -13.966528092736 + E -13.966528092735 H(0) -45.224831203736 K -3.7226022594356 N(-3) -64.071413252819 - N(0) -19.539412420617 + N(0) -19.539412420616 N(3) -15.917214058761 N(5) -2.9377614291833 Na -3.0152984089092 O(0) -3.5724441064573 -gammas SOLUTION_RAW 13 Solution after simulation 1. - -temp 20 - -pressure 2 + -temp 50 + -pressure 1.1 -potential 0 -total_h 22.135866361697 -total_o 11.068757726907 - -cb -6.7902654296992e-17 + -cb -6.7997561691754e-17 -density 0.99831968732863 -totals K 3.9260409219821e-05 N 0.00023927986057314 Na 0.00020001945135325 - -pH 7.0816246305178 - -pe 13.966528092736 + -pH 7.0816246305188 + -pe 13.966528092735 -mu 0.0012000859545714 -ah2o 0.99995464840361 -mass_water 0.19939988387738 -soln_vol 0.19975821827742 - -total_alkalinity -7.5900107774396e-19 + -total_alkalinity -6.7760981419119e-19 -activities - E -13.966528092736 + E -13.966528092735 H(0) -45.224831203736 K -3.7226022594356 N(-3) -64.071413252819 - N(0) -19.539412420617 + N(0) -19.539412420616 N(3) -15.917214058761 N(5) -2.9377614291833 Na -3.0152984089092 O(0) -3.5724441064573 -gammas SOLUTION_RAW 14 Solution after simulation 1. - -temp 20 - -pressure 2 + -temp 50 + -pressure 1.1 -potential 0 -total_h 22.135866361697 -total_o 11.068757726907 - -cb -6.7902654296992e-17 + -cb -6.7997561691754e-17 -density 0.99831968732863 -totals K 3.9260409219821e-05 N 0.00023927986057314 Na 0.00020001945135325 - -pH 7.0816246305178 - -pe 13.966528092736 + -pH 7.0816246305188 + -pe 13.966528092735 -mu 0.0012000859545714 -ah2o 0.99995464840361 -mass_water 0.19939988387738 -soln_vol 0.19975821827742 - -total_alkalinity -7.5900107774396e-19 + -total_alkalinity -6.7760981419119e-19 -activities - E -13.966528092736 + E -13.966528092735 H(0) -45.224831203736 K -3.7226022594356 N(-3) -64.071413252819 - N(0) -19.539412420617 + N(0) -19.539412420616 N(3) -15.917214058761 N(5) -2.9377614291833 Na -3.0152984089092 O(0) -3.5724441064573 -gammas SOLUTION_RAW 15 Solution after simulation 1. - -temp 20 - -pressure 2 + -temp 50 + -pressure 1.1 -potential 0 -total_h 22.135866361697 -total_o 11.068757726907 - -cb -6.7902654296992e-17 + -cb -6.7997561691754e-17 -density 0.99831968732863 -totals K 3.9260409219821e-05 N 0.00023927986057314 Na 0.00020001945135325 - -pH 7.0816246305178 - -pe 13.966528092736 + -pH 7.0816246305188 + -pe 13.966528092735 -mu 0.0012000859545714 -ah2o 0.99995464840361 -mass_water 0.19939988387738 -soln_vol 0.19975821827742 - -total_alkalinity -7.5900107774396e-19 + -total_alkalinity -6.7760981419119e-19 -activities - E -13.966528092736 + E -13.966528092735 H(0) -45.224831203736 K -3.7226022594356 N(-3) -64.071413252819 - N(0) -19.539412420617 + N(0) -19.539412420616 N(3) -15.917214058761 N(5) -2.9377614291833 Na -3.0152984089092 O(0) -3.5724441064573 -gammas SOLUTION_RAW 16 Solution after simulation 1. - -temp 20 - -pressure 2 + -temp 50 + -pressure 1.1 -potential 0 -total_h 22.135866361697 -total_o 11.068757726907 - -cb -6.7902654296992e-17 + -cb -6.7997561691754e-17 -density 0.99831968732863 -totals K 3.9260409219821e-05 N 0.00023927986057314 Na 0.00020001945135325 - -pH 7.0816246305178 - -pe 13.966528092736 + -pH 7.0816246305188 + -pe 13.966528092735 -mu 0.0012000859545714 -ah2o 0.99995464840361 -mass_water 0.19939988387738 -soln_vol 0.19975821827742 - -total_alkalinity -7.5900107774396e-19 + -total_alkalinity -6.7760981419119e-19 -activities - E -13.966528092736 + E -13.966528092735 H(0) -45.224831203736 K -3.7226022594356 N(-3) -64.071413252819 - N(0) -19.539412420617 + N(0) -19.539412420616 N(3) -15.917214058761 N(5) -2.9377614291833 Na -3.0152984089092 O(0) -3.5724441064573 -gammas SOLUTION_RAW 17 Solution after simulation 1. - -temp 20 - -pressure 2 + -temp 50 + -pressure 1.1 -potential 0 -total_h 22.135866361697 -total_o 11.068757726907 - -cb -6.7902654296992e-17 + -cb -6.7997561691754e-17 -density 0.99831968732863 -totals K 3.9260409219821e-05 N 0.00023927986057314 Na 0.00020001945135325 - -pH 7.0816246305178 - -pe 13.966528092736 + -pH 7.0816246305188 + -pe 13.966528092735 -mu 0.0012000859545714 -ah2o 0.99995464840361 -mass_water 0.19939988387738 -soln_vol 0.19975821827742 - -total_alkalinity -7.5900107774396e-19 + -total_alkalinity -6.7760981419119e-19 -activities - E -13.966528092736 + E -13.966528092735 H(0) -45.224831203736 K -3.7226022594356 N(-3) -64.071413252819 - N(0) -19.539412420617 + N(0) -19.539412420616 N(3) -15.917214058761 N(5) -2.9377614291833 Na -3.0152984089092 O(0) -3.5724441064573 -gammas SOLUTION_RAW 18 Solution after simulation 1. - -temp 20 - -pressure 2 + -temp 50 + -pressure 1.1 -potential 0 -total_h 22.135866361697 -total_o 11.068757726907 - -cb -6.7902654296992e-17 + -cb -6.7997561691754e-17 -density 0.99831968732863 -totals K 3.9260409219821e-05 N 0.00023927986057314 Na 0.00020001945135325 - -pH 7.0816246305178 - -pe 13.966528092736 + -pH 7.0816246305188 + -pe 13.966528092735 -mu 0.0012000859545714 -ah2o 0.99995464840361 -mass_water 0.19939988387738 -soln_vol 0.19975821827742 - -total_alkalinity -7.5900107774396e-19 + -total_alkalinity -6.7760981419119e-19 -activities - E -13.966528092736 + E -13.966528092735 H(0) -45.224831203736 K -3.7226022594356 N(-3) -64.071413252819 - N(0) -19.539412420617 + N(0) -19.539412420616 N(3) -15.917214058761 N(5) -2.9377614291833 Na -3.0152984089092 O(0) -3.5724441064573 -gammas SOLUTION_RAW 19 Solution after simulation 1. - -temp 20 - -pressure 2 + -temp 50 + -pressure 1.1 -potential 0 -total_h 22.135866361697 -total_o 11.068757726907 - -cb -6.7902654296992e-17 + -cb -6.7997561691754e-17 -density 0.99831968732863 -totals K 3.9260409219821e-05 N 0.00023927986057314 Na 0.00020001945135325 - -pH 7.0816246305178 - -pe 13.966528092736 + -pH 7.0816246305188 + -pe 13.966528092735 -mu 0.0012000859545714 -ah2o 0.99995464840361 -mass_water 0.19939988387738 -soln_vol 0.19975821827742 - -total_alkalinity -7.5900107774396e-19 + -total_alkalinity -6.7760981419119e-19 -activities - E -13.966528092736 + E -13.966528092735 H(0) -45.224831203736 K -3.7226022594356 N(-3) -64.071413252819 - N(0) -19.539412420617 + N(0) -19.539412420616 N(3) -15.917214058761 N(5) -2.9377614291833 Na -3.0152984089092 @@ -833,9 +833,9 @@ -component X # EXCHANGE_MODIFY candidate identifiers # -totals - H 1.556973507194e-64 + H 1.5569735071866e-64 K 0.00011075000841372 - N 3.892433767985e-65 + N 3.8924337679664e-65 Na 0.0001092499916584 X 0.00022000000007212 -charge_balance 0 @@ -854,9 +854,9 @@ -component X # EXCHANGE_MODIFY candidate identifiers # -totals - H 1.556973507194e-64 + H 1.5569735071866e-64 K 0.00011075000841372 - N 3.892433767985e-65 + N 3.8924337679664e-65 Na 0.0001092499916584 X 0.00022000000007212 -charge_balance 0 @@ -875,9 +875,9 @@ -component X # EXCHANGE_MODIFY candidate identifiers # -totals - H 1.556973507194e-64 + H 1.5569735071866e-64 K 0.00011075000841372 - N 3.892433767985e-65 + N 3.8924337679664e-65 Na 0.0001092499916584 X 0.00022000000007212 -charge_balance 0 @@ -896,9 +896,9 @@ -component X # EXCHANGE_MODIFY candidate identifiers # -totals - H 1.556973507194e-64 + H 1.5569735071866e-64 K 0.00011075000841372 - N 3.892433767985e-65 + N 3.8924337679664e-65 Na 0.0001092499916584 X 0.00022000000007212 -charge_balance 0 @@ -917,9 +917,9 @@ -component X # EXCHANGE_MODIFY candidate identifiers # -totals - H 1.556973507194e-64 + H 1.5569735071866e-64 K 0.00011075000841372 - N 3.892433767985e-65 + N 3.8924337679664e-65 Na 0.0001092499916584 X 0.00022000000007212 -charge_balance 0 @@ -938,9 +938,9 @@ -component X # EXCHANGE_MODIFY candidate identifiers # -totals - H 1.556973507194e-64 + H 1.5569735071866e-64 K 0.00011075000841372 - N 3.892433767985e-65 + N 3.8924337679664e-65 Na 0.0001092499916584 X 0.00022000000007212 -charge_balance 0 @@ -959,9 +959,9 @@ -component X # EXCHANGE_MODIFY candidate identifiers # -totals - H 1.556973507194e-64 + H 1.5569735071866e-64 K 0.00011075000841372 - N 3.892433767985e-65 + N 3.8924337679664e-65 Na 0.0001092499916584 X 0.00022000000007212 -charge_balance 0 @@ -980,9 +980,9 @@ -component X # EXCHANGE_MODIFY candidate identifiers # -totals - H 1.556973507194e-64 + H 1.5569735071866e-64 K 0.00011075000841372 - N 3.892433767985e-65 + N 3.8924337679664e-65 Na 0.0001092499916584 X 0.00022000000007212 -charge_balance 0 diff --git a/Tests/Output/AdvectBMI_cpp.yaml b/Tests/Output/AdvectBMI_cpp.yaml index 007c51277..dd6ceef51 100644 --- a/Tests/Output/AdvectBMI_cpp.yaml +++ b/Tests/Output/AdvectBMI_cpp.yaml @@ -1,3 +1,4 @@ +SetGridCellCount: 40 SetErrorHandlerMode: 1 SetComponentH2O: false SetRebalanceFraction: 0.5 @@ -55,6 +56,47 @@ SetRepresentativeVolume: - 1 - 1 - 1 +SetDensity: + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 SetPorosity: - 0.20000000000000001 - 0.20000000000000001 diff --git a/Tests/Output/AdvectBMI_cpp_utility.txt b/Tests/Output/AdvectBMI_cpp_utility.txt index 19339b85c..ccae08255 100644 --- a/Tests/Output/AdvectBMI_cpp_utility.txt +++ b/Tests/Output/AdvectBMI_cpp_utility.txt @@ -37,10 +37,10 @@ Using solution 1. Activity of water = 1.000 Ionic strength (mol/kgw) = 1.500e-03 Mass of water (kg) = 9.970e-01 - Total alkalinity (eq/kg) = -7.786e-19 + Total alkalinity (eq/kg) = -1.657e-19 Temperature (°C) = 15.00 Pressure (atm) = 3.00 - Electrical balance (eq) = -3.611e-17 + Electrical balance (eq) = -3.675e-17 Percent error, 100*(Cat-|An|)/(Cat+|An|) = -0.00 Iterations = 12 Total H = 1.106821e+02 @@ -91,6 +91,6 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 4.221 Seconds. +End of Run after 0.546 Seconds. ------------------------------- diff --git a/Tests/Output/AdvectBMI_f90.chem.txt b/Tests/Output/AdvectBMI_f90.chem.txt new file mode 100644 index 000000000..962572e2e --- /dev/null +++ b/Tests/Output/AdvectBMI_f90.chem.txt @@ -0,0 +1,2481 @@ +------------------------------------ +Reading input data for simulation 1. +------------------------------------ + + TITLE Example 11.--Transport and cation exchange. + SOLUTION 0 CaCl2 + units mmol/kgw + temp 25.0 + pH 7.0 charge + pe 12.5 O2(g) -0.68 + Ca 0.6 + Cl 1.2 + SOLUTION 1-40 Initial solution for column + units mmol/kgw + temp 25.0 + pH 7.0 charge + pe 12.5 O2(g) -0.68 + Na 1.0 + K 0.2 + N(5) 1.2 + END +----- +TITLE +----- + + Example 11.--Transport and cation exchange. + +------------------------------------------- +Beginning of initial solution calculations. +------------------------------------------- + +Initial solution 0. CaCl2 + +-----------------------------Solution composition------------------------------ + + Elements Molality Moles + + Ca 6.000e-04 6.000e-04 + Cl 1.200e-03 1.200e-03 + +----------------------------Description of solution---------------------------- + + pH = 6.995 Charge balance + pe = 13.632 Equilibrium with O2(g) + Specific Conductance (µS/cm, 25°C) = 155 + Density (g/cm³) = 0.99710 + Volume (L) = 1.00298 + Activity of water = 1.000 + Ionic strength (mol/kgw) = 1.800e-03 + Mass of water (kg) = 1.000e+00 + Total alkalinity (eq/kg) = 6.950e-20 + Temperature (°C) = 25.00 + Electrical balance (eq) = 4.519e-18 + Percent error, 100*(Cat-|An|)/(Cat+|An|) = 0.00 + Iterations = 4 + Total H = 1.110124e+02 + Total O = 5.550675e+01 + +----------------------------Distribution of species---------------------------- + + Log Log Log mole V + Species Molality Activity Molality Activity Gamma cm³/mol + + H+ 1.058e-07 1.012e-07 -6.976 -6.995 -0.019 0.00 + OH- 1.049e-07 1.000e-07 -6.979 -7.000 -0.021 -4.10 + H2O 5.551e+01 1.000e+00 1.744 -0.000 0.000 18.07 +Ca 6.000e-04 + Ca+2 6.000e-04 4.983e-04 -3.222 -3.302 -0.081 -18.10 + CaOH+ 8.569e-10 8.174e-10 -9.067 -9.088 -0.020 (0) +Cl 1.200e-03 + Cl- 1.200e-03 1.144e-03 -2.921 -2.941 -0.021 18.08 +H(0) 0.000e+00 + H2 0.000e+00 0.000e+00 -44.404 -44.404 0.000 28.61 +O(0) 5.351e-04 + O2 2.675e-04 2.676e-04 -3.573 -3.572 0.000 30.40 + +------------------------------Saturation indices------------------------------- + + Phase SI** log IAP log K(298 K, 1 atm) + + H2(g) -41.30 -44.40 -3.10 H2 + H2O(g) -1.50 -0.00 1.50 H2O + O2(g) -0.68 -3.57 -2.89 O2 Pressure 0.2 atm, phi 1.000 + +**For a gas, SI = log10(fugacity). Fugacity = pressure * phi / 1 atm. + For ideal gases, phi = 1. + +Initial solution 1. Initial solution for column + +-----------------------------Solution composition------------------------------ + + Elements Molality Moles + + K 2.000e-04 2.000e-04 + N(5) 1.200e-03 1.200e-03 + Na 1.000e-03 1.000e-03 + +----------------------------Description of solution---------------------------- + + pH = 6.997 Charge balance + pe = 13.630 Equilibrium with O2(g) + Specific Conductance (µS/cm, 25°C) = 146 + Density (g/cm³) = 0.99711 + Volume (L) = 1.00301 + Activity of water = 1.000 + Ionic strength (mol/kgw) = 1.200e-03 + Mass of water (kg) = 1.000e+00 + Total alkalinity (eq/kg) = -9.247e-19 + Temperature (°C) = 25.00 + Electrical balance (eq) = -9.243e-17 + Percent error, 100*(Cat-|An|)/(Cat+|An|) = -0.00 + Iterations = 3 (7 overall) + Total H = 1.110124e+02 + Total O = 5.551035e+01 + +----------------------------Distribution of species---------------------------- + + Log Log Log mole V + Species Molality Activity Molality Activity Gamma cm³/mol + + H+ 1.045e-07 1.007e-07 -6.981 -6.997 -0.016 0.00 + OH- 1.045e-07 1.005e-07 -6.981 -6.998 -0.017 -4.10 + H2O 5.551e+01 1.000e+00 1.744 -0.000 0.000 18.07 +H(0) 0.000e+00 + H2 0.000e+00 0.000e+00 -44.404 -44.404 0.000 28.61 +K 2.000e-04 + K+ 2.000e-04 1.923e-04 -3.699 -3.716 -0.017 9.01 +N(5) 1.200e-03 + NO3- 1.200e-03 1.154e-03 -2.921 -2.938 -0.017 29.49 +Na 1.000e-03 + Na+ 1.000e-03 9.621e-04 -3.000 -3.017 -0.017 -1.47 + NaOH 9.666e-21 9.668e-21 -20.015 -20.015 0.000 (0) +O(0) 5.351e-04 + O2 2.676e-04 2.676e-04 -3.573 -3.572 0.000 30.40 + +------------------------------Saturation indices------------------------------- + + Phase SI** log IAP log K(298 K, 1 atm) + + H2(g) -41.30 -44.40 -3.10 H2 + H2O(g) -1.50 -0.00 1.50 H2O + O2(g) -0.68 -3.57 -2.89 O2 Pressure 0.2 atm, phi 1.000 + +**For a gas, SI = log10(fugacity). Fugacity = pressure * phi / 1 atm. + For ideal gases, phi = 1. + +------------------ +End of simulation. +------------------ + +------------------------------------ +Reading input data for simulation 2. +------------------------------------ + + EXCHANGE 1-40 + equilibrate 1 + X 0.0011 + END +------------------------------------------------------- +Beginning of initial exchange-composition calculations. +------------------------------------------------------- + +Exchange 1. + +X 1.100e-03 mol + + Equiv- Equivalent Log + Species Moles alents Fraction Gamma + + KX 5.507e-04 5.507e-04 5.006e-01 -0.017 + NaX 5.493e-04 5.493e-04 4.994e-01 -0.017 + +------------------ +End of simulation. +------------------ + +------------------------------------ +Reading input data for simulation 3. +------------------------------------ + + SELECTED_OUTPUT + file advect.sel + reset false + totals Na Cl K Ca + USER_PUNCH + heading Temperature Pressure Hyd_K + 10 PUNCH TC, PRESSURE + 20 PUNCH CALLBACK(cell_no, 0, "HYDRAULIC_K") + END +------------------ +End of simulation. +------------------ + +------------------------------------ +Reading input data for simulation 4. +------------------------------------ + +------------------------------- +End of Run after 1.806 Seconds. +------------------------------- + +Number of threads: 3 +Number of MPI processes: 1 +MPI task number: 0 +File prefix: AdvectBMI_f90 +Number of grid cells in the user's model: 40 +Number of components for transport: 8 + H 1.0080 + O 16.0000 + Charge 1.0000 + Ca 40.0800 + Cl 35.4530 + K 39.1020 + N 14.0067 + Na 22.9898 + +Time: 10 +Chemistry cell: 0 +Grid cell(s) (0-based): 0 20 +------------------------------------ +Reading input data for simulation 1. +------------------------------------ + + RUN_CELLS + -start_time 777600 + -time_step 86400 + -cells 0 + END +-------------------------- +Beginning of run as cells. +-------------------------- + +----------------------------------------- +Beginning of batch-reaction calculations. +----------------------------------------- + +Reaction step 1. + +Using solution 0. Solution after simulation 1. +Using exchange 0. Exchange assemblage after simulation 1. + +-----------------------------Exchange composition------------------------------ + +X 2.200e-04 mol + + Equiv- Equivalent Log + Species Moles alents Fraction Gamma + + CaX2 1.100e-04 2.200e-04 1.000e+00 -0.080 + KX 5.579e-15 5.579e-15 2.536e-11 -0.020 + NaX 9.246e-22 9.246e-22 4.203e-18 -0.020 + +-----------------------------Solution composition------------------------------ + + Elements Molality Moles + + Ca 6.000e-04 1.196e-04 + Cl 1.200e-03 2.393e-04 + K 2.946e-13 5.875e-14 + Na 2.522e-19 5.029e-20 + +----------------------------Description of solution---------------------------- + + pH = 7.079 Charge balance + pe = 13.969 Adjusted to redox equilibrium + Specific Conductance (µS/cm, 20°C) = 138 + Density (g/cm³) = 0.99831 + Volume (L) = 0.19976 + Activity of water = 1.000 + Ionic strength (mol/kgw) = 1.800e-03 + Mass of water (kg) = 1.994e-01 + Total alkalinity (eq/kg) = 1.157e-19 + Temperature (°C) = 20.00 + Pressure (atm) = 2.00 + Electrical balance (eq) = 1.051e-18 + Percent error, 100*(Cat-|An|)/(Cat+|An|) = 0.00 + Iterations = 2 + Total H = 2.213642e+01 + Total O = 1.106831e+01 + +----------------------------Distribution of species---------------------------- + + Log Log Log mole V + Species Molality Activity Molality Activity Gamma cm³/mol + + H+ 8.715e-08 8.341e-08 -7.060 -7.079 -0.019 0.00 + OH- 8.611e-08 8.215e-08 -7.065 -7.085 -0.020 -4.31 + H2O 5.551e+01 1.000e+00 1.744 -0.000 0.000 18.05 +Ca 6.000e-04 + Ca+2 6.000e-04 4.991e-04 -3.222 -3.302 -0.080 -18.16 + CaOH+ 1.041e-09 9.931e-10 -8.983 -9.003 -0.020 (0) +Cl 1.200e-03 + Cl- 1.200e-03 1.145e-03 -2.921 -2.941 -0.020 17.92 +H(0) 0.000e+00 + H2 0.000e+00 0.000e+00 -45.225 -45.225 0.000 28.61 +K 2.946e-13 + K+ 2.946e-13 2.811e-13 -12.531 -12.551 -0.020 8.85 +Na 2.522e-19 + Na+ 2.522e-19 2.407e-19 -18.598 -18.618 -0.020 -1.74 + NaOH 1.976e-36 1.977e-36 -35.704 -35.704 0.000 (0) +O(0) 5.351e-04 + O2 2.675e-04 2.676e-04 -3.573 -3.572 0.000 29.98 + +------------------------------Saturation indices------------------------------- + + Phase SI** log IAP log K(293 K, 2 atm) + + H2(g) -42.14 -45.22 -3.09 H2 + H2O(g) -1.63 -0.00 1.63 H2O + Halite -23.13 -21.56 1.57 NaCl + O2(g) -0.72 -3.57 -2.85 O2 + Sylvite -16.37 -15.49 0.87 KCl + +**For a gas, SI = log10(fugacity). Fugacity = pressure * phi / 1 atm. + For ideal gases, phi = 1. + +------------------ +End of simulation. +------------------ + +------------------------------------ +Reading input data for simulation 2. +------------------------------------ + +------------------------------- +End of Run after 1.835 Seconds. +------------------------------- + +Time: 10 +Chemistry cell: 1 +Grid cell(s) (0-based): 1 21 +------------------------------------ +Reading input data for simulation 1. +------------------------------------ + + RUN_CELLS + -start_time 777600 + -time_step 86400 + -cells 1 + END +-------------------------- +Beginning of run as cells. +-------------------------- + +----------------------------------------- +Beginning of batch-reaction calculations. +----------------------------------------- + +Reaction step 1. + +Using solution 1. Solution after simulation 1. +Using exchange 1. Exchange assemblage after simulation 1. + +-----------------------------Exchange composition------------------------------ + +X 2.200e-04 mol + + Equiv- Equivalent Log + Species Moles alents Fraction Gamma + + CaX2 1.100e-04 2.200e-04 1.000e+00 -0.080 + KX 1.234e-12 1.234e-12 5.609e-09 -0.020 + NaX 1.560e-18 1.560e-18 7.089e-15 -0.020 + +-----------------------------Solution composition------------------------------ + + Elements Molality Moles + + Ca 6.000e-04 1.196e-04 + Cl 1.200e-03 2.393e-04 + K 6.516e-11 1.299e-11 + Na 4.254e-16 8.482e-17 + +----------------------------Description of solution---------------------------- + + pH = 7.079 Charge balance + pe = 13.969 Adjusted to redox equilibrium + Specific Conductance (µS/cm, 20°C) = 138 + Density (g/cm³) = 0.99831 + Volume (L) = 0.19976 + Activity of water = 1.000 + Ionic strength (mol/kgw) = 1.800e-03 + Mass of water (kg) = 1.994e-01 + Total alkalinity (eq/kg) = 3.051e-19 + Temperature (°C) = 20.00 + Pressure (atm) = 2.00 + Electrical balance (eq) = 7.408e-19 + Percent error, 100*(Cat-|An|)/(Cat+|An|) = 0.00 + Iterations = 5 + Total H = 2.213642e+01 + Total O = 1.106831e+01 + +----------------------------Distribution of species---------------------------- + + Log Log Log mole V + Species Molality Activity Molality Activity Gamma cm³/mol + + H+ 8.715e-08 8.341e-08 -7.060 -7.079 -0.019 0.00 + OH- 8.611e-08 8.215e-08 -7.065 -7.085 -0.020 -4.31 + H2O 5.551e+01 1.000e+00 1.744 -0.000 0.000 18.05 +Ca 6.000e-04 + Ca+2 6.000e-04 4.991e-04 -3.222 -3.302 -0.080 -18.16 + CaOH+ 1.041e-09 9.931e-10 -8.983 -9.003 -0.020 (0) +Cl 1.200e-03 + Cl- 1.200e-03 1.145e-03 -2.921 -2.941 -0.020 17.92 +H(0) 0.000e+00 + H2 0.000e+00 0.000e+00 -45.225 -45.225 0.000 28.61 +K 6.516e-11 + K+ 6.516e-11 6.217e-11 -10.186 -10.206 -0.020 8.85 +Na 4.254e-16 + Na+ 4.254e-16 4.061e-16 -15.371 -15.391 -0.020 -1.74 + NaOH 3.334e-33 3.335e-33 -32.477 -32.477 0.000 (0) +O(0) 5.351e-04 + O2 2.675e-04 2.676e-04 -3.573 -3.572 0.000 29.98 + +------------------------------Saturation indices------------------------------- + + Phase SI** log IAP log K(293 K, 2 atm) + + H2(g) -42.14 -45.22 -3.09 H2 + H2O(g) -1.63 -0.00 1.63 H2O + Halite -19.90 -18.33 1.57 NaCl + O2(g) -0.72 -3.57 -2.85 O2 + Sylvite -14.02 -13.15 0.87 KCl + +**For a gas, SI = log10(fugacity). Fugacity = pressure * phi / 1 atm. + For ideal gases, phi = 1. + +------------------ +End of simulation. +------------------ + +------------------------------------ +Reading input data for simulation 2. +------------------------------------ + +------------------------------- +End of Run after 1.835 Seconds. +------------------------------- + +Time: 10 +Chemistry cell: 2 +Grid cell(s) (0-based): 2 22 +------------------------------------ +Reading input data for simulation 1. +------------------------------------ + + RUN_CELLS + -start_time 777600 + -time_step 86400 + -cells 2 + END +-------------------------- +Beginning of run as cells. +-------------------------- + +----------------------------------------- +Beginning of batch-reaction calculations. +----------------------------------------- + +Reaction step 1. + +Using solution 2. Solution after simulation 1. +Using exchange 2. Exchange assemblage after simulation 1. + +-----------------------------Exchange composition------------------------------ + +X 2.200e-04 mol + + Equiv- Equivalent Log + Species Moles alents Fraction Gamma + + CaX2 1.100e-04 2.200e-04 1.000e+00 -0.080 + KX 1.614e-10 1.614e-10 7.337e-07 -0.020 + NaX 1.938e-15 1.938e-15 8.808e-12 -0.020 + +-----------------------------Solution composition------------------------------ + + Elements Molality Moles + + Ca 6.000e-04 1.196e-04 + Cl 1.200e-03 2.393e-04 + K 8.524e-09 1.700e-09 + Na 5.285e-13 1.054e-13 + +----------------------------Description of solution---------------------------- + + pH = 7.079 Charge balance + pe = 13.969 Adjusted to redox equilibrium + Specific Conductance (µS/cm, 20°C) = 138 + Density (g/cm³) = 0.99831 + Volume (L) = 0.19976 + Activity of water = 1.000 + Ionic strength (mol/kgw) = 1.800e-03 + Mass of water (kg) = 1.994e-01 + Total alkalinity (eq/kg) = -2.928e-19 + Temperature (°C) = 20.00 + Pressure (atm) = 2.00 + Electrical balance (eq) = 1.087e-18 + Percent error, 100*(Cat-|An|)/(Cat+|An|) = 0.00 + Iterations = 6 + Total H = 2.213642e+01 + Total O = 1.106831e+01 + +----------------------------Distribution of species---------------------------- + + Log Log Log mole V + Species Molality Activity Molality Activity Gamma cm³/mol + + H+ 8.715e-08 8.341e-08 -7.060 -7.079 -0.019 0.00 + OH- 8.611e-08 8.215e-08 -7.065 -7.085 -0.020 -4.31 + H2O 5.551e+01 1.000e+00 1.744 -0.000 0.000 18.05 +Ca 6.000e-04 + Ca+2 6.000e-04 4.991e-04 -3.222 -3.302 -0.080 -18.16 + CaOH+ 1.041e-09 9.931e-10 -8.983 -9.003 -0.020 (0) +Cl 1.200e-03 + Cl- 1.200e-03 1.145e-03 -2.921 -2.941 -0.020 17.92 +H(0) 0.000e+00 + H2 0.000e+00 0.000e+00 -45.225 -45.225 0.000 28.61 +K 8.524e-09 + K+ 8.524e-09 8.133e-09 -8.069 -8.090 -0.020 8.85 +Na 5.285e-13 + Na+ 5.285e-13 5.045e-13 -12.277 -12.297 -0.020 -1.74 + NaOH 4.142e-30 4.144e-30 -29.383 -29.383 0.000 (0) +O(0) 5.351e-04 + O2 2.675e-04 2.676e-04 -3.573 -3.572 0.000 29.98 + +------------------------------Saturation indices------------------------------- + + Phase SI** log IAP log K(293 K, 2 atm) + + H2(g) -42.14 -45.22 -3.09 H2 + H2O(g) -1.63 -0.00 1.63 H2O + Halite -16.80 -15.24 1.57 NaCl + O2(g) -0.72 -3.57 -2.85 O2 + Sylvite -11.91 -11.03 0.87 KCl + +**For a gas, SI = log10(fugacity). Fugacity = pressure * phi / 1 atm. + For ideal gases, phi = 1. + +------------------ +End of simulation. +------------------ + +------------------------------------ +Reading input data for simulation 2. +------------------------------------ + +------------------------------- +End of Run after 1.836 Seconds. +------------------------------- + +Time: 10 +Chemistry cell: 3 +Grid cell(s) (0-based): 3 23 +------------------------------------ +Reading input data for simulation 1. +------------------------------------ + + RUN_CELLS + -start_time 777600 + -time_step 86400 + -cells 3 + END +-------------------------- +Beginning of run as cells. +-------------------------- + +----------------------------------------- +Beginning of batch-reaction calculations. +----------------------------------------- + +Reaction step 1. + +Using solution 3. Solution after simulation 1. +Using exchange 3. Exchange assemblage after simulation 1. + +-----------------------------Exchange composition------------------------------ + +X 2.200e-04 mol + + Equiv- Equivalent Log + Species Moles alents Fraction Gamma + + CaX2 1.100e-04 2.200e-04 9.999e-01 -0.080 + KX 1.700e-08 1.700e-08 7.725e-05 -0.020 + NaX 2.274e-12 2.274e-12 1.034e-08 -0.020 + +-----------------------------Solution composition------------------------------ + + Elements Molality Moles + + Ca 5.996e-04 1.196e-04 + Cl 1.200e-03 2.393e-04 + K 8.972e-07 1.789e-07 + Na 6.201e-10 1.236e-10 + +----------------------------Description of solution---------------------------- + + pH = 7.079 Charge balance + pe = 13.969 Adjusted to redox equilibrium + Specific Conductance (µS/cm, 20°C) = 138 + Density (g/cm³) = 0.99831 + Volume (L) = 0.19976 + Activity of water = 1.000 + Ionic strength (mol/kgw) = 1.800e-03 + Mass of water (kg) = 1.994e-01 + Total alkalinity (eq/kg) = -2.019e-19 + Temperature (°C) = 20.00 + Pressure (atm) = 2.00 + Electrical balance (eq) = 6.299e-18 + Percent error, 100*(Cat-|An|)/(Cat+|An|) = 0.00 + Iterations = 6 + Total H = 2.213642e+01 + Total O = 1.106831e+01 + +----------------------------Distribution of species---------------------------- + + Log Log Log mole V + Species Molality Activity Molality Activity Gamma cm³/mol + + H+ 8.715e-08 8.341e-08 -7.060 -7.079 -0.019 0.00 + OH- 8.611e-08 8.215e-08 -7.065 -7.085 -0.020 -4.31 + H2O 5.551e+01 1.000e+00 1.744 -0.000 0.000 18.05 +Ca 5.996e-04 + Ca+2 5.996e-04 4.987e-04 -3.222 -3.302 -0.080 -18.16 + CaOH+ 1.040e-09 9.923e-10 -8.983 -9.003 -0.020 (0) +Cl 1.200e-03 + Cl- 1.200e-03 1.145e-03 -2.921 -2.941 -0.020 17.92 +H(0) 0.000e+00 + H2 0.000e+00 0.000e+00 -45.225 -45.225 0.000 28.61 +K 8.972e-07 + K+ 8.972e-07 8.560e-07 -6.047 -6.068 -0.020 8.85 +Na 6.201e-10 + Na+ 6.201e-10 5.920e-10 -9.208 -9.228 -0.020 -1.74 + NaOH 4.860e-27 4.862e-27 -26.313 -26.313 0.000 (0) +O(0) 5.351e-04 + O2 2.675e-04 2.676e-04 -3.573 -3.572 0.000 29.98 + +------------------------------Saturation indices------------------------------- + + Phase SI** log IAP log K(293 K, 2 atm) + + H2(g) -42.14 -45.22 -3.09 H2 + H2O(g) -1.63 -0.00 1.63 H2O + Halite -13.74 -12.17 1.57 NaCl + O2(g) -0.72 -3.57 -2.85 O2 + Sylvite -9.88 -9.01 0.87 KCl + +**For a gas, SI = log10(fugacity). Fugacity = pressure * phi / 1 atm. + For ideal gases, phi = 1. + +------------------ +End of simulation. +------------------ + +------------------------------------ +Reading input data for simulation 2. +------------------------------------ + +------------------------------- +End of Run after 1.836 Seconds. +------------------------------- + +Time: 10 +Chemistry cell: 4 +Grid cell(s) (0-based): 4 24 +------------------------------------ +Reading input data for simulation 1. +------------------------------------ + + RUN_CELLS + -start_time 777600 + -time_step 86400 + -cells 4 + END +-------------------------- +Beginning of run as cells. +-------------------------- + +----------------------------------------- +Beginning of batch-reaction calculations. +----------------------------------------- + +Reaction step 1. + +Using solution 4. Solution after simulation 1. +Using exchange 4. Exchange assemblage after simulation 1. + +-----------------------------Exchange composition------------------------------ + +X 2.200e-04 mol + + Equiv- Equivalent Log + Species Moles alents Fraction Gamma + + CaX2 1.092e-04 2.184e-04 9.926e-01 -0.079 + KX 1.616e-06 1.616e-06 7.344e-03 -0.020 + NaX 2.646e-09 2.646e-09 1.203e-05 -0.020 + +-----------------------------Solution composition------------------------------ + + Elements Molality Moles + + Ca 5.583e-04 1.113e-04 + Cl 1.200e-03 2.393e-04 + K 8.262e-05 1.647e-05 + Na 6.987e-07 1.393e-07 + +----------------------------Description of solution---------------------------- + + pH = 7.079 Charge balance + pe = 13.969 Adjusted to redox equilibrium + Specific Conductance (µS/cm, 20°C) = 139 + Density (g/cm³) = 0.99831 + Volume (L) = 0.19976 + Activity of water = 1.000 + Ionic strength (mol/kgw) = 1.758e-03 + Mass of water (kg) = 1.994e-01 + Total alkalinity (eq/kg) = 2.447e-19 + Temperature (°C) = 20.00 + Pressure (atm) = 2.00 + Electrical balance (eq) = 2.790e-16 + Percent error, 100*(Cat-|An|)/(Cat+|An|) = 0.00 + Iterations = 7 + Total H = 2.213642e+01 + Total O = 1.106831e+01 + +----------------------------Distribution of species---------------------------- + + Log Log Log mole V + Species Molality Activity Molality Activity Gamma cm³/mol + + H+ 8.707e-08 8.337e-08 -7.060 -7.079 -0.019 0.00 + OH- 8.610e-08 8.218e-08 -7.065 -7.085 -0.020 -4.31 + H2O 5.551e+01 1.000e+00 1.744 -0.000 0.000 18.05 +Ca 5.583e-04 + Ca+2 5.583e-04 4.654e-04 -3.253 -3.332 -0.079 -18.16 + CaOH+ 9.702e-10 9.264e-10 -9.013 -9.033 -0.020 (0) +Cl 1.200e-03 + Cl- 1.200e-03 1.146e-03 -2.921 -2.941 -0.020 17.92 +H(0) 0.000e+00 + H2 0.000e+00 0.000e+00 -45.225 -45.225 0.000 28.61 +K 8.262e-05 + K+ 8.262e-05 7.886e-05 -4.083 -4.103 -0.020 8.85 +Na 6.987e-07 + Na+ 6.987e-07 6.674e-07 -6.156 -6.176 -0.020 -1.74 + NaOH 5.481e-24 5.484e-24 -23.261 -23.261 0.000 (0) +O(0) 5.351e-04 + O2 2.675e-04 2.676e-04 -3.573 -3.572 0.000 29.98 + +------------------------------Saturation indices------------------------------- + + Phase SI** log IAP log K(293 K, 2 atm) + + H2(g) -42.14 -45.22 -3.09 H2 + H2O(g) -1.63 -0.00 1.63 H2O + Halite -10.68 -9.12 1.57 NaCl + O2(g) -0.72 -3.57 -2.85 O2 + Sylvite -7.92 -7.04 0.87 KCl + +**For a gas, SI = log10(fugacity). Fugacity = pressure * phi / 1 atm. + For ideal gases, phi = 1. + +------------------ +End of simulation. +------------------ + +------------------------------------ +Reading input data for simulation 2. +------------------------------------ + +------------------------------- +End of Run after 1.836 Seconds. +------------------------------- + +Time: 10 +Chemistry cell: 5 +Grid cell(s) (0-based): 5 25 +------------------------------------ +Reading input data for simulation 1. +------------------------------------ + + RUN_CELLS + -start_time 777600 + -time_step 86400 + -cells 5 + END +-------------------------- +Beginning of run as cells. +-------------------------- + +----------------------------------------- +Beginning of batch-reaction calculations. +----------------------------------------- + +Reaction step 1. + +Using solution 5. Solution after simulation 1. +Using exchange 5. Exchange assemblage after simulation 1. + +-----------------------------Exchange composition------------------------------ + +X 2.200e-04 mol + + Equiv- Equivalent Log + Species Moles alents Fraction Gamma + + KX 1.072e-04 1.072e-04 4.871e-01 -0.017 + CaX2 5.530e-05 1.106e-04 5.027e-01 -0.066 + NaX 2.252e-06 2.252e-06 1.023e-02 -0.017 + +-----------------------------Solution composition------------------------------ + + Elements Molality Moles + + Ca 1.065e-05 2.124e-06 + Cl 1.200e-03 2.393e-04 + K 1.063e-03 2.120e-04 + Na 1.154e-04 2.301e-05 + +----------------------------Description of solution---------------------------- + + pH = 7.082 Charge balance + pe = 13.967 Adjusted to redox equilibrium + Specific Conductance (µS/cm, 20°C) = 152 + Density (g/cm³) = 0.99831 + Volume (L) = 0.19976 + Activity of water = 1.000 + Ionic strength (mol/kgw) = 1.211e-03 + Mass of water (kg) = 1.994e-01 + Total alkalinity (eq/kg) = 1.542e-18 + Temperature (°C) = 20.00 + Pressure (atm) = 2.00 + Electrical balance (eq) = 9.176e-14 + Percent error, 100*(Cat-|An|)/(Cat+|An|) = 0.00 + Iterations = 8 + Total H = 2.213642e+01 + Total O = 1.106831e+01 + +----------------------------Distribution of species---------------------------- + + Log Log Log mole V + Species Molality Activity Molality Activity Gamma cm³/mol + + H+ 8.598e-08 8.288e-08 -7.066 -7.082 -0.016 0.00 + OH- 8.596e-08 8.267e-08 -7.066 -7.083 -0.017 -4.32 + H2O 5.551e+01 1.000e+00 1.744 -0.000 0.000 18.05 +Ca 1.065e-05 + Ca+2 1.065e-05 9.140e-06 -4.973 -5.039 -0.066 -18.19 + CaOH+ 1.902e-11 1.830e-11 -10.721 -10.738 -0.017 (0) +Cl 1.200e-03 + Cl- 1.200e-03 1.154e-03 -2.921 -2.938 -0.017 17.91 +H(0) 0.000e+00 + H2 0.000e+00 0.000e+00 -45.225 -45.225 0.000 28.61 +K 1.063e-03 + K+ 1.063e-03 1.023e-03 -2.973 -2.990 -0.017 8.84 +Na 1.154e-04 + Na+ 1.154e-04 1.110e-04 -3.938 -3.955 -0.017 -1.75 + NaOH 9.175e-22 9.178e-22 -21.037 -21.037 0.000 (0) +O(0) 5.351e-04 + O2 2.675e-04 2.676e-04 -3.573 -3.573 0.000 29.98 + +------------------------------Saturation indices------------------------------- + + Phase SI** log IAP log K(293 K, 2 atm) + + H2(g) -42.14 -45.22 -3.09 H2 + H2O(g) -1.63 -0.00 1.63 H2O + Halite -8.46 -6.89 1.57 NaCl + O2(g) -0.72 -3.57 -2.85 O2 + Sylvite -6.80 -5.93 0.87 KCl + +**For a gas, SI = log10(fugacity). Fugacity = pressure * phi / 1 atm. + For ideal gases, phi = 1. + +------------------ +End of simulation. +------------------ + +------------------------------------ +Reading input data for simulation 2. +------------------------------------ + +------------------------------- +End of Run after 1.835 Seconds. +------------------------------- + +Time: 10 +Chemistry cell: 6 +Grid cell(s) (0-based): 6 26 +------------------------------------ +Reading input data for simulation 1. +------------------------------------ + + RUN_CELLS + -start_time 777600 + -time_step 86400 + -cells 6 + END +-------------------------- +Beginning of run as cells. +-------------------------- + +----------------------------------------- +Beginning of batch-reaction calculations. +----------------------------------------- + +Reaction step 1. + +Using solution 6. Solution after simulation 1. +Using exchange 6. Exchange assemblage after simulation 1. + +-----------------------------Exchange composition------------------------------ + +X 2.200e-04 mol + + Equiv- Equivalent Log + Species Moles alents Fraction Gamma + + KX 1.815e-04 1.815e-04 8.250e-01 -0.017 + NaX 3.850e-05 3.850e-05 1.750e-01 -0.017 + CaX2 7.697e-09 1.539e-08 6.997e-05 -0.066 + +-----------------------------Solution composition------------------------------ + + Elements Molality Moles + + Ca 1.499e-10 2.988e-11 + Cl 1.200e-03 2.393e-04 + K 5.727e-04 1.142e-04 + Na 6.273e-04 1.251e-04 + +----------------------------Description of solution---------------------------- + + pH = 7.082 Charge balance + pe = 13.967 Adjusted to redox equilibrium + Specific Conductance (µS/cm, 20°C) = 142 + Density (g/cm³) = 0.99830 + Volume (L) = 0.19976 + Activity of water = 1.000 + Ionic strength (mol/kgw) = 1.200e-03 + Mass of water (kg) = 1.994e-01 + Total alkalinity (eq/kg) = 3.336e-19 + Temperature (°C) = 20.00 + Pressure (atm) = 2.00 + Electrical balance (eq) = -7.013e-16 + Percent error, 100*(Cat-|An|)/(Cat+|An|) = -0.00 + Iterations = 6 + Total H = 2.213642e+01 + Total O = 1.106831e+01 + +----------------------------Distribution of species---------------------------- + + Log Log Log mole V + Species Molality Activity Molality Activity Gamma cm³/mol + + H+ 8.595e-08 8.287e-08 -7.066 -7.082 -0.016 0.00 + OH- 8.595e-08 8.268e-08 -7.066 -7.083 -0.017 -4.32 + H2O 5.551e+01 1.000e+00 1.744 -0.000 0.000 18.05 +Ca 1.499e-10 + Ca+2 1.499e-10 1.287e-10 -9.824 -9.890 -0.066 -18.19 + CaOH+ 2.679e-16 2.577e-16 -15.572 -15.589 -0.017 (0) +Cl 1.200e-03 + Cl- 1.200e-03 1.154e-03 -2.921 -2.938 -0.017 17.91 +H(0) 0.000e+00 + H2 0.000e+00 0.000e+00 -45.225 -45.225 0.000 28.61 +K 5.727e-04 + K+ 5.727e-04 5.509e-04 -3.242 -3.259 -0.017 8.84 +Na 6.273e-04 + Na+ 6.273e-04 6.037e-04 -3.203 -3.219 -0.017 -1.75 + NaOH 4.989e-21 4.991e-21 -20.302 -20.302 0.000 (0) +O(0) 5.351e-04 + O2 2.675e-04 2.676e-04 -3.573 -3.573 0.000 29.98 + +------------------------------Saturation indices------------------------------- + + Phase SI** log IAP log K(293 K, 2 atm) + + H2(g) -42.14 -45.22 -3.09 H2 + H2O(g) -1.63 -0.00 1.63 H2O + Halite -7.72 -6.16 1.57 NaCl + O2(g) -0.72 -3.57 -2.85 O2 + Sylvite -7.07 -6.20 0.87 KCl + +**For a gas, SI = log10(fugacity). Fugacity = pressure * phi / 1 atm. + For ideal gases, phi = 1. + +------------------ +End of simulation. +------------------ + +------------------------------------ +Reading input data for simulation 2. +------------------------------------ + +------------------------------- +End of Run after 1.835 Seconds. +------------------------------- + +Time: 10 +Chemistry cell: 7 +Grid cell(s) (0-based): 7 27 +------------------------------------ +Reading input data for simulation 1. +------------------------------------ + + RUN_CELLS + -start_time 777600 + -time_step 86400 + -cells 7 + END +-------------------------- +Beginning of run as cells. +-------------------------- + +----------------------------------------- +Beginning of batch-reaction calculations. +----------------------------------------- + +Reaction step 1. + +Using solution 7. Solution after simulation 1. +Using exchange 7. Exchange assemblage after simulation 1. + +-----------------------------Exchange composition------------------------------ + +X 2.200e-04 mol + + Equiv- Equivalent Log + Species Moles alents Fraction Gamma + + KX 1.242e-04 1.242e-04 5.647e-01 -0.017 + NaX 9.577e-05 9.577e-05 4.353e-01 -0.017 + CaX2 1.209e-14 2.418e-14 1.099e-10 -0.066 + +-----------------------------Solution composition------------------------------ + + Elements Molality Moles + + Ca 8.889e-17 1.773e-17 + Cl 1.200e-03 2.393e-04 + K 2.409e-04 4.804e-05 + Na 9.591e-04 1.912e-04 + +----------------------------Description of solution---------------------------- + + pH = 7.082 Charge balance + pe = 13.967 Adjusted to redox equilibrium + Specific Conductance (µS/cm, 20°C) = 136 + Density (g/cm³) = 0.99830 + Volume (L) = 0.19976 + Activity of water = 1.000 + Ionic strength (mol/kgw) = 1.200e-03 + Mass of water (kg) = 1.994e-01 + Total alkalinity (eq/kg) = 3.137e-18 + Temperature (°C) = 20.00 + Pressure (atm) = 2.00 + Electrical balance (eq) = 7.519e-13 + Percent error, 100*(Cat-|An|)/(Cat+|An|) = 0.00 + Iterations = 4 + Total H = 2.213642e+01 + Total O = 1.106831e+01 + +----------------------------Distribution of species---------------------------- + + Log Log Log mole V + Species Molality Activity Molality Activity Gamma cm³/mol + + OH- 8.595e-08 8.268e-08 -7.066 -7.083 -0.017 -4.32 + H+ 8.595e-08 8.287e-08 -7.066 -7.082 -0.016 0.00 + H2O 5.551e+01 1.000e+00 1.744 -0.000 0.000 18.05 +Ca 8.889e-17 + Ca+2 8.889e-17 7.634e-17 -16.051 -16.117 -0.066 -18.19 + CaOH+ 1.589e-22 1.529e-22 -21.799 -21.816 -0.017 (0) +Cl 1.200e-03 + Cl- 1.200e-03 1.154e-03 -2.921 -2.938 -0.017 17.91 +H(0) 0.000e+00 + H2 0.000e+00 0.000e+00 -45.225 -45.225 0.000 28.61 +K 2.409e-04 + K+ 2.409e-04 2.318e-04 -3.618 -3.635 -0.017 8.84 +Na 9.591e-04 + Na+ 9.591e-04 9.230e-04 -3.018 -3.035 -0.017 -1.75 + NaOH 7.628e-21 7.630e-21 -20.118 -20.117 0.000 (0) +O(0) 5.351e-04 + O2 2.675e-04 2.676e-04 -3.573 -3.573 0.000 29.98 + +------------------------------Saturation indices------------------------------- + + Phase SI** log IAP log K(293 K, 2 atm) + + H2(g) -42.14 -45.22 -3.09 H2 + H2O(g) -1.63 -0.00 1.63 H2O + Halite -7.54 -5.97 1.57 NaCl + O2(g) -0.72 -3.57 -2.85 O2 + Sylvite -7.45 -6.57 0.87 KCl + +**For a gas, SI = log10(fugacity). Fugacity = pressure * phi / 1 atm. + For ideal gases, phi = 1. + +------------------ +End of simulation. +------------------ + +------------------------------------ +Reading input data for simulation 2. +------------------------------------ + +------------------------------- +End of Run after 1.836 Seconds. +------------------------------- + +Time: 10 +Chemistry cell: 8 +Grid cell(s) (0-based): 8 28 +------------------------------------ +Reading input data for simulation 1. +------------------------------------ + + RUN_CELLS + -start_time 777600 + -time_step 86400 + -cells 8 + END +-------------------------- +Beginning of run as cells. +-------------------------- + +----------------------------------------- +Beginning of batch-reaction calculations. +----------------------------------------- + +Reaction step 1. + +Using solution 8. Solution after simulation 1. +Using exchange 8. Exchange assemblage after simulation 1. + +-----------------------------Exchange composition------------------------------ + +X 2.200e-04 mol + + Equiv- Equivalent Log + Species Moles alents Fraction Gamma + + KX 1.116e-04 1.116e-04 5.074e-01 -0.017 + NaX 1.084e-04 1.084e-04 4.926e-01 -0.017 + CaX2 2.857e-21 5.713e-21 2.597e-17 -0.066 + +-----------------------------Solution composition------------------------------ + + Elements Molality Moles + + Ca 1.785e-23 3.559e-24 + Cl 1.200e-03 2.393e-04 + K 1.995e-04 3.978e-05 + Na 1.000e-03 1.995e-04 + +----------------------------Description of solution---------------------------- + + pH = 7.082 Charge balance + pe = 13.967 Adjusted to redox equilibrium + Specific Conductance (µS/cm, 20°C) = 135 + Density (g/cm³) = 0.99830 + Volume (L) = 0.19976 + Activity of water = 1.000 + Ionic strength (mol/kgw) = 1.200e-03 + Mass of water (kg) = 1.994e-01 + Total alkalinity (eq/kg) = 2.785e-19 + Temperature (°C) = 20.00 + Pressure (atm) = 2.00 + Electrical balance (eq) = 1.445e-13 + Percent error, 100*(Cat-|An|)/(Cat+|An|) = 0.00 + Iterations = 5 + Total H = 2.213642e+01 + Total O = 1.106831e+01 + +----------------------------Distribution of species---------------------------- + + Log Log Log mole V + Species Molality Activity Molality Activity Gamma cm³/mol + + OH- 8.595e-08 8.268e-08 -7.066 -7.083 -0.017 -4.32 + H+ 8.595e-08 8.287e-08 -7.066 -7.082 -0.016 0.00 + H2O 5.551e+01 1.000e+00 1.744 -0.000 0.000 18.05 +Ca 1.785e-23 + Ca+2 1.785e-23 1.533e-23 -22.748 -22.815 -0.066 -18.19 + CaOH+ 3.190e-29 3.070e-29 -28.496 -28.513 -0.017 (0) +Cl 1.200e-03 + Cl- 1.200e-03 1.154e-03 -2.921 -2.938 -0.017 17.91 +H(0) 0.000e+00 + H2 0.000e+00 0.000e+00 -45.225 -45.225 0.000 28.61 +K 1.995e-04 + K+ 1.995e-04 1.919e-04 -3.700 -3.717 -0.017 8.84 +Na 1.000e-03 + Na+ 1.000e-03 9.629e-04 -3.000 -3.016 -0.017 -1.75 + NaOH 7.957e-21 7.959e-21 -20.099 -20.099 0.000 (0) +O(0) 5.351e-04 + O2 2.675e-04 2.676e-04 -3.573 -3.573 0.000 29.98 + +------------------------------Saturation indices------------------------------- + + Phase SI** log IAP log K(293 K, 2 atm) + + H2(g) -42.14 -45.22 -3.09 H2 + H2O(g) -1.63 -0.00 1.63 H2O + Halite -7.52 -5.95 1.57 NaCl + O2(g) -0.72 -3.57 -2.85 O2 + Sylvite -7.53 -6.65 0.87 KCl + +**For a gas, SI = log10(fugacity). Fugacity = pressure * phi / 1 atm. + For ideal gases, phi = 1. + +------------------ +End of simulation. +------------------ + +------------------------------------ +Reading input data for simulation 2. +------------------------------------ + +------------------------------- +End of Run after 1.836 Seconds. +------------------------------- + +Time: 10 +Chemistry cell: 9 +Grid cell(s) (0-based): 9 29 +------------------------------------ +Reading input data for simulation 1. +------------------------------------ + + RUN_CELLS + -start_time 777600 + -time_step 86400 + -cells 9 + END +-------------------------- +Beginning of run as cells. +-------------------------- + +----------------------------------------- +Beginning of batch-reaction calculations. +----------------------------------------- + +Reaction step 1. + +Using solution 9. Solution after simulation 1. +Using exchange 9. Exchange assemblage after simulation 1. + +-----------------------------Exchange composition------------------------------ + +X 2.200e-04 mol + + Equiv- Equivalent Log + Species Moles alents Fraction Gamma + + KX 1.108e-04 1.108e-04 5.035e-01 -0.017 + NaX 1.092e-04 1.092e-04 4.965e-01 -0.017 + +-----------------------------Solution composition------------------------------ + + Elements Molality Moles + + Cl 1.200e-03 2.393e-04 + K 1.970e-04 3.928e-05 + Na 1.003e-03 2.000e-04 + +----------------------------Description of solution---------------------------- + + pH = 7.082 Charge balance + pe = 13.967 Adjusted to redox equilibrium + Specific Conductance (µS/cm, 20°C) = 135 + Density (g/cm³) = 0.99830 + Volume (L) = 0.19976 + Activity of water = 1.000 + Ionic strength (mol/kgw) = 1.200e-03 + Mass of water (kg) = 1.994e-01 + Total alkalinity (eq/kg) = -5.725e-21 + Temperature (°C) = 20.00 + Pressure (atm) = 2.00 + Electrical balance (eq) = -1.575e-17 + Percent error, 100*(Cat-|An|)/(Cat+|An|) = -0.00 + Iterations = 2 + Total H = 2.213642e+01 + Total O = 1.106831e+01 + +----------------------------Distribution of species---------------------------- + + Log Log Log mole V + Species Molality Activity Molality Activity Gamma cm³/mol + + H+ 8.595e-08 8.287e-08 -7.066 -7.082 -0.016 0.00 + OH- 8.595e-08 8.268e-08 -7.066 -7.083 -0.017 -4.32 + H2O 5.551e+01 1.000e+00 1.744 -0.000 0.000 18.05 +Cl 1.200e-03 + Cl- 1.200e-03 1.154e-03 -2.921 -2.938 -0.017 17.91 +H(0) 0.000e+00 + H2 0.000e+00 0.000e+00 -45.225 -45.225 0.000 28.61 +K 1.970e-04 + K+ 1.970e-04 1.895e-04 -3.706 -3.722 -0.017 8.84 +Na 1.003e-03 + Na+ 1.003e-03 9.653e-04 -2.999 -3.015 -0.017 -1.75 + NaOH 7.977e-21 7.980e-21 -20.098 -20.098 0.000 (0) +O(0) 5.351e-04 + O2 2.675e-04 2.676e-04 -3.573 -3.573 0.000 29.98 + +------------------------------Saturation indices------------------------------- + + Phase SI** log IAP log K(293 K, 2 atm) + + H2(g) -42.14 -45.22 -3.09 H2 + H2O(g) -1.63 -0.00 1.63 H2O + Halite -7.52 -5.95 1.57 NaCl + O2(g) -0.72 -3.57 -2.85 O2 + Sylvite -7.53 -6.66 0.87 KCl + +**For a gas, SI = log10(fugacity). Fugacity = pressure * phi / 1 atm. + For ideal gases, phi = 1. + +------------------ +End of simulation. +------------------ + +------------------------------------ +Reading input data for simulation 2. +------------------------------------ + +------------------------------- +End of Run after 1.837 Seconds. +------------------------------- + +Time: 10 +Chemistry cell: 10 +Grid cell(s) (0-based): 10 30 +------------------------------------ +Reading input data for simulation 1. +------------------------------------ + + RUN_CELLS + -start_time 777600 + -time_step 86400 + -cells 10 + END +-------------------------- +Beginning of run as cells. +-------------------------- + +----------------------------------------- +Beginning of batch-reaction calculations. +----------------------------------------- + +Reaction step 1. + +Using solution 10. Solution after simulation 1. +Using exchange 10. Exchange assemblage after simulation 1. + +-----------------------------Exchange composition------------------------------ + +X 2.200e-04 mol + + Equiv- Equivalent Log + Species Moles alents Fraction Gamma + + KX 1.108e-04 1.108e-04 5.034e-01 -0.017 + NaX 1.092e-04 1.092e-04 4.966e-01 -0.017 + NH4X 3.892e-65 3.892e-65 1.769e-61 -0.017 + +-----------------------------Solution composition------------------------------ + + Elements Molality Moles + + K 1.969e-04 3.926e-05 + N 1.200e-03 2.393e-04 + Na 1.003e-03 2.000e-04 + +----------------------------Description of solution---------------------------- + + pH = 7.082 Charge balance + pe = 13.967 Adjusted to redox equilibrium + Specific Conductance (µS/cm, 20°C) = 130 + Density (g/cm³) = 0.99832 + Volume (L) = 0.19976 + Activity of water = 1.000 + Ionic strength (mol/kgw) = 1.200e-03 + Mass of water (kg) = 1.994e-01 + Total alkalinity (eq/kg) = -3.398e-18 + Temperature (°C) = 20.00 + Pressure (atm) = 2.00 + Electrical balance (eq) = -6.800e-17 + Percent error, 100*(Cat-|An|)/(Cat+|An|) = -0.00 + Iterations = 2 + Total H = 2.213587e+01 + Total O = 1.106876e+01 + +----------------------------Distribution of species---------------------------- + + Log Log Log mole V + Species Molality Activity Molality Activity Gamma cm³/mol + + H+ 8.595e-08 8.287e-08 -7.066 -7.082 -0.016 0.00 + OH- 8.595e-08 8.268e-08 -7.066 -7.083 -0.017 -4.32 + H2O 5.551e+01 1.000e+00 1.744 -0.000 0.000 18.05 +H(0) 0.000e+00 + H2 0.000e+00 0.000e+00 -45.225 -45.225 0.000 28.61 +K 1.969e-04 + K+ 1.969e-04 1.894e-04 -3.706 -3.723 -0.017 8.84 +N(-3) 0.000e+00 + NH4+ 0.000e+00 0.000e+00 -64.054 -64.071 -0.017 17.80 + NH3 0.000e+00 0.000e+00 -66.390 -66.390 0.000 24.19 +N(0) 5.774e-20 + N2 2.887e-20 2.888e-20 -19.540 -19.539 0.000 29.29 +N(3) 1.258e-16 + NO2- 1.258e-16 1.210e-16 -15.900 -15.917 -0.017 24.69 +N(5) 1.200e-03 + NO3- 1.200e-03 1.154e-03 -2.921 -2.938 -0.017 28.98 +Na 1.003e-03 + Na+ 1.003e-03 9.654e-04 -2.999 -3.015 -0.017 -1.75 + NaOH 7.978e-21 7.980e-21 -20.098 -20.098 0.000 (0) +O(0) 5.351e-04 + O2 2.676e-04 2.676e-04 -3.573 -3.572 0.000 29.98 + +------------------------------Saturation indices------------------------------- + + Phase SI** log IAP log K(293 K, 2 atm) + + H2(g) -42.14 -45.22 -3.09 H2 + H2O(g) -1.63 -0.00 1.63 H2O + N2(g) -16.39 -19.54 -3.14 N2 + NH3(g) -68.29 -66.39 1.90 NH3 + O2(g) -0.72 -3.57 -2.85 O2 + +**For a gas, SI = log10(fugacity). Fugacity = pressure * phi / 1 atm. + For ideal gases, phi = 1. + +------------------ +End of simulation. +------------------ + +------------------------------------ +Reading input data for simulation 2. +------------------------------------ + +------------------------------- +End of Run after 1.835 Seconds. +------------------------------- + +Time: 10 +Chemistry cell: 11 +Grid cell(s) (0-based): 11 31 +------------------------------------ +Reading input data for simulation 1. +------------------------------------ + + RUN_CELLS + -start_time 777600 + -time_step 86400 + -cells 11 + END +-------------------------- +Beginning of run as cells. +-------------------------- + +----------------------------------------- +Beginning of batch-reaction calculations. +----------------------------------------- + +Reaction step 1. + +Using solution 11. Solution after simulation 1. +Using exchange 11. Exchange assemblage after simulation 1. + +-----------------------------Exchange composition------------------------------ + +X 2.200e-04 mol + + Equiv- Equivalent Log + Species Moles alents Fraction Gamma + + KX 1.108e-04 1.108e-04 5.034e-01 -0.017 + NaX 1.092e-04 1.092e-04 4.966e-01 -0.017 + NH4X 3.892e-65 3.892e-65 1.769e-61 -0.017 + +-----------------------------Solution composition------------------------------ + + Elements Molality Moles + + K 1.969e-04 3.926e-05 + N 1.200e-03 2.393e-04 + Na 1.003e-03 2.000e-04 + +----------------------------Description of solution---------------------------- + + pH = 7.082 Charge balance + pe = 13.967 Adjusted to redox equilibrium + Specific Conductance (µS/cm, 20°C) = 130 + Density (g/cm³) = 0.99832 + Volume (L) = 0.19976 + Activity of water = 1.000 + Ionic strength (mol/kgw) = 1.200e-03 + Mass of water (kg) = 1.994e-01 + Total alkalinity (eq/kg) = -3.398e-18 + Temperature (°C) = 20.00 + Pressure (atm) = 2.00 + Electrical balance (eq) = -6.800e-17 + Percent error, 100*(Cat-|An|)/(Cat+|An|) = -0.00 + Iterations = 2 + Total H = 2.213587e+01 + Total O = 1.106876e+01 + +----------------------------Distribution of species---------------------------- + + Log Log Log mole V + Species Molality Activity Molality Activity Gamma cm³/mol + + H+ 8.595e-08 8.287e-08 -7.066 -7.082 -0.016 0.00 + OH- 8.595e-08 8.268e-08 -7.066 -7.083 -0.017 -4.32 + H2O 5.551e+01 1.000e+00 1.744 -0.000 0.000 18.05 +H(0) 0.000e+00 + H2 0.000e+00 0.000e+00 -45.225 -45.225 0.000 28.61 +K 1.969e-04 + K+ 1.969e-04 1.894e-04 -3.706 -3.723 -0.017 8.84 +N(-3) 0.000e+00 + NH4+ 0.000e+00 0.000e+00 -64.054 -64.071 -0.017 17.80 + NH3 0.000e+00 0.000e+00 -66.390 -66.390 0.000 24.19 +N(0) 5.774e-20 + N2 2.887e-20 2.888e-20 -19.540 -19.539 0.000 29.29 +N(3) 1.258e-16 + NO2- 1.258e-16 1.210e-16 -15.900 -15.917 -0.017 24.69 +N(5) 1.200e-03 + NO3- 1.200e-03 1.154e-03 -2.921 -2.938 -0.017 28.98 +Na 1.003e-03 + Na+ 1.003e-03 9.654e-04 -2.999 -3.015 -0.017 -1.75 + NaOH 7.978e-21 7.980e-21 -20.098 -20.098 0.000 (0) +O(0) 5.351e-04 + O2 2.676e-04 2.676e-04 -3.573 -3.572 0.000 29.98 + +------------------------------Saturation indices------------------------------- + + Phase SI** log IAP log K(293 K, 2 atm) + + H2(g) -42.14 -45.22 -3.09 H2 + H2O(g) -1.63 -0.00 1.63 H2O + N2(g) -16.39 -19.54 -3.14 N2 + NH3(g) -68.29 -66.39 1.90 NH3 + O2(g) -0.72 -3.57 -2.85 O2 + +**For a gas, SI = log10(fugacity). Fugacity = pressure * phi / 1 atm. + For ideal gases, phi = 1. + +------------------ +End of simulation. +------------------ + +------------------------------------ +Reading input data for simulation 2. +------------------------------------ + +------------------------------- +End of Run after 1.835 Seconds. +------------------------------- + +Time: 10 +Chemistry cell: 12 +Grid cell(s) (0-based): 12 32 +------------------------------------ +Reading input data for simulation 1. +------------------------------------ + + RUN_CELLS + -start_time 777600 + -time_step 86400 + -cells 12 + END +-------------------------- +Beginning of run as cells. +-------------------------- + +----------------------------------------- +Beginning of batch-reaction calculations. +----------------------------------------- + +Reaction step 1. + +Using solution 12. Solution after simulation 1. +Using exchange 12. Exchange assemblage after simulation 1. + +-----------------------------Exchange composition------------------------------ + +X 2.200e-04 mol + + Equiv- Equivalent Log + Species Moles alents Fraction Gamma + + KX 1.108e-04 1.108e-04 5.034e-01 -0.017 + NaX 1.092e-04 1.092e-04 4.966e-01 -0.017 + NH4X 3.892e-65 3.892e-65 1.769e-61 -0.017 + +-----------------------------Solution composition------------------------------ + + Elements Molality Moles + + K 1.969e-04 3.926e-05 + N 1.200e-03 2.393e-04 + Na 1.003e-03 2.000e-04 + +----------------------------Description of solution---------------------------- + + pH = 7.082 Charge balance + pe = 13.967 Adjusted to redox equilibrium + Specific Conductance (µS/cm, 20°C) = 130 + Density (g/cm³) = 0.99832 + Volume (L) = 0.19976 + Activity of water = 1.000 + Ionic strength (mol/kgw) = 1.200e-03 + Mass of water (kg) = 1.994e-01 + Total alkalinity (eq/kg) = -3.398e-18 + Temperature (°C) = 20.00 + Pressure (atm) = 2.00 + Electrical balance (eq) = -6.800e-17 + Percent error, 100*(Cat-|An|)/(Cat+|An|) = -0.00 + Iterations = 2 + Total H = 2.213587e+01 + Total O = 1.106876e+01 + +----------------------------Distribution of species---------------------------- + + Log Log Log mole V + Species Molality Activity Molality Activity Gamma cm³/mol + + H+ 8.595e-08 8.287e-08 -7.066 -7.082 -0.016 0.00 + OH- 8.595e-08 8.268e-08 -7.066 -7.083 -0.017 -4.32 + H2O 5.551e+01 1.000e+00 1.744 -0.000 0.000 18.05 +H(0) 0.000e+00 + H2 0.000e+00 0.000e+00 -45.225 -45.225 0.000 28.61 +K 1.969e-04 + K+ 1.969e-04 1.894e-04 -3.706 -3.723 -0.017 8.84 +N(-3) 0.000e+00 + NH4+ 0.000e+00 0.000e+00 -64.054 -64.071 -0.017 17.80 + NH3 0.000e+00 0.000e+00 -66.390 -66.390 0.000 24.19 +N(0) 5.774e-20 + N2 2.887e-20 2.888e-20 -19.540 -19.539 0.000 29.29 +N(3) 1.258e-16 + NO2- 1.258e-16 1.210e-16 -15.900 -15.917 -0.017 24.69 +N(5) 1.200e-03 + NO3- 1.200e-03 1.154e-03 -2.921 -2.938 -0.017 28.98 +Na 1.003e-03 + Na+ 1.003e-03 9.654e-04 -2.999 -3.015 -0.017 -1.75 + NaOH 7.978e-21 7.980e-21 -20.098 -20.098 0.000 (0) +O(0) 5.351e-04 + O2 2.676e-04 2.676e-04 -3.573 -3.572 0.000 29.98 + +------------------------------Saturation indices------------------------------- + + Phase SI** log IAP log K(293 K, 2 atm) + + H2(g) -42.14 -45.22 -3.09 H2 + H2O(g) -1.63 -0.00 1.63 H2O + N2(g) -16.39 -19.54 -3.14 N2 + NH3(g) -68.29 -66.39 1.90 NH3 + O2(g) -0.72 -3.57 -2.85 O2 + +**For a gas, SI = log10(fugacity). Fugacity = pressure * phi / 1 atm. + For ideal gases, phi = 1. + +------------------ +End of simulation. +------------------ + +------------------------------------ +Reading input data for simulation 2. +------------------------------------ + +------------------------------- +End of Run after 1.836 Seconds. +------------------------------- + +Time: 10 +Chemistry cell: 13 +Grid cell(s) (0-based): 13 33 +------------------------------------ +Reading input data for simulation 1. +------------------------------------ + + RUN_CELLS + -start_time 777600 + -time_step 86400 + -cells 13 + END +-------------------------- +Beginning of run as cells. +-------------------------- + +----------------------------------------- +Beginning of batch-reaction calculations. +----------------------------------------- + +Reaction step 1. + +Using solution 13. Solution after simulation 1. +Using exchange 13. Exchange assemblage after simulation 1. + +-----------------------------Exchange composition------------------------------ + +X 2.200e-04 mol + + Equiv- Equivalent Log + Species Moles alents Fraction Gamma + + KX 1.108e-04 1.108e-04 5.034e-01 -0.017 + NaX 1.092e-04 1.092e-04 4.966e-01 -0.017 + NH4X 3.892e-65 3.892e-65 1.769e-61 -0.017 + +-----------------------------Solution composition------------------------------ + + Elements Molality Moles + + K 1.969e-04 3.926e-05 + N 1.200e-03 2.393e-04 + Na 1.003e-03 2.000e-04 + +----------------------------Description of solution---------------------------- + + pH = 7.082 Charge balance + pe = 13.967 Adjusted to redox equilibrium + Specific Conductance (µS/cm, 20°C) = 130 + Density (g/cm³) = 0.99832 + Volume (L) = 0.19976 + Activity of water = 1.000 + Ionic strength (mol/kgw) = 1.200e-03 + Mass of water (kg) = 1.994e-01 + Total alkalinity (eq/kg) = -3.398e-18 + Temperature (°C) = 20.00 + Pressure (atm) = 2.00 + Electrical balance (eq) = -6.800e-17 + Percent error, 100*(Cat-|An|)/(Cat+|An|) = -0.00 + Iterations = 2 + Total H = 2.213587e+01 + Total O = 1.106876e+01 + +----------------------------Distribution of species---------------------------- + + Log Log Log mole V + Species Molality Activity Molality Activity Gamma cm³/mol + + H+ 8.595e-08 8.287e-08 -7.066 -7.082 -0.016 0.00 + OH- 8.595e-08 8.268e-08 -7.066 -7.083 -0.017 -4.32 + H2O 5.551e+01 1.000e+00 1.744 -0.000 0.000 18.05 +H(0) 0.000e+00 + H2 0.000e+00 0.000e+00 -45.225 -45.225 0.000 28.61 +K 1.969e-04 + K+ 1.969e-04 1.894e-04 -3.706 -3.723 -0.017 8.84 +N(-3) 0.000e+00 + NH4+ 0.000e+00 0.000e+00 -64.054 -64.071 -0.017 17.80 + NH3 0.000e+00 0.000e+00 -66.390 -66.390 0.000 24.19 +N(0) 5.774e-20 + N2 2.887e-20 2.888e-20 -19.540 -19.539 0.000 29.29 +N(3) 1.258e-16 + NO2- 1.258e-16 1.210e-16 -15.900 -15.917 -0.017 24.69 +N(5) 1.200e-03 + NO3- 1.200e-03 1.154e-03 -2.921 -2.938 -0.017 28.98 +Na 1.003e-03 + Na+ 1.003e-03 9.654e-04 -2.999 -3.015 -0.017 -1.75 + NaOH 7.978e-21 7.980e-21 -20.098 -20.098 0.000 (0) +O(0) 5.351e-04 + O2 2.676e-04 2.676e-04 -3.573 -3.572 0.000 29.98 + +------------------------------Saturation indices------------------------------- + + Phase SI** log IAP log K(293 K, 2 atm) + + H2(g) -42.14 -45.22 -3.09 H2 + H2O(g) -1.63 -0.00 1.63 H2O + N2(g) -16.39 -19.54 -3.14 N2 + NH3(g) -68.29 -66.39 1.90 NH3 + O2(g) -0.72 -3.57 -2.85 O2 + +**For a gas, SI = log10(fugacity). Fugacity = pressure * phi / 1 atm. + For ideal gases, phi = 1. + +------------------ +End of simulation. +------------------ + +------------------------------------ +Reading input data for simulation 2. +------------------------------------ + +------------------------------- +End of Run after 1.836 Seconds. +------------------------------- + +Time: 10 +Chemistry cell: 14 +Grid cell(s) (0-based): 14 34 +------------------------------------ +Reading input data for simulation 1. +------------------------------------ + + RUN_CELLS + -start_time 777600 + -time_step 86400 + -cells 14 + END +-------------------------- +Beginning of run as cells. +-------------------------- + +----------------------------------------- +Beginning of batch-reaction calculations. +----------------------------------------- + +Reaction step 1. + +Using solution 14. Solution after simulation 1. +Using exchange 14. Exchange assemblage after simulation 1. + +-----------------------------Exchange composition------------------------------ + +X 2.200e-04 mol + + Equiv- Equivalent Log + Species Moles alents Fraction Gamma + + KX 1.108e-04 1.108e-04 5.034e-01 -0.017 + NaX 1.092e-04 1.092e-04 4.966e-01 -0.017 + NH4X 3.892e-65 3.892e-65 1.769e-61 -0.017 + +-----------------------------Solution composition------------------------------ + + Elements Molality Moles + + K 1.969e-04 3.926e-05 + N 1.200e-03 2.393e-04 + Na 1.003e-03 2.000e-04 + +----------------------------Description of solution---------------------------- + + pH = 7.082 Charge balance + pe = 13.967 Adjusted to redox equilibrium + Specific Conductance (µS/cm, 20°C) = 130 + Density (g/cm³) = 0.99832 + Volume (L) = 0.19976 + Activity of water = 1.000 + Ionic strength (mol/kgw) = 1.200e-03 + Mass of water (kg) = 1.994e-01 + Total alkalinity (eq/kg) = -3.398e-18 + Temperature (°C) = 20.00 + Pressure (atm) = 2.00 + Electrical balance (eq) = -6.800e-17 + Percent error, 100*(Cat-|An|)/(Cat+|An|) = -0.00 + Iterations = 2 + Total H = 2.213587e+01 + Total O = 1.106876e+01 + +----------------------------Distribution of species---------------------------- + + Log Log Log mole V + Species Molality Activity Molality Activity Gamma cm³/mol + + H+ 8.595e-08 8.287e-08 -7.066 -7.082 -0.016 0.00 + OH- 8.595e-08 8.268e-08 -7.066 -7.083 -0.017 -4.32 + H2O 5.551e+01 1.000e+00 1.744 -0.000 0.000 18.05 +H(0) 0.000e+00 + H2 0.000e+00 0.000e+00 -45.225 -45.225 0.000 28.61 +K 1.969e-04 + K+ 1.969e-04 1.894e-04 -3.706 -3.723 -0.017 8.84 +N(-3) 0.000e+00 + NH4+ 0.000e+00 0.000e+00 -64.054 -64.071 -0.017 17.80 + NH3 0.000e+00 0.000e+00 -66.390 -66.390 0.000 24.19 +N(0) 5.774e-20 + N2 2.887e-20 2.888e-20 -19.540 -19.539 0.000 29.29 +N(3) 1.258e-16 + NO2- 1.258e-16 1.210e-16 -15.900 -15.917 -0.017 24.69 +N(5) 1.200e-03 + NO3- 1.200e-03 1.154e-03 -2.921 -2.938 -0.017 28.98 +Na 1.003e-03 + Na+ 1.003e-03 9.654e-04 -2.999 -3.015 -0.017 -1.75 + NaOH 7.978e-21 7.980e-21 -20.098 -20.098 0.000 (0) +O(0) 5.351e-04 + O2 2.676e-04 2.676e-04 -3.573 -3.572 0.000 29.98 + +------------------------------Saturation indices------------------------------- + + Phase SI** log IAP log K(293 K, 2 atm) + + H2(g) -42.14 -45.22 -3.09 H2 + H2O(g) -1.63 -0.00 1.63 H2O + N2(g) -16.39 -19.54 -3.14 N2 + NH3(g) -68.29 -66.39 1.90 NH3 + O2(g) -0.72 -3.57 -2.85 O2 + +**For a gas, SI = log10(fugacity). Fugacity = pressure * phi / 1 atm. + For ideal gases, phi = 1. + +------------------ +End of simulation. +------------------ + +------------------------------------ +Reading input data for simulation 2. +------------------------------------ + +------------------------------- +End of Run after 1.836 Seconds. +------------------------------- + +Time: 10 +Chemistry cell: 15 +Grid cell(s) (0-based): 15 35 +------------------------------------ +Reading input data for simulation 1. +------------------------------------ + + RUN_CELLS + -start_time 777600 + -time_step 86400 + -cells 15 + END +-------------------------- +Beginning of run as cells. +-------------------------- + +----------------------------------------- +Beginning of batch-reaction calculations. +----------------------------------------- + +Reaction step 1. + +Using solution 15. Solution after simulation 1. +Using exchange 15. Exchange assemblage after simulation 1. + +-----------------------------Exchange composition------------------------------ + +X 2.200e-04 mol + + Equiv- Equivalent Log + Species Moles alents Fraction Gamma + + KX 1.108e-04 1.108e-04 5.034e-01 -0.017 + NaX 1.092e-04 1.092e-04 4.966e-01 -0.017 + NH4X 3.892e-65 3.892e-65 1.769e-61 -0.017 + +-----------------------------Solution composition------------------------------ + + Elements Molality Moles + + K 1.969e-04 3.926e-05 + N 1.200e-03 2.393e-04 + Na 1.003e-03 2.000e-04 + +----------------------------Description of solution---------------------------- + + pH = 7.082 Charge balance + pe = 13.967 Adjusted to redox equilibrium + Specific Conductance (µS/cm, 20°C) = 130 + Density (g/cm³) = 0.99832 + Volume (L) = 0.19976 + Activity of water = 1.000 + Ionic strength (mol/kgw) = 1.200e-03 + Mass of water (kg) = 1.994e-01 + Total alkalinity (eq/kg) = -3.398e-18 + Temperature (°C) = 20.00 + Pressure (atm) = 2.00 + Electrical balance (eq) = -6.800e-17 + Percent error, 100*(Cat-|An|)/(Cat+|An|) = -0.00 + Iterations = 2 + Total H = 2.213587e+01 + Total O = 1.106876e+01 + +----------------------------Distribution of species---------------------------- + + Log Log Log mole V + Species Molality Activity Molality Activity Gamma cm³/mol + + H+ 8.595e-08 8.287e-08 -7.066 -7.082 -0.016 0.00 + OH- 8.595e-08 8.268e-08 -7.066 -7.083 -0.017 -4.32 + H2O 5.551e+01 1.000e+00 1.744 -0.000 0.000 18.05 +H(0) 0.000e+00 + H2 0.000e+00 0.000e+00 -45.225 -45.225 0.000 28.61 +K 1.969e-04 + K+ 1.969e-04 1.894e-04 -3.706 -3.723 -0.017 8.84 +N(-3) 0.000e+00 + NH4+ 0.000e+00 0.000e+00 -64.054 -64.071 -0.017 17.80 + NH3 0.000e+00 0.000e+00 -66.390 -66.390 0.000 24.19 +N(0) 5.774e-20 + N2 2.887e-20 2.888e-20 -19.540 -19.539 0.000 29.29 +N(3) 1.258e-16 + NO2- 1.258e-16 1.210e-16 -15.900 -15.917 -0.017 24.69 +N(5) 1.200e-03 + NO3- 1.200e-03 1.154e-03 -2.921 -2.938 -0.017 28.98 +Na 1.003e-03 + Na+ 1.003e-03 9.654e-04 -2.999 -3.015 -0.017 -1.75 + NaOH 7.978e-21 7.980e-21 -20.098 -20.098 0.000 (0) +O(0) 5.351e-04 + O2 2.676e-04 2.676e-04 -3.573 -3.572 0.000 29.98 + +------------------------------Saturation indices------------------------------- + + Phase SI** log IAP log K(293 K, 2 atm) + + H2(g) -42.14 -45.22 -3.09 H2 + H2O(g) -1.63 -0.00 1.63 H2O + N2(g) -16.39 -19.54 -3.14 N2 + NH3(g) -68.29 -66.39 1.90 NH3 + O2(g) -0.72 -3.57 -2.85 O2 + +**For a gas, SI = log10(fugacity). Fugacity = pressure * phi / 1 atm. + For ideal gases, phi = 1. + +------------------ +End of simulation. +------------------ + +------------------------------------ +Reading input data for simulation 2. +------------------------------------ + +------------------------------- +End of Run after 1.837 Seconds. +------------------------------- + +Time: 10 +Chemistry cell: 16 +Grid cell(s) (0-based): 16 36 +------------------------------------ +Reading input data for simulation 1. +------------------------------------ + + RUN_CELLS + -start_time 777600 + -time_step 86400 + -cells 16 + END +-------------------------- +Beginning of run as cells. +-------------------------- + +----------------------------------------- +Beginning of batch-reaction calculations. +----------------------------------------- + +Reaction step 1. + +Using solution 16. Solution after simulation 1. +Using exchange 16. Exchange assemblage after simulation 1. + +-----------------------------Exchange composition------------------------------ + +X 2.200e-04 mol + + Equiv- Equivalent Log + Species Moles alents Fraction Gamma + + KX 1.108e-04 1.108e-04 5.034e-01 -0.017 + NaX 1.092e-04 1.092e-04 4.966e-01 -0.017 + NH4X 3.892e-65 3.892e-65 1.769e-61 -0.017 + +-----------------------------Solution composition------------------------------ + + Elements Molality Moles + + K 1.969e-04 3.926e-05 + N 1.200e-03 2.393e-04 + Na 1.003e-03 2.000e-04 + +----------------------------Description of solution---------------------------- + + pH = 7.082 Charge balance + pe = 13.967 Adjusted to redox equilibrium + Specific Conductance (µS/cm, 20°C) = 130 + Density (g/cm³) = 0.99832 + Volume (L) = 0.19976 + Activity of water = 1.000 + Ionic strength (mol/kgw) = 1.200e-03 + Mass of water (kg) = 1.994e-01 + Total alkalinity (eq/kg) = -3.398e-18 + Temperature (°C) = 20.00 + Pressure (atm) = 2.00 + Electrical balance (eq) = -6.800e-17 + Percent error, 100*(Cat-|An|)/(Cat+|An|) = -0.00 + Iterations = 2 + Total H = 2.213587e+01 + Total O = 1.106876e+01 + +----------------------------Distribution of species---------------------------- + + Log Log Log mole V + Species Molality Activity Molality Activity Gamma cm³/mol + + H+ 8.595e-08 8.287e-08 -7.066 -7.082 -0.016 0.00 + OH- 8.595e-08 8.268e-08 -7.066 -7.083 -0.017 -4.32 + H2O 5.551e+01 1.000e+00 1.744 -0.000 0.000 18.05 +H(0) 0.000e+00 + H2 0.000e+00 0.000e+00 -45.225 -45.225 0.000 28.61 +K 1.969e-04 + K+ 1.969e-04 1.894e-04 -3.706 -3.723 -0.017 8.84 +N(-3) 0.000e+00 + NH4+ 0.000e+00 0.000e+00 -64.054 -64.071 -0.017 17.80 + NH3 0.000e+00 0.000e+00 -66.390 -66.390 0.000 24.19 +N(0) 5.774e-20 + N2 2.887e-20 2.888e-20 -19.540 -19.539 0.000 29.29 +N(3) 1.258e-16 + NO2- 1.258e-16 1.210e-16 -15.900 -15.917 -0.017 24.69 +N(5) 1.200e-03 + NO3- 1.200e-03 1.154e-03 -2.921 -2.938 -0.017 28.98 +Na 1.003e-03 + Na+ 1.003e-03 9.654e-04 -2.999 -3.015 -0.017 -1.75 + NaOH 7.978e-21 7.980e-21 -20.098 -20.098 0.000 (0) +O(0) 5.351e-04 + O2 2.676e-04 2.676e-04 -3.573 -3.572 0.000 29.98 + +------------------------------Saturation indices------------------------------- + + Phase SI** log IAP log K(293 K, 2 atm) + + H2(g) -42.14 -45.22 -3.09 H2 + H2O(g) -1.63 -0.00 1.63 H2O + N2(g) -16.39 -19.54 -3.14 N2 + NH3(g) -68.29 -66.39 1.90 NH3 + O2(g) -0.72 -3.57 -2.85 O2 + +**For a gas, SI = log10(fugacity). Fugacity = pressure * phi / 1 atm. + For ideal gases, phi = 1. + +------------------ +End of simulation. +------------------ + +------------------------------------ +Reading input data for simulation 2. +------------------------------------ + +------------------------------- +End of Run after 1.838 Seconds. +------------------------------- + +Time: 10 +Chemistry cell: 17 +Grid cell(s) (0-based): 17 37 +------------------------------------ +Reading input data for simulation 1. +------------------------------------ + + RUN_CELLS + -start_time 777600 + -time_step 86400 + -cells 17 + END +-------------------------- +Beginning of run as cells. +-------------------------- + +----------------------------------------- +Beginning of batch-reaction calculations. +----------------------------------------- + +Reaction step 1. + +Using solution 17. Solution after simulation 1. +Using exchange 17. Exchange assemblage after simulation 1. + +-----------------------------Exchange composition------------------------------ + +X 2.200e-04 mol + + Equiv- Equivalent Log + Species Moles alents Fraction Gamma + + KX 1.108e-04 1.108e-04 5.034e-01 -0.017 + NaX 1.092e-04 1.092e-04 4.966e-01 -0.017 + NH4X 3.892e-65 3.892e-65 1.769e-61 -0.017 + +-----------------------------Solution composition------------------------------ + + Elements Molality Moles + + K 1.969e-04 3.926e-05 + N 1.200e-03 2.393e-04 + Na 1.003e-03 2.000e-04 + +----------------------------Description of solution---------------------------- + + pH = 7.082 Charge balance + pe = 13.967 Adjusted to redox equilibrium + Specific Conductance (µS/cm, 20°C) = 130 + Density (g/cm³) = 0.99832 + Volume (L) = 0.19976 + Activity of water = 1.000 + Ionic strength (mol/kgw) = 1.200e-03 + Mass of water (kg) = 1.994e-01 + Total alkalinity (eq/kg) = -3.398e-18 + Temperature (°C) = 20.00 + Pressure (atm) = 2.00 + Electrical balance (eq) = -6.800e-17 + Percent error, 100*(Cat-|An|)/(Cat+|An|) = -0.00 + Iterations = 2 + Total H = 2.213587e+01 + Total O = 1.106876e+01 + +----------------------------Distribution of species---------------------------- + + Log Log Log mole V + Species Molality Activity Molality Activity Gamma cm³/mol + + H+ 8.595e-08 8.287e-08 -7.066 -7.082 -0.016 0.00 + OH- 8.595e-08 8.268e-08 -7.066 -7.083 -0.017 -4.32 + H2O 5.551e+01 1.000e+00 1.744 -0.000 0.000 18.05 +H(0) 0.000e+00 + H2 0.000e+00 0.000e+00 -45.225 -45.225 0.000 28.61 +K 1.969e-04 + K+ 1.969e-04 1.894e-04 -3.706 -3.723 -0.017 8.84 +N(-3) 0.000e+00 + NH4+ 0.000e+00 0.000e+00 -64.054 -64.071 -0.017 17.80 + NH3 0.000e+00 0.000e+00 -66.390 -66.390 0.000 24.19 +N(0) 5.774e-20 + N2 2.887e-20 2.888e-20 -19.540 -19.539 0.000 29.29 +N(3) 1.258e-16 + NO2- 1.258e-16 1.210e-16 -15.900 -15.917 -0.017 24.69 +N(5) 1.200e-03 + NO3- 1.200e-03 1.154e-03 -2.921 -2.938 -0.017 28.98 +Na 1.003e-03 + Na+ 1.003e-03 9.654e-04 -2.999 -3.015 -0.017 -1.75 + NaOH 7.978e-21 7.980e-21 -20.098 -20.098 0.000 (0) +O(0) 5.351e-04 + O2 2.676e-04 2.676e-04 -3.573 -3.572 0.000 29.98 + +------------------------------Saturation indices------------------------------- + + Phase SI** log IAP log K(293 K, 2 atm) + + H2(g) -42.14 -45.22 -3.09 H2 + H2O(g) -1.63 -0.00 1.63 H2O + N2(g) -16.39 -19.54 -3.14 N2 + NH3(g) -68.29 -66.39 1.90 NH3 + O2(g) -0.72 -3.57 -2.85 O2 + +**For a gas, SI = log10(fugacity). Fugacity = pressure * phi / 1 atm. + For ideal gases, phi = 1. + +------------------ +End of simulation. +------------------ + +------------------------------------ +Reading input data for simulation 2. +------------------------------------ + +------------------------------- +End of Run after 1.838 Seconds. +------------------------------- + +Time: 10 +Chemistry cell: 18 +Grid cell(s) (0-based): 18 38 +------------------------------------ +Reading input data for simulation 1. +------------------------------------ + + RUN_CELLS + -start_time 777600 + -time_step 86400 + -cells 18 + END +-------------------------- +Beginning of run as cells. +-------------------------- + +----------------------------------------- +Beginning of batch-reaction calculations. +----------------------------------------- + +Reaction step 1. + +Using solution 18. Solution after simulation 1. +Using exchange 18. Exchange assemblage after simulation 1. + +-----------------------------Exchange composition------------------------------ + +X 2.200e-04 mol + + Equiv- Equivalent Log + Species Moles alents Fraction Gamma + + KX 1.108e-04 1.108e-04 5.034e-01 -0.017 + NaX 1.092e-04 1.092e-04 4.966e-01 -0.017 + NH4X 3.892e-65 3.892e-65 1.769e-61 -0.017 + +-----------------------------Solution composition------------------------------ + + Elements Molality Moles + + K 1.969e-04 3.926e-05 + N 1.200e-03 2.393e-04 + Na 1.003e-03 2.000e-04 + +----------------------------Description of solution---------------------------- + + pH = 7.082 Charge balance + pe = 13.967 Adjusted to redox equilibrium + Specific Conductance (µS/cm, 20°C) = 130 + Density (g/cm³) = 0.99832 + Volume (L) = 0.19976 + Activity of water = 1.000 + Ionic strength (mol/kgw) = 1.200e-03 + Mass of water (kg) = 1.994e-01 + Total alkalinity (eq/kg) = -3.398e-18 + Temperature (°C) = 20.00 + Pressure (atm) = 2.00 + Electrical balance (eq) = -6.800e-17 + Percent error, 100*(Cat-|An|)/(Cat+|An|) = -0.00 + Iterations = 2 + Total H = 2.213587e+01 + Total O = 1.106876e+01 + +----------------------------Distribution of species---------------------------- + + Log Log Log mole V + Species Molality Activity Molality Activity Gamma cm³/mol + + H+ 8.595e-08 8.287e-08 -7.066 -7.082 -0.016 0.00 + OH- 8.595e-08 8.268e-08 -7.066 -7.083 -0.017 -4.32 + H2O 5.551e+01 1.000e+00 1.744 -0.000 0.000 18.05 +H(0) 0.000e+00 + H2 0.000e+00 0.000e+00 -45.225 -45.225 0.000 28.61 +K 1.969e-04 + K+ 1.969e-04 1.894e-04 -3.706 -3.723 -0.017 8.84 +N(-3) 0.000e+00 + NH4+ 0.000e+00 0.000e+00 -64.054 -64.071 -0.017 17.80 + NH3 0.000e+00 0.000e+00 -66.390 -66.390 0.000 24.19 +N(0) 5.774e-20 + N2 2.887e-20 2.888e-20 -19.540 -19.539 0.000 29.29 +N(3) 1.258e-16 + NO2- 1.258e-16 1.210e-16 -15.900 -15.917 -0.017 24.69 +N(5) 1.200e-03 + NO3- 1.200e-03 1.154e-03 -2.921 -2.938 -0.017 28.98 +Na 1.003e-03 + Na+ 1.003e-03 9.654e-04 -2.999 -3.015 -0.017 -1.75 + NaOH 7.978e-21 7.980e-21 -20.098 -20.098 0.000 (0) +O(0) 5.351e-04 + O2 2.676e-04 2.676e-04 -3.573 -3.572 0.000 29.98 + +------------------------------Saturation indices------------------------------- + + Phase SI** log IAP log K(293 K, 2 atm) + + H2(g) -42.14 -45.22 -3.09 H2 + H2O(g) -1.63 -0.00 1.63 H2O + N2(g) -16.39 -19.54 -3.14 N2 + NH3(g) -68.29 -66.39 1.90 NH3 + O2(g) -0.72 -3.57 -2.85 O2 + +**For a gas, SI = log10(fugacity). Fugacity = pressure * phi / 1 atm. + For ideal gases, phi = 1. + +------------------ +End of simulation. +------------------ + +------------------------------------ +Reading input data for simulation 2. +------------------------------------ + +------------------------------- +End of Run after 1.839 Seconds. +------------------------------- + +Time: 10 +Chemistry cell: 19 +Grid cell(s) (0-based): 19 39 +------------------------------------ +Reading input data for simulation 1. +------------------------------------ + + RUN_CELLS + -start_time 777600 + -time_step 86400 + -cells 19 + END +-------------------------- +Beginning of run as cells. +-------------------------- + +----------------------------------------- +Beginning of batch-reaction calculations. +----------------------------------------- + +Reaction step 1. + +Using solution 19. Solution after simulation 1. +Using exchange 19. Exchange assemblage after simulation 1. + +-----------------------------Exchange composition------------------------------ + +X 2.200e-04 mol + + Equiv- Equivalent Log + Species Moles alents Fraction Gamma + + KX 1.108e-04 1.108e-04 5.034e-01 -0.017 + NaX 1.092e-04 1.092e-04 4.966e-01 -0.017 + NH4X 3.892e-65 3.892e-65 1.769e-61 -0.017 + +-----------------------------Solution composition------------------------------ + + Elements Molality Moles + + K 1.969e-04 3.926e-05 + N 1.200e-03 2.393e-04 + Na 1.003e-03 2.000e-04 + +----------------------------Description of solution---------------------------- + + pH = 7.082 Charge balance + pe = 13.967 Adjusted to redox equilibrium + Specific Conductance (µS/cm, 20°C) = 130 + Density (g/cm³) = 0.99832 + Volume (L) = 0.19976 + Activity of water = 1.000 + Ionic strength (mol/kgw) = 1.200e-03 + Mass of water (kg) = 1.994e-01 + Total alkalinity (eq/kg) = -3.398e-18 + Temperature (°C) = 20.00 + Pressure (atm) = 2.00 + Electrical balance (eq) = -6.800e-17 + Percent error, 100*(Cat-|An|)/(Cat+|An|) = -0.00 + Iterations = 2 + Total H = 2.213587e+01 + Total O = 1.106876e+01 + +----------------------------Distribution of species---------------------------- + + Log Log Log mole V + Species Molality Activity Molality Activity Gamma cm³/mol + + H+ 8.595e-08 8.287e-08 -7.066 -7.082 -0.016 0.00 + OH- 8.595e-08 8.268e-08 -7.066 -7.083 -0.017 -4.32 + H2O 5.551e+01 1.000e+00 1.744 -0.000 0.000 18.05 +H(0) 0.000e+00 + H2 0.000e+00 0.000e+00 -45.225 -45.225 0.000 28.61 +K 1.969e-04 + K+ 1.969e-04 1.894e-04 -3.706 -3.723 -0.017 8.84 +N(-3) 0.000e+00 + NH4+ 0.000e+00 0.000e+00 -64.054 -64.071 -0.017 17.80 + NH3 0.000e+00 0.000e+00 -66.390 -66.390 0.000 24.19 +N(0) 5.774e-20 + N2 2.887e-20 2.888e-20 -19.540 -19.539 0.000 29.29 +N(3) 1.258e-16 + NO2- 1.258e-16 1.210e-16 -15.900 -15.917 -0.017 24.69 +N(5) 1.200e-03 + NO3- 1.200e-03 1.154e-03 -2.921 -2.938 -0.017 28.98 +Na 1.003e-03 + Na+ 1.003e-03 9.654e-04 -2.999 -3.015 -0.017 -1.75 + NaOH 7.978e-21 7.980e-21 -20.098 -20.098 0.000 (0) +O(0) 5.351e-04 + O2 2.676e-04 2.676e-04 -3.573 -3.572 0.000 29.98 + +------------------------------Saturation indices------------------------------- + + Phase SI** log IAP log K(293 K, 2 atm) + + H2(g) -42.14 -45.22 -3.09 H2 + H2O(g) -1.63 -0.00 1.63 H2O + N2(g) -16.39 -19.54 -3.14 N2 + NH3(g) -68.29 -66.39 1.90 NH3 + O2(g) -0.72 -3.57 -2.85 O2 + +**For a gas, SI = log10(fugacity). Fugacity = pressure * phi / 1 atm. + For ideal gases, phi = 1. + +------------------ +End of simulation. +------------------ + +------------------------------------ +Reading input data for simulation 2. +------------------------------------ + +------------------------------- +End of Run after 1.839 Seconds. +------------------------------- + diff --git a/Tests/Output/AdvectBMI_f90.dmp b/Tests/Output/AdvectBMI_f90.dmp new file mode 100644 index 000000000..fd55a6650 --- /dev/null +++ b/Tests/Output/AdvectBMI_f90.dmp @@ -0,0 +1,997 @@ + SOLUTION_RAW 0 Solution after simulation 1. + -temp 11 + -pressure 10 + -potential 0 + -total_h 22.136415505711 + -total_o 11.068314447237 + -cb 1.050774149571e-18 + -density 0.99830524784931 + -totals + Ca 0.00011964289826793 + Cl 0.00023928579659462 + K 5.8750816837893e-14 + Na 5.0285660777464e-20 + -pH 7.07879604971 + -pe 13.969354457422 + -mu 0.0018000850694612 + -ah2o 0.99996484900903 + -mass_water 0.19940483056236 + -soln_vol 0.19975835757839 + -total_alkalinity 2.3078339090229e-20 + -activities + Ca -3.3018013654974 + Cl -2.9412141501733 + E -13.969354457422 + H(0) -45.224826771493 + K -12.551155967533 + Na -18.618448968438 + O(0) -3.5724441104545 + -gammas + SOLUTION_RAW 1 Solution after simulation 1. + -temp 11 + -pressure 10 + -potential 0 + -total_h 22.136415505711 + -total_o 11.068314447237 + -cb 7.4075678215349e-19 + -density 0.9983052478494 + -totals + Ca 0.00011964289180017 + Cl 0.00023928579659462 + K 1.2994194765224e-11 + Na 8.4819564419848e-17 + -pH 7.0787960498582 + -pe 13.969354457273 + -mu 0.0018000850370259 + -ah2o 0.99996484900848 + -mass_water 0.19940483056236 + -soln_vol 0.19975835757862 + -total_alkalinity 6.083086224715e-20 + -activities + Ca -3.3018013883042 + Cl -2.9412141499986 + E -13.969354457273 + H(0) -45.224826771491 + K -10.206420504568 + Na -15.39139709174 + O(0) -3.5724441104576 + -gammas + SOLUTION_RAW 2 Solution after simulation 1. + -temp 11 + -pressure 10 + -potential 0 + -total_h 22.136415505711 + -total_o 11.068314447237 + -cb 1.087461264099e-18 + -density 0.99830524786079 + -totals + Ca 0.00011964204834046 + Cl 0.00023928579659462 + K 1.6998083052281e-09 + Na 1.0538874983484e-13 + -pH 7.0787960691273 + -pe 13.969354437912 + -mu 0.0018000808071463 + -ah2o 0.99996484893657 + -mass_water 0.19940483056236 + -soln_vol 0.19975835760855 + -total_alkalinity -5.8375790189092e-20 + -activities + Ca -3.3018043625499 + Cl -2.9412141272248 + E -13.969354437912 + H(0) -45.224826771308 + K -8.0897699068024 + Na -12.297098854615 + O(0) -3.5724441108878 + -gammas + SOLUTION_RAW 3 Solution after simulation 1. + -temp 11 + -pressure 10 + -potential 0 + -total_h 22.136415505711 + -total_o 11.068314447237 + -cb 6.2993443240608e-18 + -density 0.99830524888929 + -totals + Ca 0.0001195533788944 + Cl 0.00023928579659462 + K 1.7891515852859e-07 + Na 1.2364729923646e-10 + -pH 7.0787980954847 + -pe 13.969352402081 + -mu 0.0017996361373178 + -ah2o 0.99996484137719 + -mass_water 0.19940483056236 + -soln_vol 0.19975836078693 + -total_alkalinity -4.025060860683e-20 + -activities + Ca -3.3021171525641 + Cl -2.9412117329418 + E -13.969352402081 + H(0) -45.224826752361 + K -6.0675203126222 + Na -9.2277061356187 + O(0) -3.5724441553476 + -gammas + SOLUTION_RAW 4 Solution after simulation 1. + -temp 11 + -pressure 10 + -potential 0 + -total_h 22.136415505711 + -total_o 11.068314447237 + -cb 2.7899452433526e-16 + -density 0.99830534209357 + -totals + Ca 0.00011133610379392 + Cl 0.00023928579659464 + K 1.6474256036527e-05 + Na 1.3933297054804e-07 + -pH 7.0789862884286 + -pe 13.969163331038 + -mu 0.0017584271924245 + -ah2o 0.9999641408255 + -mass_water 0.19940483056264 + -soln_vol 0.19975865369741 + -total_alkalinity 4.8800347418178e-20 + -activities + Ca -3.3321851919438 + Cl -2.9409884191375 + E -13.969163331038 + H(0) -45.224824996163 + K -4.1031374741148 + Na -6.1756188689487 + O(0) -3.5724482762571 + -gammas + SOLUTION_RAW 5 Solution after simulation 1. + -temp 11 + -pressure 10 + -potential 0 + -total_h 22.136415505711 + -total_o 11.068314447237 + -cb 9.1760133444219e-14 + -density 0.99830599410147 + -totals + Ca 2.1235996938492e-06 + Cl 0.00023928579659728 + K 0.00021202857277338 + Na 2.3010024527965e-05 + -pH 7.0815725817894 + -pe 13.966565367277 + -mu 0.0012107356299945 + -ah2o 0.9999548300763 + -mass_water 0.19940483056657 + -soln_vol 0.1997623247924 + -total_alkalinity 3.0744979879616e-19 + -activities + Ca -5.0390564337549 + Cl -2.9376960035394 + E -13.966565367277 + H(0) -45.224801655362 + K -2.99024504251 + Na -3.9545342945762 + O(0) -3.5725030454002 + -gammas + EXCHANGE_RAW 0 Exchange assemblage after simulation 1. + # EXCHANGE_MODIFY candidate identifiers # + -exchange_gammas 1 + -component X + # EXCHANGE_MODIFY candidate identifiers # + -totals + Ca 0.00011000000007735 + K 5.578978683061e-15 + Na 9.2458165885048e-22 + X 0.00022000000016027 + -charge_balance 0 + -la 1.2218455551817 + -phase_proportion 0 + -formula_z 0 + # EXCHANGE_MODIFY candidates with new_def=true # + -new_def 0 + -solution_equilibria 0 + -n_solution -999 + # Exchange workspace variables # + -totals + EXCHANGE_RAW 1 Exchange assemblage after simulation 1. + # EXCHANGE_MODIFY candidate identifiers # + -exchange_gammas 1 + -component X + # EXCHANGE_MODIFY candidate identifiers # + -totals + Ca 0.00010999999941902 + K 1.233929011179e-12 + Na 1.5595423075109e-18 + X 0.00022000000007198 + -charge_balance 0 + -la 1.2218455657082 + -phase_proportion 0 + -formula_z 0 + # EXCHANGE_MODIFY candidates with new_def=true # + -new_def 0 + -solution_equilibria 0 + -n_solution -999 + # Exchange workspace variables # + -totals + EXCHANGE_RAW 2 Exchange assemblage after simulation 1. + # EXCHANGE_MODIFY candidate identifiers # + -exchange_gammas 1 + -component X + # EXCHANGE_MODIFY candidate identifiers # + -totals + Ca 0.00010999991932863 + K 1.6141434301678e-10 + Na 1.9377455513261e-15 + X 0.00022000000007354 + -charge_balance 0 + -la 1.2218469384705 + -phase_proportion 0 + -formula_z 0 + # EXCHANGE_MODIFY candidates with new_def=true # + -new_def 0 + -solution_equilibria 0 + -n_solution -999 + # Exchange workspace variables # + -totals + EXCHANGE_RAW 3 Exchange assemblage after simulation 1. + # EXCHANGE_MODIFY candidate identifiers # + -exchange_gammas 1 + -component X + # EXCHANGE_MODIFY candidate identifiers # + -totals + Ca 0.00010999150115391 + K 1.6995489881071e-08 + Na 2.2742149191652e-12 + X 0.00022000000007192 + -charge_balance 0 + -la 1.2219913122299 + -phase_proportion 0 + -formula_z 0 + # EXCHANGE_MODIFY candidates with new_def=true # + -new_def 0 + -solution_equilibria 0 + -n_solution -999 + # Exchange workspace variables # + -totals + EXCHANGE_RAW 4 Exchange assemblage after simulation 1. + # EXCHANGE_MODIFY candidate identifiers # + -exchange_gammas 1 + -component X + # EXCHANGE_MODIFY candidate identifiers # + -totals + Ca 0.00010919081226404 + K 1.6157299307705e-06 + Na 2.6459228053411e-09 + X 0.00022000000038165 + -charge_balance 0 + -la 1.2358677284202 + -phase_proportion 0 + -formula_z 0 + # EXCHANGE_MODIFY candidates with new_def=true # + -new_def 0 + -solution_equilibria 0 + -n_solution -999 + # Exchange workspace variables # + -totals + EXCHANGE_RAW 5 Exchange assemblage after simulation 1. + # EXCHANGE_MODIFY candidate identifiers # + -exchange_gammas 1 + -component X + # EXCHANGE_MODIFY candidate identifiers # + -totals + Ca 5.5298103951778e-05 + K 0.00010715222898898 + Na 2.2515631796115e-06 + X 0.00022000000007215 + -charge_balance 0 + -la 1.9479117009121 + -phase_proportion 0 + -formula_z 0 + # EXCHANGE_MODIFY candidates with new_def=true # + -new_def 0 + -solution_equilibria 0 + -n_solution -999 + # Exchange workspace variables # + -totals + SOLUTION_RAW 6 Solution after simulation 1. + -temp 11 + -pressure 10 + -potential 0 + -total_h 22.136415505711 + -total_o 11.068314447238 + -cb -7.0131871306237e-16 + -density 0.99830319084416 + -totals + Ca 2.9884729795162e-11 + Cl 0.00023928579659462 + K 0.00011419229852425 + Na 0.0001250934383002 + -pH 7.0816246296562 + -pe 13.966513092483 + -mu 0.001200086104411 + -ah2o 0.99995464903458 + -mass_water 0.19940483056666 + -soln_vol 0.19976131924196 + -total_alkalinity 6.6511938694164e-20 + -activities + Ca -9.8904037600626 + Cl -2.9376246522544 + E -13.966513092483 + H(0) -45.224801201507 + K -3.2589310415151 + Na -3.2191468857373 + O(0) -3.5725041103674 + -gammas + SOLUTION_RAW 7 Solution after simulation 1. + -temp 11 + -pressure 10 + -potential 0 + -total_h 22.136415505711 + -total_o 11.068314447238 + -cb 7.519440964854e-13 + -density 0.99830135805566 + -totals + Ca 1.7725778405703e-17 + Cl 0.00023928579659467 + K 4.8038347520833e-05 + Na 0.00019124744982574 + -pH 7.0816246303982 + -pe 13.96651309174 + -mu 0.0012000859564291 + -ah2o 0.99995464903197 + -mass_water 0.19940483056666 + -soln_vol 0.19976061828604 + -total_alkalinity 6.2549743560035e-19 + -activities + Ca -16.117247773922 + Cl -2.9376246512605 + E -13.96651309174 + H(0) -45.224801201505 + K -3.6349797956564 + Na -3.034785761604 + O(0) -3.572504110375 + -gammas + SOLUTION_RAW 8 Solution after simulation 1. + -temp 11 + -pressure 10 + -potential 0 + -total_h 22.136415505711 + -total_o 11.068314447237 + -cb 1.4446859131826e-13 + -density 0.99830112934291 + -totals + Ca 3.559165139662e-24 + Cl 0.00023928579659468 + K 3.9783056142788e-05 + Na 0.00019950274059636 + -pH 7.0816246303915 + -pe 13.966513091748 + -mu 0.0012000859549058 + -ah2o 0.99995464903202 + -mass_water 0.19940483056666 + -soln_vol 0.19976053081432 + -total_alkalinity 5.553690632681e-20 + -activities + Ca -22.814504950611 + Cl -2.9376246512502 + E -13.966513091748 + H(0) -45.224801201508 + K -3.7168697126014 + Na -3.0164325483659 + O(0) -3.5725041103679 + -gammas + SOLUTION_RAW 9 Solution after simulation 1. + -temp 11 + -pressure 10 + -potential 0 + -total_h 22.136415505852 + -total_o 11.068314447393 + -cb -1.5753846671975e-17 + -density 0.99830111534334 + -totals + Cl 0.00023928579659624 + K 3.9277732064696e-05 + Na 0.00020000806453153 + -pH 7.0816246303917 + -pe 13.96651317794 + -mu 0.0012000859545433 + -ah2o 0.99995464902842 + -mass_water 0.19940483056793 + -soln_vol 0.19976052546253 + -total_alkalinity -1.1415092453232e-21 + -activities + Cl -2.9376246512477 + E -13.96651317794 + H(0) -45.224801382473 + K -3.722421452022 + Na -3.0153339071739 + O(0) -3.5725037484386 + -gammas + SOLUTION_RAW 10 Solution after simulation 1. + -temp 11 + -pressure 10 + -potential 0 + -total_h 22.135866361697 + -total_o 11.068757726907 + -cb -6.7997561691754e-17 + -density 0.99831968732863 + -totals + K 3.9260409219821e-05 + N 0.00023927986057314 + Na 0.00020001945135325 + -pH 7.0816246305188 + -pe 13.966528092735 + -mu 0.0012000859545714 + -ah2o 0.99995464840361 + -mass_water 0.19939988387738 + -soln_vol 0.19975821827742 + -total_alkalinity -6.7760981419119e-19 + -activities + E -13.966528092735 + H(0) -45.224831203736 + K -3.7226022594356 + N(-3) -64.071413252819 + N(0) -19.539412420616 + N(3) -15.917214058761 + N(5) -2.9377614291833 + Na -3.0152984089092 + O(0) -3.5724441064573 + -gammas + EXCHANGE_RAW 6 Exchange assemblage after simulation 1. + # EXCHANGE_MODIFY candidate identifiers # + -exchange_gammas 1 + -component X + # EXCHANGE_MODIFY candidate identifiers # + -totals + Ca 7.6966419072614e-09 + K 0.00018148921301038 + Na 3.8495393845064e-05 + X 0.00022000000013926 + -charge_balance 0 + -la 2.4455188861322 + -phase_proportion 0 + -formula_z 0 + # EXCHANGE_MODIFY candidates with new_def=true # + -new_def 0 + -solution_equilibria 0 + -n_solution -999 + # Exchange workspace variables # + -totals + EXCHANGE_RAW 7 Exchange assemblage after simulation 1. + # EXCHANGE_MODIFY candidate identifiers # + -exchange_gammas 1 + -component X + # EXCHANGE_MODIFY candidate identifiers # + -totals + Ca 1.2087506837347e-14 + K 0.00012423437997991 + Na 9.5765620068131e-05 + X 0.00022000000007221 + -charge_balance 0 + -la 2.6569586208605 + -phase_proportion 0 + -formula_z 0 + # EXCHANGE_MODIFY candidates with new_def=true # + -new_def 0 + -solution_equilibria 0 + -n_solution -999 + # Exchange workspace variables # + -totals + EXCHANGE_RAW 8 Exchange assemblage after simulation 1. + # EXCHANGE_MODIFY candidate identifiers # + -exchange_gammas 1 + -component X + # EXCHANGE_MODIFY candidate identifiers # + -totals + Ca 2.8566435934267e-21 + K 0.00011161951512659 + Na 0.00010838048494552 + X 0.00022000000007212 + -charge_balance 0 + -la 2.6923468725498 + -phase_proportion 0 + -formula_z 0 + # EXCHANGE_MODIFY candidates with new_def=true # + -new_def 0 + -solution_equilibria 0 + -n_solution -999 + # Exchange workspace variables # + -totals + EXCHANGE_RAW 9 Exchange assemblage after simulation 1. + # EXCHANGE_MODIFY candidate identifiers # + -exchange_gammas 1 + -component X + # EXCHANGE_MODIFY candidate identifiers # + -totals + K 0.00011077740051585 + Na 0.00010922259955631 + X 0.00022000000007216 + -charge_balance 0 + -la 2.6946096502043 + -phase_proportion 0 + -formula_z 0 + # EXCHANGE_MODIFY candidates with new_def=true # + -new_def 0 + -solution_equilibria 0 + -n_solution -999 + # Exchange workspace variables # + -totals + EXCHANGE_RAW 10 Exchange assemblage after simulation 1. + # EXCHANGE_MODIFY candidate identifiers # + -exchange_gammas 1 + -component X + # EXCHANGE_MODIFY candidate identifiers # + -totals + H 1.5569735071866e-64 + K 0.00011075000841372 + N 3.8924337679664e-65 + Na 0.0001092499916584 + X 0.00022000000007212 + -charge_balance 0 + -la 2.6946830556585 + -phase_proportion 0 + -formula_z 0 + # EXCHANGE_MODIFY candidates with new_def=true # + -new_def 0 + -solution_equilibria 0 + -n_solution -999 + # Exchange workspace variables # + -totals + SOLUTION_RAW 11 Solution after simulation 1. + -temp 11 + -pressure 10 + -potential 0 + -total_h 22.135866361697 + -total_o 11.068757726907 + -cb -6.7997561691754e-17 + -density 0.99831968732863 + -totals + K 3.9260409219821e-05 + N 0.00023927986057314 + Na 0.00020001945135325 + -pH 7.0816246305188 + -pe 13.966528092735 + -mu 0.0012000859545714 + -ah2o 0.99995464840361 + -mass_water 0.19939988387738 + -soln_vol 0.19975821827742 + -total_alkalinity -6.7760981419119e-19 + -activities + E -13.966528092735 + H(0) -45.224831203736 + K -3.7226022594356 + N(-3) -64.071413252819 + N(0) -19.539412420616 + N(3) -15.917214058761 + N(5) -2.9377614291833 + Na -3.0152984089092 + O(0) -3.5724441064573 + -gammas + SOLUTION_RAW 12 Solution after simulation 1. + -temp 11 + -pressure 10 + -potential 0 + -total_h 22.135866361697 + -total_o 11.068757726907 + -cb -6.7997561691754e-17 + -density 0.99831968732863 + -totals + K 3.9260409219821e-05 + N 0.00023927986057314 + Na 0.00020001945135325 + -pH 7.0816246305188 + -pe 13.966528092735 + -mu 0.0012000859545714 + -ah2o 0.99995464840361 + -mass_water 0.19939988387738 + -soln_vol 0.19975821827742 + -total_alkalinity -6.7760981419119e-19 + -activities + E -13.966528092735 + H(0) -45.224831203736 + K -3.7226022594356 + N(-3) -64.071413252819 + N(0) -19.539412420616 + N(3) -15.917214058761 + N(5) -2.9377614291833 + Na -3.0152984089092 + O(0) -3.5724441064573 + -gammas + SOLUTION_RAW 13 Solution after simulation 1. + -temp 11 + -pressure 10 + -potential 0 + -total_h 22.135866361697 + -total_o 11.068757726907 + -cb -6.7997561691754e-17 + -density 0.99831968732863 + -totals + K 3.9260409219821e-05 + N 0.00023927986057314 + Na 0.00020001945135325 + -pH 7.0816246305188 + -pe 13.966528092735 + -mu 0.0012000859545714 + -ah2o 0.99995464840361 + -mass_water 0.19939988387738 + -soln_vol 0.19975821827742 + -total_alkalinity -6.7760981419119e-19 + -activities + E -13.966528092735 + H(0) -45.224831203736 + K -3.7226022594356 + N(-3) -64.071413252819 + N(0) -19.539412420616 + N(3) -15.917214058761 + N(5) -2.9377614291833 + Na -3.0152984089092 + O(0) -3.5724441064573 + -gammas + SOLUTION_RAW 14 Solution after simulation 1. + -temp 11 + -pressure 10 + -potential 0 + -total_h 22.135866361697 + -total_o 11.068757726907 + -cb -6.7997561691754e-17 + -density 0.99831968732863 + -totals + K 3.9260409219821e-05 + N 0.00023927986057314 + Na 0.00020001945135325 + -pH 7.0816246305188 + -pe 13.966528092735 + -mu 0.0012000859545714 + -ah2o 0.99995464840361 + -mass_water 0.19939988387738 + -soln_vol 0.19975821827742 + -total_alkalinity -6.7760981419119e-19 + -activities + E -13.966528092735 + H(0) -45.224831203736 + K -3.7226022594356 + N(-3) -64.071413252819 + N(0) -19.539412420616 + N(3) -15.917214058761 + N(5) -2.9377614291833 + Na -3.0152984089092 + O(0) -3.5724441064573 + -gammas + SOLUTION_RAW 15 Solution after simulation 1. + -temp 11 + -pressure 10 + -potential 0 + -total_h 22.135866361697 + -total_o 11.068757726907 + -cb -6.7997561691754e-17 + -density 0.99831968732863 + -totals + K 3.9260409219821e-05 + N 0.00023927986057314 + Na 0.00020001945135325 + -pH 7.0816246305188 + -pe 13.966528092735 + -mu 0.0012000859545714 + -ah2o 0.99995464840361 + -mass_water 0.19939988387738 + -soln_vol 0.19975821827742 + -total_alkalinity -6.7760981419119e-19 + -activities + E -13.966528092735 + H(0) -45.224831203736 + K -3.7226022594356 + N(-3) -64.071413252819 + N(0) -19.539412420616 + N(3) -15.917214058761 + N(5) -2.9377614291833 + Na -3.0152984089092 + O(0) -3.5724441064573 + -gammas + SOLUTION_RAW 16 Solution after simulation 1. + -temp 11 + -pressure 10 + -potential 0 + -total_h 22.135866361697 + -total_o 11.068757726907 + -cb -6.7997561691754e-17 + -density 0.99831968732863 + -totals + K 3.9260409219821e-05 + N 0.00023927986057314 + Na 0.00020001945135325 + -pH 7.0816246305188 + -pe 13.966528092735 + -mu 0.0012000859545714 + -ah2o 0.99995464840361 + -mass_water 0.19939988387738 + -soln_vol 0.19975821827742 + -total_alkalinity -6.7760981419119e-19 + -activities + E -13.966528092735 + H(0) -45.224831203736 + K -3.7226022594356 + N(-3) -64.071413252819 + N(0) -19.539412420616 + N(3) -15.917214058761 + N(5) -2.9377614291833 + Na -3.0152984089092 + O(0) -3.5724441064573 + -gammas + SOLUTION_RAW 17 Solution after simulation 1. + -temp 11 + -pressure 10 + -potential 0 + -total_h 22.135866361697 + -total_o 11.068757726907 + -cb -6.7997561691754e-17 + -density 0.99831968732863 + -totals + K 3.9260409219821e-05 + N 0.00023927986057314 + Na 0.00020001945135325 + -pH 7.0816246305188 + -pe 13.966528092735 + -mu 0.0012000859545714 + -ah2o 0.99995464840361 + -mass_water 0.19939988387738 + -soln_vol 0.19975821827742 + -total_alkalinity -6.7760981419119e-19 + -activities + E -13.966528092735 + H(0) -45.224831203736 + K -3.7226022594356 + N(-3) -64.071413252819 + N(0) -19.539412420616 + N(3) -15.917214058761 + N(5) -2.9377614291833 + Na -3.0152984089092 + O(0) -3.5724441064573 + -gammas + SOLUTION_RAW 18 Solution after simulation 1. + -temp 11 + -pressure 10 + -potential 0 + -total_h 22.135866361697 + -total_o 11.068757726907 + -cb -6.7997561691754e-17 + -density 0.99831968732863 + -totals + K 3.9260409219821e-05 + N 0.00023927986057314 + Na 0.00020001945135325 + -pH 7.0816246305188 + -pe 13.966528092735 + -mu 0.0012000859545714 + -ah2o 0.99995464840361 + -mass_water 0.19939988387738 + -soln_vol 0.19975821827742 + -total_alkalinity -6.7760981419119e-19 + -activities + E -13.966528092735 + H(0) -45.224831203736 + K -3.7226022594356 + N(-3) -64.071413252819 + N(0) -19.539412420616 + N(3) -15.917214058761 + N(5) -2.9377614291833 + Na -3.0152984089092 + O(0) -3.5724441064573 + -gammas + SOLUTION_RAW 19 Solution after simulation 1. + -temp 11 + -pressure 10 + -potential 0 + -total_h 22.135866361697 + -total_o 11.068757726907 + -cb -6.7997561691754e-17 + -density 0.99831968732863 + -totals + K 3.9260409219821e-05 + N 0.00023927986057314 + Na 0.00020001945135325 + -pH 7.0816246305188 + -pe 13.966528092735 + -mu 0.0012000859545714 + -ah2o 0.99995464840361 + -mass_water 0.19939988387738 + -soln_vol 0.19975821827742 + -total_alkalinity -6.7760981419119e-19 + -activities + E -13.966528092735 + H(0) -45.224831203736 + K -3.7226022594356 + N(-3) -64.071413252819 + N(0) -19.539412420616 + N(3) -15.917214058761 + N(5) -2.9377614291833 + Na -3.0152984089092 + O(0) -3.5724441064573 + -gammas + EXCHANGE_RAW 11 Exchange assemblage after simulation 1. + # EXCHANGE_MODIFY candidate identifiers # + -exchange_gammas 1 + -component X + # EXCHANGE_MODIFY candidate identifiers # + -totals + H 1.5569735071866e-64 + K 0.00011075000841372 + N 3.8924337679664e-65 + Na 0.0001092499916584 + X 0.00022000000007212 + -charge_balance 0 + -la 2.6946830556585 + -phase_proportion 0 + -formula_z 0 + # EXCHANGE_MODIFY candidates with new_def=true # + -new_def 0 + -solution_equilibria 0 + -n_solution -999 + # Exchange workspace variables # + -totals + EXCHANGE_RAW 12 Exchange assemblage after simulation 1. + # EXCHANGE_MODIFY candidate identifiers # + -exchange_gammas 1 + -component X + # EXCHANGE_MODIFY candidate identifiers # + -totals + H 1.5569735071866e-64 + K 0.00011075000841372 + N 3.8924337679664e-65 + Na 0.0001092499916584 + X 0.00022000000007212 + -charge_balance 0 + -la 2.6946830556585 + -phase_proportion 0 + -formula_z 0 + # EXCHANGE_MODIFY candidates with new_def=true # + -new_def 0 + -solution_equilibria 0 + -n_solution -999 + # Exchange workspace variables # + -totals + EXCHANGE_RAW 13 Exchange assemblage after simulation 1. + # EXCHANGE_MODIFY candidate identifiers # + -exchange_gammas 1 + -component X + # EXCHANGE_MODIFY candidate identifiers # + -totals + H 1.5569735071866e-64 + K 0.00011075000841372 + N 3.8924337679664e-65 + Na 0.0001092499916584 + X 0.00022000000007212 + -charge_balance 0 + -la 2.6946830556585 + -phase_proportion 0 + -formula_z 0 + # EXCHANGE_MODIFY candidates with new_def=true # + -new_def 0 + -solution_equilibria 0 + -n_solution -999 + # Exchange workspace variables # + -totals + EXCHANGE_RAW 14 Exchange assemblage after simulation 1. + # EXCHANGE_MODIFY candidate identifiers # + -exchange_gammas 1 + -component X + # EXCHANGE_MODIFY candidate identifiers # + -totals + H 1.5569735071866e-64 + K 0.00011075000841372 + N 3.8924337679664e-65 + Na 0.0001092499916584 + X 0.00022000000007212 + -charge_balance 0 + -la 2.6946830556585 + -phase_proportion 0 + -formula_z 0 + # EXCHANGE_MODIFY candidates with new_def=true # + -new_def 0 + -solution_equilibria 0 + -n_solution -999 + # Exchange workspace variables # + -totals + EXCHANGE_RAW 15 Exchange assemblage after simulation 1. + # EXCHANGE_MODIFY candidate identifiers # + -exchange_gammas 1 + -component X + # EXCHANGE_MODIFY candidate identifiers # + -totals + H 1.5569735071866e-64 + K 0.00011075000841372 + N 3.8924337679664e-65 + Na 0.0001092499916584 + X 0.00022000000007212 + -charge_balance 0 + -la 2.6946830556585 + -phase_proportion 0 + -formula_z 0 + # EXCHANGE_MODIFY candidates with new_def=true # + -new_def 0 + -solution_equilibria 0 + -n_solution -999 + # Exchange workspace variables # + -totals + EXCHANGE_RAW 16 Exchange assemblage after simulation 1. + # EXCHANGE_MODIFY candidate identifiers # + -exchange_gammas 1 + -component X + # EXCHANGE_MODIFY candidate identifiers # + -totals + H 1.5569735071866e-64 + K 0.00011075000841372 + N 3.8924337679664e-65 + Na 0.0001092499916584 + X 0.00022000000007212 + -charge_balance 0 + -la 2.6946830556585 + -phase_proportion 0 + -formula_z 0 + # EXCHANGE_MODIFY candidates with new_def=true # + -new_def 0 + -solution_equilibria 0 + -n_solution -999 + # Exchange workspace variables # + -totals + EXCHANGE_RAW 17 Exchange assemblage after simulation 1. + # EXCHANGE_MODIFY candidate identifiers # + -exchange_gammas 1 + -component X + # EXCHANGE_MODIFY candidate identifiers # + -totals + H 1.5569735071866e-64 + K 0.00011075000841372 + N 3.8924337679664e-65 + Na 0.0001092499916584 + X 0.00022000000007212 + -charge_balance 0 + -la 2.6946830556585 + -phase_proportion 0 + -formula_z 0 + # EXCHANGE_MODIFY candidates with new_def=true # + -new_def 0 + -solution_equilibria 0 + -n_solution -999 + # Exchange workspace variables # + -totals + EXCHANGE_RAW 18 Exchange assemblage after simulation 1. + # EXCHANGE_MODIFY candidate identifiers # + -exchange_gammas 1 + -component X + # EXCHANGE_MODIFY candidate identifiers # + -totals + H 1.5569735071866e-64 + K 0.00011075000841372 + N 3.8924337679664e-65 + Na 0.0001092499916584 + X 0.00022000000007212 + -charge_balance 0 + -la 2.6946830556585 + -phase_proportion 0 + -formula_z 0 + # EXCHANGE_MODIFY candidates with new_def=true # + -new_def 0 + -solution_equilibria 0 + -n_solution -999 + # Exchange workspace variables # + -totals + EXCHANGE_RAW 19 Exchange assemblage after simulation 1. + # EXCHANGE_MODIFY candidate identifiers # + -exchange_gammas 1 + -component X + # EXCHANGE_MODIFY candidate identifiers # + -totals + H 1.5569735071866e-64 + K 0.00011075000841372 + N 3.8924337679664e-65 + Na 0.0001092499916584 + X 0.00022000000007212 + -charge_balance 0 + -la 2.6946830556585 + -phase_proportion 0 + -formula_z 0 + # EXCHANGE_MODIFY candidates with new_def=true # + -new_def 0 + -solution_equilibria 0 + -n_solution -999 + # Exchange workspace variables # + -totals diff --git a/Tests/Output/AdvectBMI_f90.yaml b/Tests/Output/AdvectBMI_f90.yaml new file mode 100644 index 000000000..bf6138ba4 --- /dev/null +++ b/Tests/Output/AdvectBMI_f90.yaml @@ -0,0 +1,1131 @@ +SetGridCellCount: 40 +SetErrorHandlerMode: 1 +SetComponentH2O: false +SetRebalanceFraction: 0.5 +SetRebalanceByCell: true +UseSolutionDensityVolume: false +SetPartitionUZSolids: false +SetFilePrefix: AdvectBMI_f90 +OpenFiles: "" +SetUnitsSolution: 2 +SetUnitsPPassemblage: 1 +SetUnitsExchange: 1 +SetUnitsSurface: 1 +SetUnitsGasPhase: 1 +SetUnitsSSassemblage: 1 +SetUnitsKinetics: 1 +SetTimeConversion: 1.1574074074074073e-05 +SetRepresentativeVolume: + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 +SetDensity: + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 +SetPorosity: + - 0.20000000000000001 + - 0.20000000000000001 + - 0.20000000000000001 + - 0.20000000000000001 + - 0.20000000000000001 + - 0.20000000000000001 + - 0.20000000000000001 + - 0.20000000000000001 + - 0.20000000000000001 + - 0.20000000000000001 + - 0.20000000000000001 + - 0.20000000000000001 + - 0.20000000000000001 + - 0.20000000000000001 + - 0.20000000000000001 + - 0.20000000000000001 + - 0.20000000000000001 + - 0.20000000000000001 + - 0.20000000000000001 + - 0.20000000000000001 + - 0.20000000000000001 + - 0.20000000000000001 + - 0.20000000000000001 + - 0.20000000000000001 + - 0.20000000000000001 + - 0.20000000000000001 + - 0.20000000000000001 + - 0.20000000000000001 + - 0.20000000000000001 + - 0.20000000000000001 + - 0.20000000000000001 + - 0.20000000000000001 + - 0.20000000000000001 + - 0.20000000000000001 + - 0.20000000000000001 + - 0.20000000000000001 + - 0.20000000000000001 + - 0.20000000000000001 + - 0.20000000000000001 + - 0.20000000000000001 +SetSaturation: + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 +SetPrintChemistryMask: + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 + - 0 +CreateMapping: + - 0 + - 1 + - 2 + - 3 + - 4 + - 5 + - 6 + - 7 + - 8 + - 9 + - 10 + - 11 + - 12 + - 13 + - 14 + - 15 + - 16 + - 17 + - 18 + - 19 + - 0 + - 1 + - 2 + - 3 + - 4 + - 5 + - 6 + - 7 + - 8 + - 9 + - 10 + - 11 + - 12 + - 13 + - 14 + - 15 + - 16 + - 17 + - 18 + - 19 +SetPrintChemistryOn: + workers: false + initial_phreeqc: true + utility: false +LoadDatabase: phreeqc.dat +RunFile: + workers: true + initial_phreeqc: true + utility: true + chemistry_name: advect.pqi +RunString: + workers: true + initial_phreeqc: false + utility: true + input_string: DELETE; -all +FindComponents: "" +InitialPhreeqc2Module: + ic1: + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + ic2: + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + f1: + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 +InitialPhreeqcCell2Module: + n: -1 + cell_numbers: + - 18 + - 19 +SetTimeStep: 86400 +SetTime: 0 +RunCells: "" \ No newline at end of file diff --git a/Tests/Output/AdvectBMI_py.yaml b/Tests/Output/AdvectBMI_py.yaml new file mode 100644 index 000000000..8f6a5ac46 --- /dev/null +++ b/Tests/Output/AdvectBMI_py.yaml @@ -0,0 +1,1131 @@ +SetGridCellCount: 40 +SetErrorHandlerMode: 1 +SetComponentH2O: false +SetRebalanceFraction: 0.5 +SetRebalanceByCell: true +UseSolutionDensityVolume: false +SetPartitionUZSolids: false +SetFilePrefix: AdvectBMI_py +OpenFiles: '' +SetUnitsSolution: 2 +SetUnitsPPassemblage: 1 +SetUnitsExchange: 1 +SetUnitsSurface: 1 +SetUnitsGasPhase: 1 +SetUnitsSSassemblage: 1 +SetUnitsKinetics: 1 +SetTimeConversion: 1.1574074074074073e-05 +SetRepresentativeVolume: +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +SetDensity: +- 1.0 +- 1.0 +- 1.0 +- 1.0 +- 1.0 +- 1.0 +- 1.0 +- 1.0 +- 1.0 +- 1.0 +- 1.0 +- 1.0 +- 1.0 +- 1.0 +- 1.0 +- 1.0 +- 1.0 +- 1.0 +- 1.0 +- 1.0 +- 1.0 +- 1.0 +- 1.0 +- 1.0 +- 1.0 +- 1.0 +- 1.0 +- 1.0 +- 1.0 +- 1.0 +- 1.0 +- 1.0 +- 1.0 +- 1.0 +- 1.0 +- 1.0 +- 1.0 +- 1.0 +- 1.0 +- 1.0 +SetPorosity: +- 0.2 +- 0.2 +- 0.2 +- 0.2 +- 0.2 +- 0.2 +- 0.2 +- 0.2 +- 0.2 +- 0.2 +- 0.2 +- 0.2 +- 0.2 +- 0.2 +- 0.2 +- 0.2 +- 0.2 +- 0.2 +- 0.2 +- 0.2 +- 0.2 +- 0.2 +- 0.2 +- 0.2 +- 0.2 +- 0.2 +- 0.2 +- 0.2 +- 0.2 +- 0.2 +- 0.2 +- 0.2 +- 0.2 +- 0.2 +- 0.2 +- 0.2 +- 0.2 +- 0.2 +- 0.2 +- 0.2 +SetSaturation: +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +SetPrintChemistryMask: +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 1 +- 0 +- 0 +- 0 +- 0 +- 0 +- 0 +- 0 +- 0 +- 0 +- 0 +- 0 +- 0 +- 0 +- 0 +- 0 +- 0 +- 0 +- 0 +- 0 +- 0 +CreateMapping: +- 0 +- 1 +- 2 +- 3 +- 4 +- 5 +- 6 +- 7 +- 8 +- 9 +- 10 +- 11 +- 12 +- 13 +- 14 +- 15 +- 16 +- 17 +- 18 +- 19 +- 0 +- 1 +- 2 +- 3 +- 4 +- 5 +- 6 +- 7 +- 8 +- 9 +- 10 +- 11 +- 12 +- 13 +- 14 +- 15 +- 16 +- 17 +- 18 +- 19 +SetPrintChemistryOn: + workers: false + initial_phreeqc: true + utility: false +LoadDatabase: phreeqc.dat +RunFile: + workers: true + initial_phreeqc: true + utility: true + chemistry_name: advect.pqi +RunString: + workers: true + initial_phreeqc: false + utility: true + input_string: DELETE; -all +FindComponents: '' +InitialPhreeqc2Module_mix: + ic1: + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + ic2: + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + - -1 + f1: + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 + - 1 +InitialPhreeqcCell2Module: + n: -1 + cell_numbers: + - 18 + - 19 +SetTimeStep: 86400.0 +SetTime: 0.0 +RunCells: '' diff --git a/Tests/Output/Advect_c.chem.txt b/Tests/Output/Advect_c.chem.txt index f4972a3f8..ee30eea15 100644 --- a/Tests/Output/Advect_c.chem.txt +++ b/Tests/Output/Advect_c.chem.txt @@ -196,7 +196,7 @@ Reading input data for simulation 4. ------------------------------------ ------------------------------- -End of Run after 4.574 Seconds. +End of Run after 0.655 Seconds. ------------------------------- Number of threads: 3 @@ -270,10 +270,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.800e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = -4.978e-22 + Total alkalinity (eq/kg) = -8.678e-21 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = 1.075e-18 + Electrical balance (eq) = 1.077e-18 Percent error, 100*(Cat-|An|)/(Cat+|An|) = 0.00 Iterations = 2 Total H = 2.213642e+01 @@ -324,7 +324,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 4.889 Seconds. +End of Run after 0.682 Seconds. ------------------------------- Time: 10 @@ -382,10 +382,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.800e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = -1.954e-19 + Total alkalinity (eq/kg) = -5.106e-20 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = 8.407e-19 + Electrical balance (eq) = 7.850e-19 Percent error, 100*(Cat-|An|)/(Cat+|An|) = 0.00 Iterations = 5 Total H = 2.213642e+01 @@ -436,7 +436,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 4.894 Seconds. +End of Run after 0.682 Seconds. ------------------------------- Time: 10 @@ -494,10 +494,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.800e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = 1.656e-19 + Total alkalinity (eq/kg) = 3.834e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = 8.968e-19 + Electrical balance (eq) = 8.537e-19 Percent error, 100*(Cat-|An|)/(Cat+|An|) = 0.00 Iterations = 6 Total H = 2.213642e+01 @@ -548,7 +548,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 4.898 Seconds. +End of Run after 0.682 Seconds. ------------------------------- Time: 10 @@ -606,10 +606,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.800e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = 1.009e-18 + Total alkalinity (eq/kg) = 1.771e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = 5.877e-18 + Electrical balance (eq) = 6.041e-18 Percent error, 100*(Cat-|An|)/(Cat+|An|) = 0.00 Iterations = 6 Total H = 2.213642e+01 @@ -660,7 +660,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 4.902 Seconds. +End of Run after 0.683 Seconds. ------------------------------- Time: 10 @@ -718,7 +718,7 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.758e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = 5.691e-19 + Total alkalinity (eq/kg) = 5.826e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 Electrical balance (eq) = 2.786e-16 @@ -772,7 +772,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 4.906 Seconds. +End of Run after 0.683 Seconds. ------------------------------- Time: 10 @@ -830,7 +830,7 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.211e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = -4.274e-19 + Total alkalinity (eq/kg) = 3.295e-20 Temperature (°C) = 20.00 Pressure (atm) = 2.00 Electrical balance (eq) = 9.176e-14 @@ -884,7 +884,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 4.889 Seconds. +End of Run after 0.682 Seconds. ------------------------------- Time: 10 @@ -942,7 +942,7 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.200e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = -1.274e-19 + Total alkalinity (eq/kg) = 7.751e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 Electrical balance (eq) = -7.020e-16 @@ -996,7 +996,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 4.894 Seconds. +End of Run after 0.682 Seconds. ------------------------------- Time: 10 @@ -1054,7 +1054,7 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.200e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = 4.509e-18 + Total alkalinity (eq/kg) = 4.523e-18 Temperature (°C) = 20.00 Pressure (atm) = 2.00 Electrical balance (eq) = 7.519e-13 @@ -1108,7 +1108,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 4.898 Seconds. +End of Run after 0.682 Seconds. ------------------------------- Time: 10 @@ -1166,7 +1166,7 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.200e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = 1.023e-18 + Total alkalinity (eq/kg) = 6.863e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 Electrical balance (eq) = 1.445e-13 @@ -1220,7 +1220,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 4.902 Seconds. +End of Run after 0.683 Seconds. ------------------------------- Time: 10 @@ -1276,10 +1276,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.200e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = -9.905e-19 + Total alkalinity (eq/kg) = -1.143e-18 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = -1.555e-17 + Electrical balance (eq) = -1.553e-17 Percent error, 100*(Cat-|An|)/(Cat+|An|) = -0.00 Iterations = 2 Total H = 2.213642e+01 @@ -1327,7 +1327,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 4.907 Seconds. +End of Run after 0.683 Seconds. ------------------------------- Time: 10 @@ -1442,7 +1442,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 4.889 Seconds. +End of Run after 0.682 Seconds. ------------------------------- Time: 10 @@ -1557,7 +1557,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 4.894 Seconds. +End of Run after 0.682 Seconds. ------------------------------- Time: 10 @@ -1672,7 +1672,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 4.898 Seconds. +End of Run after 0.682 Seconds. ------------------------------- Time: 10 @@ -1787,7 +1787,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 4.902 Seconds. +End of Run after 0.683 Seconds. ------------------------------- Time: 10 @@ -1902,7 +1902,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 4.906 Seconds. +End of Run after 0.683 Seconds. ------------------------------- Time: 10 @@ -2017,7 +2017,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 4.909 Seconds. +End of Run after 0.684 Seconds. ------------------------------- Time: 10 @@ -2132,7 +2132,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 4.911 Seconds. +End of Run after 0.684 Seconds. ------------------------------- Time: 10 @@ -2247,7 +2247,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 4.914 Seconds. +End of Run after 0.685 Seconds. ------------------------------- Time: 10 @@ -2362,7 +2362,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 4.916 Seconds. +End of Run after 0.686 Seconds. ------------------------------- Time: 10 @@ -2477,6 +2477,6 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 4.918 Seconds. +End of Run after 0.686 Seconds. ------------------------------- diff --git a/Tests/Output/Advect_c.dmp b/Tests/Output/Advect_c.dmp index 97caaac7e..e30ba2344 100644 --- a/Tests/Output/Advect_c.dmp +++ b/Tests/Output/Advect_c.dmp @@ -4,7 +4,7 @@ -potential 0 -total_h 22.136415505852 -total_o 11.068314447308 - -cb 1.075129655527e-18 + -cb 1.0767509295276e-18 -density 0.99830524784931 -totals Ca 0.0001196428982687 @@ -17,7 +17,7 @@ -ah2o 0.99996484900903 -mass_water 0.19940483056363 -soln_vol 0.19975835757967 - -total_alkalinity -9.9261673506363e-23 + -total_alkalinity -1.7304618414609e-21 -activities Ca -3.3018013654974 Cl -2.9412141501733 @@ -33,24 +33,24 @@ -potential 0 -total_h 22.136415505852 -total_o 11.068314447308 - -cb 8.4070997865194e-19 + -cb 7.8499109259037e-19 -density 0.9983052478494 -totals Ca 0.00011964289180093 Cl 0.00023928579659614 K 1.2994194764655e-11 Na 8.48195644157e-17 - -pH 7.078796049857 - -pe 13.969354457274 + -pH 7.0787960498574 + -pe 13.969354457273 -mu 0.0018000850370259 -ah2o 0.99996484900848 -mass_water 0.19940483056363 -soln_vol 0.19975835757989 - -total_alkalinity -3.8966824296148e-20 + -total_alkalinity -1.0180938979303e-20 -activities Ca -3.3018013883042 Cl -2.9412141499986 - E -13.969354457274 + E -13.969354457273 H(0) -45.22482677149 K -10.206420504589 Na -15.391397091764 @@ -62,20 +62,20 @@ -potential 0 -total_h 22.136415505852 -total_o 11.068314447308 - -cb 8.9683583757489e-19 + -cb 8.5365370087717e-19 -density 0.99830524786079 -totals Ca 0.00011964204834122 Cl 0.00023928579659614 K 1.6998083051542e-09 Na 1.0538874982917e-13 - -pH 7.0787960691285 + -pH 7.078796069129 -pe 13.96935443791 -mu 0.0018000808071463 -ah2o 0.99996484893657 -mass_water 0.19940483056363 -soln_vol 0.19975835760982 - -total_alkalinity 3.3030976220468e-20 + -total_alkalinity 7.6461267101952e-20 -activities Ca -3.3018043625499 Cl -2.9412141272248 @@ -91,24 +91,24 @@ -potential 0 -total_h 22.136415505852 -total_o 11.068314447308 - -cb 5.876535917038e-18 + -cb 6.0411713287157e-18 -density 0.99830524888929 -totals Ca 0.00011955337889516 Cl 0.00023928579659614 K 1.7891515852047e-07 Na 1.2364729922871e-10 - -pH 7.0787980954878 - -pe 13.969352402078 + -pH 7.0787980954857 + -pe 13.96935240208 -mu 0.0017996361373178 -ah2o 0.99996484137719 -mass_water 0.19940483056363 -soln_vol 0.1997583607882 - -total_alkalinity 2.012894389811e-19 + -total_alkalinity 3.5317303433564e-20 -activities Ca -3.3021171525641 Cl -2.9412117329418 - E -13.969352402078 + E -13.96935240208 H(0) -45.224826752359 K -6.0675203126446 Na -9.2277061356486 @@ -120,7 +120,7 @@ -potential 0 -total_h 22.136415505852 -total_o 11.068314447308 - -cb 2.7860479322657e-16 + -cb 2.7860065401479e-16 -density 0.99830534209357 -totals Ca 0.00011133610379508 @@ -133,7 +133,7 @@ -ah2o 0.9999641408255 -mass_water 0.19940483056391 -soln_vol 0.19975865369868 - -total_alkalinity 1.1347594515247e-19 + -total_alkalinity 1.161725539494e-19 -activities Ca -3.3321851919421 Cl -2.9409884191375 @@ -143,6 +143,35 @@ Na -6.1756188689826 O(0) -3.5724482762599 -gammas + SOLUTION_RAW 5 Solution after simulation 1. + -temp 20 + -pressure 2 + -potential 0 + -total_h 22.136415505852 + -total_o 11.068314447308 + -cb 9.1760266061123e-14 + -density 0.99830599410147 + -totals + Ca 2.1235996941319e-06 + Cl 0.00023928579659881 + K 0.00021202857277487 + Na 2.3010024527435e-05 + -pH 7.0815725817856 + -pe 13.96656536728 + -mu 0.0012107356299958 + -ah2o 0.9999548300763 + -mass_water 0.19940483056784 + -soln_vol 0.19976232479367 + -total_alkalinity 6.5711227861213e-21 + -activities + Ca -5.0390564336999 + Cl -2.9376960035395 + E -13.96656536728 + H(0) -45.22480165536 + K -2.9902450425097 + Na -3.9545342945889 + O(0) -3.572503045403 + -gammas EXCHANGE_RAW 0 Exchange assemblage after simulation 1. # EXCHANGE_MODIFY candidate identifiers # -exchange_gammas 1 @@ -150,8 +179,8 @@ # EXCHANGE_MODIFY candidate identifiers # -totals Ca 0.00011000000007735 - K 5.5789786827676e-15 - Na 9.2458165879821e-22 + K 5.5789786827677e-15 + Na 9.2458165879822e-22 X 0.00022000000016027 -charge_balance 0 -la 1.2218455551817 @@ -209,10 +238,10 @@ -component X # EXCHANGE_MODIFY candidate identifiers # -totals - Ca 0.00010999150115391 + Ca 0.00010999150115392 K 1.6995489880192e-08 Na 2.2742149190083e-12 - X 0.00022000000007192 + X 0.00022000000007193 -charge_balance 0 -la 1.2219913122299 -phase_proportion 0 @@ -243,59 +272,50 @@ -n_solution -999 # Exchange workspace variables # -totals - SOLUTION_RAW 5 Solution after simulation 1. - -temp 20 - -pressure 2 - -potential 0 - -total_h 22.136415505852 - -total_o 11.068314447308 - -cb 9.1760637207138e-14 - -density 0.99830599410147 + EXCHANGE_RAW 5 Exchange assemblage after simulation 1. + # EXCHANGE_MODIFY candidate identifiers # + -exchange_gammas 1 + -component X + # EXCHANGE_MODIFY candidate identifiers # + -totals + Ca 5.5298103954096e-05 + K 0.0001071522289845 + Na 2.2515631794498e-06 + X 0.00022000000007215 + -charge_balance 0 + -la 1.9479117008937 + -phase_proportion 0 + -formula_z 0 + # EXCHANGE_MODIFY candidates with new_def=true # + -new_def 0 + -solution_equilibria 0 + -n_solution -999 + # Exchange workspace variables # -totals - Ca 2.1235996941319e-06 - Cl 0.00023928579659881 - K 0.00021202857277487 - Na 2.3010024527435e-05 - -pH 7.0815725817844 - -pe 13.966565367281 - -mu 0.0012107356299958 - -ah2o 0.9999548300763 - -mass_water 0.19940483056784 - -soln_vol 0.19976232479367 - -total_alkalinity -8.5219455427663e-20 - -activities - Ca -5.0390564336998 - Cl -2.9376960035395 - E -13.966565367281 - H(0) -45.22480165536 - K -2.9902450425097 - Na -3.9545342945889 - O(0) -3.572503045403 - -gammas SOLUTION_RAW 6 Solution after simulation 1. -temp 20 -pressure 2 -potential 0 -total_h 22.136415505852 -total_o 11.068314447308 - -cb -7.0203244750827e-16 + -cb -7.0195979788943e-16 -density 0.99830319084416 -totals Ca 2.9884729799544e-11 Cl 0.00023928579659614 K 0.00011419229852628 Na 0.0001250934382997 - -pH 7.081624629655 - -pe 13.966513092484 + -pH 7.0816246296573 + -pe 13.966513092481 -mu 0.001200086104411 -ah2o 0.99995464903458 -mass_water 0.19940483056793 -soln_vol 0.19976131924323 - -total_alkalinity -2.5397753527828e-20 + -total_alkalinity 1.5456366053921e-19 -activities Ca -9.8904037600017 Cl -2.9376246522544 - E -13.966513092484 + E -13.966513092481 H(0) -45.224801201506 K -3.2589310415102 Na -3.2191468857418 @@ -307,20 +327,20 @@ -potential 0 -total_h 22.136415505852 -total_o 11.068314447308 - -cb 7.519447178337e-13 + -cb 7.519447164672e-13 -density 0.99830135805566 -totals Ca 1.7725778408102e-17 Cl 0.00023928579659619 K 4.8038347521371e-05 Na 0.00019124744982673 - -pH 7.0816246304016 + -pH 7.0816246304017 -pe 13.966513091736 -mu 0.0012000859564291 -ah2o 0.99995464903197 -mass_water 0.19940483056793 -soln_vol 0.19976061828731 - -total_alkalinity 8.9918833923699e-19 + -total_alkalinity 9.0192134398087e-19 -activities Ca -16.117247773866 Cl -2.9376246512605 @@ -336,20 +356,20 @@ -potential 0 -total_h 22.136415505852 -total_o 11.068314447308 - -cb 1.4446884162311e-13 + -cb 1.4446890227531e-13 -density 0.99830112934291 -totals Ca 3.5591651400101e-24 Cl 0.0002392857965962 K 3.9783056143054e-05 Na 0.00019950274059762 - -pH 7.0816246303934 + -pH 7.0816246303925 -pe 13.966513091746 -mu 0.0012000859549058 -ah2o 0.99995464903202 -mass_water 0.19940483056793 -soln_vol 0.19976053081559 - -total_alkalinity 2.0394965183107e-19 + -total_alkalinity 1.3685868670812e-19 -activities Ca -22.814504950571 Cl -2.9376246512502 @@ -365,19 +385,19 @@ -potential 0 -total_h 22.136415505852 -total_o 11.068314447393 - -cb -1.5547240116016e-17 + -cb -1.5532063006137e-17 -density 0.99830111534334 -totals Cl 0.00023928579659624 K 3.9277732064696e-05 Na 0.00020000806453153 - -pH 7.0816246303892 + -pH 7.0816246303888 -pe 13.966513177943 -mu 0.0012000859545433 -ah2o 0.99995464902842 -mass_water 0.19940483056793 -soln_vol 0.19976052546253 - -total_alkalinity -1.9751087794296e-19 + -total_alkalinity -2.2786509770121e-19 -activities Cl -2.9376246512477 E -13.966513177943 @@ -386,33 +406,73 @@ Na -3.0153339071739 O(0) -3.5725037484386 -gammas - EXCHANGE_RAW 5 Exchange assemblage after simulation 1. - # EXCHANGE_MODIFY candidate identifiers # - -exchange_gammas 1 - -component X - # EXCHANGE_MODIFY candidate identifiers # - -totals - Ca 5.5298103954097e-05 - K 0.0001071522289845 - Na 2.2515631794498e-06 - X 0.00022000000007215 - -charge_balance 0 - -la 1.9479117008937 - -phase_proportion 0 - -formula_z 0 - # EXCHANGE_MODIFY candidates with new_def=true # - -new_def 0 - -solution_equilibria 0 - -n_solution -999 - # Exchange workspace variables # + SOLUTION_RAW 10 Solution after simulation 1. + -temp 20 + -pressure 2 + -potential 0 + -total_h 22.135866361697 + -total_o 11.068757726907 + -cb -6.7902654296992e-17 + -density 0.99831968732863 -totals + K 3.9260409219821e-05 + N 0.00023927986057314 + Na 0.00020001945135325 + -pH 7.0816246305178 + -pe 13.966528092736 + -mu 0.0012000859545714 + -ah2o 0.99995464840361 + -mass_water 0.19939988387738 + -soln_vol 0.19975821827742 + -total_alkalinity -7.5900107774396e-19 + -activities + E -13.966528092736 + H(0) -45.224831203736 + K -3.7226022594356 + N(-3) -64.071413252819 + N(0) -19.539412420617 + N(3) -15.917214058761 + N(5) -2.9377614291833 + Na -3.0152984089092 + O(0) -3.5724441064573 + -gammas + SOLUTION_RAW 11 Solution after simulation 1. + -temp 20 + -pressure 2 + -potential 0 + -total_h 22.135866361697 + -total_o 11.068757726907 + -cb -6.7902654296992e-17 + -density 0.99831968732863 + -totals + K 3.9260409219821e-05 + N 0.00023927986057314 + Na 0.00020001945135325 + -pH 7.0816246305178 + -pe 13.966528092736 + -mu 0.0012000859545714 + -ah2o 0.99995464840361 + -mass_water 0.19939988387738 + -soln_vol 0.19975821827742 + -total_alkalinity -7.5900107774396e-19 + -activities + E -13.966528092736 + H(0) -45.224831203736 + K -3.7226022594356 + N(-3) -64.071413252819 + N(0) -19.539412420617 + N(3) -15.917214058761 + N(5) -2.9377614291833 + Na -3.0152984089092 + O(0) -3.5724441064573 + -gammas EXCHANGE_RAW 6 Exchange assemblage after simulation 1. # EXCHANGE_MODIFY candidate identifiers # -exchange_gammas 1 -component X # EXCHANGE_MODIFY candidate identifiers # -totals - Ca 7.6966419082244e-09 + Ca 7.6966419082243e-09 K 0.00018148921301107 Na 3.8495393844372e-05 X 0.00022000000013926 @@ -485,66 +545,48 @@ -n_solution -999 # Exchange workspace variables # -totals - SOLUTION_RAW 10 Solution after simulation 1. - -temp 20 - -pressure 2 - -potential 0 - -total_h 22.135866361697 - -total_o 11.068757726907 - -cb -6.7902654296992e-17 - -density 0.99831968732863 + EXCHANGE_RAW 10 Exchange assemblage after simulation 1. + # EXCHANGE_MODIFY candidate identifiers # + -exchange_gammas 1 + -component X + # EXCHANGE_MODIFY candidate identifiers # + -totals + H 1.556973507194e-64 + K 0.00011075000841372 + N 3.8924337679849e-65 + Na 0.0001092499916584 + X 0.00022000000007212 + -charge_balance 0 + -la 2.6946830556585 + -phase_proportion 0 + -formula_z 0 + # EXCHANGE_MODIFY candidates with new_def=true # + -new_def 0 + -solution_equilibria 0 + -n_solution -999 + # Exchange workspace variables # -totals - K 3.9260409219821e-05 - N 0.00023927986057314 - Na 0.00020001945135325 - -pH 7.0816246305178 - -pe 13.966528092736 - -mu 0.0012000859545714 - -ah2o 0.99995464840361 - -mass_water 0.19939988387738 - -soln_vol 0.19975821827742 - -total_alkalinity -7.5900107774396e-19 - -activities - E -13.966528092736 - H(0) -45.224831203736 - K -3.7226022594356 - N(-3) -64.071413252819 - N(0) -19.539412420617 - N(3) -15.917214058761 - N(5) -2.9377614291833 - Na -3.0152984089092 - O(0) -3.5724441064573 - -gammas - SOLUTION_RAW 11 Solution after simulation 1. - -temp 20 - -pressure 2 - -potential 0 - -total_h 22.135866361697 - -total_o 11.068757726907 - -cb -6.7902654296992e-17 - -density 0.99831968732863 + EXCHANGE_RAW 11 Exchange assemblage after simulation 1. + # EXCHANGE_MODIFY candidate identifiers # + -exchange_gammas 1 + -component X + # EXCHANGE_MODIFY candidate identifiers # + -totals + H 1.556973507194e-64 + K 0.00011075000841372 + N 3.8924337679849e-65 + Na 0.0001092499916584 + X 0.00022000000007212 + -charge_balance 0 + -la 2.6946830556585 + -phase_proportion 0 + -formula_z 0 + # EXCHANGE_MODIFY candidates with new_def=true # + -new_def 0 + -solution_equilibria 0 + -n_solution -999 + # Exchange workspace variables # -totals - K 3.9260409219821e-05 - N 0.00023927986057314 - Na 0.00020001945135325 - -pH 7.0816246305178 - -pe 13.966528092736 - -mu 0.0012000859545714 - -ah2o 0.99995464840361 - -mass_water 0.19939988387738 - -soln_vol 0.19975821827742 - -total_alkalinity -7.5900107774396e-19 - -activities - E -13.966528092736 - H(0) -45.224831203736 - K -3.7226022594356 - N(-3) -64.071413252819 - N(0) -19.539412420617 - N(3) -15.917214058761 - N(5) -2.9377614291833 - Na -3.0152984089092 - O(0) -3.5724441064573 - -gammas SOLUTION_RAW 12 Solution after simulation 1. -temp 20 -pressure 2 @@ -785,48 +827,6 @@ Na -3.0152984089092 O(0) -3.5724441064573 -gammas - EXCHANGE_RAW 10 Exchange assemblage after simulation 1. - # EXCHANGE_MODIFY candidate identifiers # - -exchange_gammas 1 - -component X - # EXCHANGE_MODIFY candidate identifiers # - -totals - H 1.556973507194e-64 - K 0.00011075000841372 - N 3.892433767985e-65 - Na 0.0001092499916584 - X 0.00022000000007212 - -charge_balance 0 - -la 2.6946830556585 - -phase_proportion 0 - -formula_z 0 - # EXCHANGE_MODIFY candidates with new_def=true # - -new_def 0 - -solution_equilibria 0 - -n_solution -999 - # Exchange workspace variables # - -totals - EXCHANGE_RAW 11 Exchange assemblage after simulation 1. - # EXCHANGE_MODIFY candidate identifiers # - -exchange_gammas 1 - -component X - # EXCHANGE_MODIFY candidate identifiers # - -totals - H 1.556973507194e-64 - K 0.00011075000841372 - N 3.892433767985e-65 - Na 0.0001092499916584 - X 0.00022000000007212 - -charge_balance 0 - -la 2.6946830556585 - -phase_proportion 0 - -formula_z 0 - # EXCHANGE_MODIFY candidates with new_def=true # - -new_def 0 - -solution_equilibria 0 - -n_solution -999 - # Exchange workspace variables # - -totals EXCHANGE_RAW 12 Exchange assemblage after simulation 1. # EXCHANGE_MODIFY candidate identifiers # -exchange_gammas 1 @@ -835,7 +835,7 @@ -totals H 1.556973507194e-64 K 0.00011075000841372 - N 3.892433767985e-65 + N 3.8924337679849e-65 Na 0.0001092499916584 X 0.00022000000007212 -charge_balance 0 @@ -856,7 +856,7 @@ -totals H 1.556973507194e-64 K 0.00011075000841372 - N 3.892433767985e-65 + N 3.8924337679849e-65 Na 0.0001092499916584 X 0.00022000000007212 -charge_balance 0 @@ -877,7 +877,7 @@ -totals H 1.556973507194e-64 K 0.00011075000841372 - N 3.892433767985e-65 + N 3.8924337679849e-65 Na 0.0001092499916584 X 0.00022000000007212 -charge_balance 0 @@ -898,7 +898,7 @@ -totals H 1.556973507194e-64 K 0.00011075000841372 - N 3.892433767985e-65 + N 3.8924337679849e-65 Na 0.0001092499916584 X 0.00022000000007212 -charge_balance 0 @@ -919,7 +919,7 @@ -totals H 1.556973507194e-64 K 0.00011075000841372 - N 3.892433767985e-65 + N 3.8924337679849e-65 Na 0.0001092499916584 X 0.00022000000007212 -charge_balance 0 @@ -940,7 +940,7 @@ -totals H 1.556973507194e-64 K 0.00011075000841372 - N 3.892433767985e-65 + N 3.8924337679849e-65 Na 0.0001092499916584 X 0.00022000000007212 -charge_balance 0 @@ -961,7 +961,7 @@ -totals H 1.556973507194e-64 K 0.00011075000841372 - N 3.892433767985e-65 + N 3.8924337679849e-65 Na 0.0001092499916584 X 0.00022000000007212 -charge_balance 0 @@ -982,7 +982,7 @@ -totals H 1.556973507194e-64 K 0.00011075000841372 - N 3.892433767985e-65 + N 3.8924337679849e-65 Na 0.0001092499916584 X 0.00022000000007212 -charge_balance 0 diff --git a/Tests/Output/Advect_c_utility.txt b/Tests/Output/Advect_c_utility.txt index 6a7243e1c..773079caf 100644 --- a/Tests/Output/Advect_c_utility.txt +++ b/Tests/Output/Advect_c_utility.txt @@ -37,10 +37,10 @@ Using solution 1. Activity of water = 1.000 Ionic strength (mol/kgw) = 1.500e-03 Mass of water (kg) = 9.970e-01 - Total alkalinity (eq/kg) = -7.786e-19 + Total alkalinity (eq/kg) = -5.652e-19 Temperature (°C) = 15.00 Pressure (atm) = 3.00 - Electrical balance (eq) = -3.611e-17 + Electrical balance (eq) = -3.644e-17 Percent error, 100*(Cat-|An|)/(Cat+|An|) = -0.00 Iterations = 12 Total H = 1.106821e+02 @@ -90,7 +90,7 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 5.66 Seconds. ------------------------------- +------------------------------- +End of Run after 0.716 Seconds. +------------------------------- diff --git a/Tests/Output/Advect_cpp.chem.txt b/Tests/Output/Advect_cpp.chem.txt index 9acd85432..93a096805 100644 --- a/Tests/Output/Advect_cpp.chem.txt +++ b/Tests/Output/Advect_cpp.chem.txt @@ -196,7 +196,7 @@ Reading input data for simulation 4. ------------------------------------ ------------------------------- -End of Run after 2.278 Seconds. +End of Run after 0.246 Seconds. ------------------------------- Database: phreeqc.dat @@ -246,7 +246,7 @@ Reading input data for simulation 5. ------------------------------------ ------------------------------- -End of Run after 1.092 Seconds. +End of Run after 0.096 Seconds. ------------------------------- 9.246e-22 4.203e-18 -0.020 @@ -270,10 +270,10 @@ End of Run after 1.092 Seconds. Activity of water = 1.000 Ionic strength (mol/kgw) = 1.800e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = -4.978e-22 + Total alkalinity (eq/kg) = -8.678e-21 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = 1.075e-18 + Electrical balance (eq) = 1.077e-18 Percent error, 100*(Cat-|An|)/(Cat+|An|) = 0.00 Iterations = 2 Total H = 2.213642e+01 @@ -324,7 +324,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 2.645 Seconds. +End of Run after 0.269 Seconds. ------------------------------- Time: 10 @@ -382,10 +382,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.800e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = -1.954e-19 + Total alkalinity (eq/kg) = -5.106e-20 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = 8.407e-19 + Electrical balance (eq) = 7.850e-19 Percent error, 100*(Cat-|An|)/(Cat+|An|) = 0.00 Iterations = 5 Total H = 2.213642e+01 @@ -436,7 +436,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 2.649 Seconds. +End of Run after 0.269 Seconds. ------------------------------- Time: 10 @@ -494,10 +494,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.800e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = 1.656e-19 + Total alkalinity (eq/kg) = 3.834e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = 8.968e-19 + Electrical balance (eq) = 8.537e-19 Percent error, 100*(Cat-|An|)/(Cat+|An|) = 0.00 Iterations = 6 Total H = 2.213642e+01 @@ -547,9 +547,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ -------------------------------- -End of Run after 2.653 Seconds. -------------------------------- +------------------------------ +End of Run after 0.27 Seconds. +------------------------------ Time: 10 Chemistry cell: 3 @@ -606,10 +606,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.800e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = 1.009e-18 + Total alkalinity (eq/kg) = 1.771e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = 5.877e-18 + Electrical balance (eq) = 6.041e-18 Percent error, 100*(Cat-|An|)/(Cat+|An|) = 0.00 Iterations = 6 Total H = 2.213642e+01 @@ -660,7 +660,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------ -End of Run after 2.66 Seconds. +End of Run after 0.27 Seconds. ------------------------------ Time: 10 @@ -718,7 +718,7 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.758e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = 5.691e-19 + Total alkalinity (eq/kg) = 5.826e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 Electrical balance (eq) = 2.786e-16 @@ -772,7 +772,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 2.666 Seconds. +End of Run after 0.271 Seconds. ------------------------------- Time: 10 @@ -830,7 +830,7 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.211e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = -4.274e-19 + Total alkalinity (eq/kg) = 3.295e-20 Temperature (°C) = 20.00 Pressure (atm) = 2.00 Electrical balance (eq) = 9.176e-14 @@ -884,7 +884,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 2.673 Seconds. +End of Run after 0.269 Seconds. ------------------------------- Time: 10 @@ -942,7 +942,7 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.200e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = -1.274e-19 + Total alkalinity (eq/kg) = 7.751e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 Electrical balance (eq) = -7.020e-16 @@ -996,7 +996,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 2.648 Seconds. +End of Run after 0.269 Seconds. ------------------------------- Time: 10 @@ -1054,7 +1054,7 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.200e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = 4.509e-18 + Total alkalinity (eq/kg) = 4.523e-18 Temperature (°C) = 20.00 Pressure (atm) = 2.00 Electrical balance (eq) = 7.519e-13 @@ -1107,9 +1107,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ -------------------------------- -End of Run after 2.653 Seconds. -------------------------------- +------------------------------ +End of Run after 0.27 Seconds. +------------------------------ Time: 10 Chemistry cell: 8 @@ -1166,7 +1166,7 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.200e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = 1.023e-18 + Total alkalinity (eq/kg) = 6.863e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 Electrical balance (eq) = 1.445e-13 @@ -1219,9 +1219,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ -------------------------------- -End of Run after 2.656 Seconds. -------------------------------- +------------------------------ +End of Run after 0.27 Seconds. +------------------------------ Time: 10 Chemistry cell: 9 @@ -1276,10 +1276,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.200e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = -9.905e-19 + Total alkalinity (eq/kg) = -1.143e-18 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = -1.555e-17 + Electrical balance (eq) = -1.553e-17 Percent error, 100*(Cat-|An|)/(Cat+|An|) = -0.00 Iterations = 2 Total H = 2.213642e+01 @@ -1327,7 +1327,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 2.666 Seconds. +End of Run after 0.269 Seconds. ------------------------------- Time: 10 @@ -1442,7 +1442,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 2.673 Seconds. +End of Run after 0.269 Seconds. ------------------------------- Time: 10 @@ -1556,9 +1556,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ -------------------------------- -End of Run after 2.647 Seconds. -------------------------------- +------------------------------ +End of Run after 0.27 Seconds. +------------------------------ Time: 10 Chemistry cell: 12 @@ -1671,9 +1671,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ -------------------------------- -End of Run after 2.652 Seconds. -------------------------------- +------------------------------ +End of Run after 0.27 Seconds. +------------------------------ Time: 10 Chemistry cell: 13 @@ -1787,7 +1787,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 2.656 Seconds. +End of Run after 0.271 Seconds. ------------------------------- Time: 10 @@ -1902,7 +1902,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 2.661 Seconds. +End of Run after 0.272 Seconds. ------------------------------- Time: 10 @@ -2017,7 +2017,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 2.666 Seconds. +End of Run after 0.272 Seconds. ------------------------------- Time: 10 @@ -2131,9 +2131,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 2.67 Seconds. ------------------------------- +------------------------------- +End of Run after 0.272 Seconds. +------------------------------- Time: 10 Chemistry cell: 17 @@ -2247,7 +2247,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 2.676 Seconds. +End of Run after 0.272 Seconds. ------------------------------- Time: 10 @@ -2362,7 +2362,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 2.681 Seconds. +End of Run after 0.273 Seconds. ------------------------------- Time: 10 @@ -2477,11 +2477,11 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 2.687 Seconds. +End of Run after 0.273 Seconds. ------------------------------- Current distribution of cells for workers Worker First cell Last Cell -0 0 5 -1 6 10 -2 11 19 +0 0 4 +1 5 9 +2 10 19 diff --git a/Tests/Output/Advect_cpp.dmp b/Tests/Output/Advect_cpp.dmp index aae4f14b0..920604379 100644 --- a/Tests/Output/Advect_cpp.dmp +++ b/Tests/Output/Advect_cpp.dmp @@ -4,7 +4,7 @@ -potential 0 -total_h 22.136415505852 -total_o 11.068314447308 - -cb 1.075129655527e-18 + -cb 1.0767509295276e-18 -density 0.99830524784931 -totals Ca 0.0001196428982687 @@ -17,7 +17,7 @@ -ah2o 0.99996484900903 -mass_water 0.19940483056363 -soln_vol 0.19975835757967 - -total_alkalinity -9.9261673506363e-23 + -total_alkalinity -1.7304618414609e-21 -activities Ca -3.3018013654974 Cl -2.9412141501733 @@ -33,24 +33,24 @@ -potential 0 -total_h 22.136415505852 -total_o 11.068314447308 - -cb 8.4070997865194e-19 + -cb 7.8499109259037e-19 -density 0.9983052478494 -totals Ca 0.00011964289180093 Cl 0.00023928579659614 K 1.2994194764655e-11 Na 8.48195644157e-17 - -pH 7.078796049857 - -pe 13.969354457274 + -pH 7.0787960498574 + -pe 13.969354457273 -mu 0.0018000850370259 -ah2o 0.99996484900848 -mass_water 0.19940483056363 -soln_vol 0.19975835757989 - -total_alkalinity -3.8966824296148e-20 + -total_alkalinity -1.0180938979303e-20 -activities Ca -3.3018013883042 Cl -2.9412141499986 - E -13.969354457274 + E -13.969354457273 H(0) -45.22482677149 K -10.206420504589 Na -15.391397091764 @@ -62,20 +62,20 @@ -potential 0 -total_h 22.136415505852 -total_o 11.068314447308 - -cb 8.9683583757489e-19 + -cb 8.5365370087717e-19 -density 0.99830524786079 -totals Ca 0.00011964204834122 Cl 0.00023928579659614 K 1.6998083051542e-09 Na 1.0538874982917e-13 - -pH 7.0787960691285 + -pH 7.078796069129 -pe 13.96935443791 -mu 0.0018000808071463 -ah2o 0.99996484893657 -mass_water 0.19940483056363 -soln_vol 0.19975835760982 - -total_alkalinity 3.3030976220468e-20 + -total_alkalinity 7.6461267101952e-20 -activities Ca -3.3018043625499 Cl -2.9412141272248 @@ -91,24 +91,24 @@ -potential 0 -total_h 22.136415505852 -total_o 11.068314447308 - -cb 5.876535917038e-18 + -cb 6.0411713287157e-18 -density 0.99830524888929 -totals Ca 0.00011955337889516 Cl 0.00023928579659614 K 1.7891515852047e-07 Na 1.2364729922871e-10 - -pH 7.0787980954878 - -pe 13.969352402078 + -pH 7.0787980954857 + -pe 13.96935240208 -mu 0.0017996361373178 -ah2o 0.99996484137719 -mass_water 0.19940483056363 -soln_vol 0.1997583607882 - -total_alkalinity 2.012894389811e-19 + -total_alkalinity 3.5317303433564e-20 -activities Ca -3.3021171525641 Cl -2.9412117329418 - E -13.969352402078 + E -13.96935240208 H(0) -45.224826752359 K -6.0675203126446 Na -9.2277061356486 @@ -120,7 +120,7 @@ -potential 0 -total_h 22.136415505852 -total_o 11.068314447308 - -cb 2.7860479322657e-16 + -cb 2.7860065401479e-16 -density 0.99830534209357 -totals Ca 0.00011133610379508 @@ -133,7 +133,7 @@ -ah2o 0.9999641408255 -mass_water 0.19940483056391 -soln_vol 0.19975865369868 - -total_alkalinity 1.1347594515247e-19 + -total_alkalinity 1.161725539494e-19 -activities Ca -3.3321851919421 Cl -2.9409884191375 @@ -143,35 +143,6 @@ Na -6.1756188689826 O(0) -3.5724482762599 -gammas - SOLUTION_RAW 5 Solution after simulation 1. - -temp 20 - -pressure 2 - -potential 0 - -total_h 22.136415505852 - -total_o 11.068314447308 - -cb 9.1760637207138e-14 - -density 0.99830599410147 - -totals - Ca 2.1235996941319e-06 - Cl 0.00023928579659881 - K 0.00021202857277487 - Na 2.3010024527435e-05 - -pH 7.0815725817844 - -pe 13.966565367281 - -mu 0.0012107356299958 - -ah2o 0.9999548300763 - -mass_water 0.19940483056784 - -soln_vol 0.19976232479367 - -total_alkalinity -8.5219455427663e-20 - -activities - Ca -5.0390564336998 - Cl -2.9376960035395 - E -13.966565367281 - H(0) -45.22480165536 - K -2.9902450425097 - Na -3.9545342945889 - O(0) -3.572503045403 - -gammas EXCHANGE_RAW 0 Exchange assemblage after simulation 1. # EXCHANGE_MODIFY candidate identifiers # -exchange_gammas 1 @@ -179,8 +150,8 @@ # EXCHANGE_MODIFY candidate identifiers # -totals Ca 0.00011000000007735 - K 5.5789786827676e-15 - Na 9.2458165879821e-22 + K 5.5789786827677e-15 + Na 9.2458165879822e-22 X 0.00022000000016027 -charge_balance 0 -la 1.2218455551817 @@ -238,10 +209,10 @@ -component X # EXCHANGE_MODIFY candidate identifiers # -totals - Ca 0.00010999150115391 + Ca 0.00010999150115392 K 1.6995489880192e-08 Na 2.2742149190083e-12 - X 0.00022000000007192 + X 0.00022000000007193 -charge_balance 0 -la 1.2219913122299 -phase_proportion 0 @@ -272,50 +243,59 @@ -n_solution -999 # Exchange workspace variables # -totals - EXCHANGE_RAW 5 Exchange assemblage after simulation 1. - # EXCHANGE_MODIFY candidate identifiers # - -exchange_gammas 1 - -component X - # EXCHANGE_MODIFY candidate identifiers # - -totals - Ca 5.5298103954097e-05 - K 0.0001071522289845 - Na 2.2515631794498e-06 - X 0.00022000000007215 - -charge_balance 0 - -la 1.9479117008937 - -phase_proportion 0 - -formula_z 0 - # EXCHANGE_MODIFY candidates with new_def=true # - -new_def 0 - -solution_equilibria 0 - -n_solution -999 - # Exchange workspace variables # + SOLUTION_RAW 5 Solution after simulation 1. + -temp 20 + -pressure 2 + -potential 0 + -total_h 22.136415505852 + -total_o 11.068314447308 + -cb 9.1760266061123e-14 + -density 0.99830599410147 -totals + Ca 2.1235996941319e-06 + Cl 0.00023928579659881 + K 0.00021202857277487 + Na 2.3010024527435e-05 + -pH 7.0815725817856 + -pe 13.96656536728 + -mu 0.0012107356299958 + -ah2o 0.9999548300763 + -mass_water 0.19940483056784 + -soln_vol 0.19976232479367 + -total_alkalinity 6.5711227861213e-21 + -activities + Ca -5.0390564336999 + Cl -2.9376960035395 + E -13.96656536728 + H(0) -45.22480165536 + K -2.9902450425097 + Na -3.9545342945889 + O(0) -3.572503045403 + -gammas SOLUTION_RAW 6 Solution after simulation 1. -temp 20 -pressure 2 -potential 0 -total_h 22.136415505852 -total_o 11.068314447308 - -cb -7.0203244750827e-16 + -cb -7.0195979788943e-16 -density 0.99830319084416 -totals Ca 2.9884729799544e-11 Cl 0.00023928579659614 K 0.00011419229852628 Na 0.0001250934382997 - -pH 7.081624629655 - -pe 13.966513092484 + -pH 7.0816246296573 + -pe 13.966513092481 -mu 0.001200086104411 -ah2o 0.99995464903458 -mass_water 0.19940483056793 -soln_vol 0.19976131924323 - -total_alkalinity -2.5397753527828e-20 + -total_alkalinity 1.5456366053921e-19 -activities Ca -9.8904037600017 Cl -2.9376246522544 - E -13.966513092484 + E -13.966513092481 H(0) -45.224801201506 K -3.2589310415102 Na -3.2191468857418 @@ -327,20 +307,20 @@ -potential 0 -total_h 22.136415505852 -total_o 11.068314447308 - -cb 7.519447178337e-13 + -cb 7.519447164672e-13 -density 0.99830135805566 -totals Ca 1.7725778408102e-17 Cl 0.00023928579659619 K 4.8038347521371e-05 Na 0.00019124744982673 - -pH 7.0816246304016 + -pH 7.0816246304017 -pe 13.966513091736 -mu 0.0012000859564291 -ah2o 0.99995464903197 -mass_water 0.19940483056793 -soln_vol 0.19976061828731 - -total_alkalinity 8.9918833923699e-19 + -total_alkalinity 9.0192134398087e-19 -activities Ca -16.117247773866 Cl -2.9376246512605 @@ -356,20 +336,20 @@ -potential 0 -total_h 22.136415505852 -total_o 11.068314447308 - -cb 1.4446884162311e-13 + -cb 1.4446890227531e-13 -density 0.99830112934291 -totals Ca 3.5591651400101e-24 Cl 0.0002392857965962 K 3.9783056143054e-05 Na 0.00019950274059762 - -pH 7.0816246303934 + -pH 7.0816246303925 -pe 13.966513091746 -mu 0.0012000859549058 -ah2o 0.99995464903202 -mass_water 0.19940483056793 -soln_vol 0.19976053081559 - -total_alkalinity 2.0394965183107e-19 + -total_alkalinity 1.3685868670812e-19 -activities Ca -22.814504950571 Cl -2.9376246512502 @@ -385,19 +365,19 @@ -potential 0 -total_h 22.136415505852 -total_o 11.068314447393 - -cb -1.5547240116016e-17 + -cb -1.5532063006137e-17 -density 0.99830111534334 -totals Cl 0.00023928579659624 K 3.9277732064696e-05 Na 0.00020000806453153 - -pH 7.0816246303892 + -pH 7.0816246303888 -pe 13.966513177943 -mu 0.0012000859545433 -ah2o 0.99995464902842 -mass_water 0.19940483056793 -soln_vol 0.19976052546253 - -total_alkalinity -1.9751087794296e-19 + -total_alkalinity -2.2786509770121e-19 -activities Cl -2.9376246512477 E -13.966513177943 @@ -406,43 +386,33 @@ Na -3.0153339071739 O(0) -3.5725037484386 -gammas - SOLUTION_RAW 10 Solution after simulation 1. - -temp 20 - -pressure 2 - -potential 0 - -total_h 22.135866361697 - -total_o 11.068757726907 - -cb -6.7902654296992e-17 - -density 0.99831968732863 + EXCHANGE_RAW 5 Exchange assemblage after simulation 1. + # EXCHANGE_MODIFY candidate identifiers # + -exchange_gammas 1 + -component X + # EXCHANGE_MODIFY candidate identifiers # + -totals + Ca 5.5298103954096e-05 + K 0.0001071522289845 + Na 2.2515631794498e-06 + X 0.00022000000007215 + -charge_balance 0 + -la 1.9479117008937 + -phase_proportion 0 + -formula_z 0 + # EXCHANGE_MODIFY candidates with new_def=true # + -new_def 0 + -solution_equilibria 0 + -n_solution -999 + # Exchange workspace variables # -totals - K 3.9260409219821e-05 - N 0.00023927986057314 - Na 0.00020001945135325 - -pH 7.0816246305178 - -pe 13.966528092736 - -mu 0.0012000859545714 - -ah2o 0.99995464840361 - -mass_water 0.19939988387738 - -soln_vol 0.19975821827742 - -total_alkalinity -7.5900107774396e-19 - -activities - E -13.966528092736 - H(0) -45.224831203736 - K -3.7226022594356 - N(-3) -64.071413252819 - N(0) -19.539412420617 - N(3) -15.917214058761 - N(5) -2.9377614291833 - Na -3.0152984089092 - O(0) -3.5724441064573 - -gammas EXCHANGE_RAW 6 Exchange assemblage after simulation 1. # EXCHANGE_MODIFY candidate identifiers # -exchange_gammas 1 -component X # EXCHANGE_MODIFY candidate identifiers # -totals - Ca 7.6966419082244e-09 + Ca 7.6966419082243e-09 K 0.00018148921301107 Na 3.8495393844372e-05 X 0.00022000000013926 @@ -515,27 +485,36 @@ -n_solution -999 # Exchange workspace variables # -totals - EXCHANGE_RAW 10 Exchange assemblage after simulation 1. - # EXCHANGE_MODIFY candidate identifiers # - -exchange_gammas 1 - -component X - # EXCHANGE_MODIFY candidate identifiers # - -totals - H 1.556973507194e-64 - K 0.00011075000841372 - N 3.892433767985e-65 - Na 0.0001092499916584 - X 0.00022000000007212 - -charge_balance 0 - -la 2.6946830556585 - -phase_proportion 0 - -formula_z 0 - # EXCHANGE_MODIFY candidates with new_def=true # - -new_def 0 - -solution_equilibria 0 - -n_solution -999 - # Exchange workspace variables # + SOLUTION_RAW 10 Solution after simulation 1. + -temp 20 + -pressure 2 + -potential 0 + -total_h 22.135866361697 + -total_o 11.068757726907 + -cb -6.7902654296992e-17 + -density 0.99831968732863 -totals + K 3.9260409219821e-05 + N 0.00023927986057314 + Na 0.00020001945135325 + -pH 7.0816246305178 + -pe 13.966528092736 + -mu 0.0012000859545714 + -ah2o 0.99995464840361 + -mass_water 0.19939988387738 + -soln_vol 0.19975821827742 + -total_alkalinity -7.5900107774396e-19 + -activities + E -13.966528092736 + H(0) -45.224831203736 + K -3.7226022594356 + N(-3) -64.071413252819 + N(0) -19.539412420617 + N(3) -15.917214058761 + N(5) -2.9377614291833 + Na -3.0152984089092 + O(0) -3.5724441064573 + -gammas SOLUTION_RAW 11 Solution after simulation 1. -temp 20 -pressure 2 @@ -806,6 +785,27 @@ Na -3.0152984089092 O(0) -3.5724441064573 -gammas + EXCHANGE_RAW 10 Exchange assemblage after simulation 1. + # EXCHANGE_MODIFY candidate identifiers # + -exchange_gammas 1 + -component X + # EXCHANGE_MODIFY candidate identifiers # + -totals + H 1.556973507194e-64 + K 0.00011075000841372 + N 3.8924337679849e-65 + Na 0.0001092499916584 + X 0.00022000000007212 + -charge_balance 0 + -la 2.6946830556585 + -phase_proportion 0 + -formula_z 0 + # EXCHANGE_MODIFY candidates with new_def=true # + -new_def 0 + -solution_equilibria 0 + -n_solution -999 + # Exchange workspace variables # + -totals EXCHANGE_RAW 11 Exchange assemblage after simulation 1. # EXCHANGE_MODIFY candidate identifiers # -exchange_gammas 1 @@ -814,7 +814,7 @@ -totals H 1.556973507194e-64 K 0.00011075000841372 - N 3.892433767985e-65 + N 3.8924337679849e-65 Na 0.0001092499916584 X 0.00022000000007212 -charge_balance 0 @@ -835,7 +835,7 @@ -totals H 1.556973507194e-64 K 0.00011075000841372 - N 3.892433767985e-65 + N 3.8924337679849e-65 Na 0.0001092499916584 X 0.00022000000007212 -charge_balance 0 @@ -856,7 +856,7 @@ -totals H 1.556973507194e-64 K 0.00011075000841372 - N 3.892433767985e-65 + N 3.8924337679849e-65 Na 0.0001092499916584 X 0.00022000000007212 -charge_balance 0 @@ -877,7 +877,7 @@ -totals H 1.556973507194e-64 K 0.00011075000841372 - N 3.892433767985e-65 + N 3.8924337679849e-65 Na 0.0001092499916584 X 0.00022000000007212 -charge_balance 0 @@ -898,7 +898,7 @@ -totals H 1.556973507194e-64 K 0.00011075000841372 - N 3.892433767985e-65 + N 3.8924337679849e-65 Na 0.0001092499916584 X 0.00022000000007212 -charge_balance 0 @@ -919,7 +919,7 @@ -totals H 1.556973507194e-64 K 0.00011075000841372 - N 3.892433767985e-65 + N 3.8924337679849e-65 Na 0.0001092499916584 X 0.00022000000007212 -charge_balance 0 @@ -940,7 +940,7 @@ -totals H 1.556973507194e-64 K 0.00011075000841372 - N 3.892433767985e-65 + N 3.8924337679849e-65 Na 0.0001092499916584 X 0.00022000000007212 -charge_balance 0 @@ -961,7 +961,7 @@ -totals H 1.556973507194e-64 K 0.00011075000841372 - N 3.892433767985e-65 + N 3.8924337679849e-65 Na 0.0001092499916584 X 0.00022000000007212 -charge_balance 0 @@ -982,7 +982,7 @@ -totals H 1.556973507194e-64 K 0.00011075000841372 - N 3.892433767985e-65 + N 3.8924337679849e-65 Na 0.0001092499916584 X 0.00022000000007212 -charge_balance 0 diff --git a/Tests/Output/Advect_cpp_units_utility.txt b/Tests/Output/Advect_cpp_units_utility.txt index a85b668af..cb9450da9 100644 --- a/Tests/Output/Advect_cpp_units_utility.txt +++ b/Tests/Output/Advect_cpp_units_utility.txt @@ -113,18 +113,18 @@ Using solution 2. ----------------------------Description of solution---------------------------- pH = 6.950 Charge balance - pe = -0.651 Adjusted to redox equilibrium + pe = -0.569 Adjusted to redox equilibrium Specific Conductance (µS/cm, 25°C) = 83620 Density (g/cm³) = 1.03837 Volume (L) = 1.00000 Activity of water = 0.964 Ionic strength (mol/kgw) = 1.062e+00 Mass of water (kg) = 9.777e-01 - Total alkalinity (eq/kg) = 2.796e-16 + Total alkalinity (eq/kg) = 1.838e-16 Temperature (°C) = 25.00 - Electrical balance (eq) = -9.719e-13 + Electrical balance (eq) = -1.495e-11 Percent error, 100*(Cat-|An|)/(Cat+|An|) = -0.00 - Iterations = 9 + Iterations = 8 Total H = 1.085353e+02 Total O = 5.426764e+01 @@ -138,22 +138,22 @@ Using solution 2. H2O 5.551e+01 9.639e-01 1.744 -0.016 0.000 18.07 Cl 1.062e+00 Cl- 1.062e+00 6.433e-01 0.026 -0.192 -0.218 18.97 -H(0) 2.800e-16 - H2 1.400e-16 1.788e-16 -15.854 -15.748 0.106 28.61 +H(0) 1.920e-16 + H2 9.598e-17 1.226e-16 -16.018 -15.912 0.106 28.61 Na 1.062e+00 Na+ 1.062e+00 7.807e-01 0.026 -0.107 -0.134 -0.27 NaOH 5.316e-18 6.789e-18 -17.274 -17.168 0.106 (0) O(0) 0.000e+00 - O2 0.000e+00 0.000e+00 -61.023 -60.917 0.106 30.40 + O2 0.000e+00 0.000e+00 -60.695 -60.589 0.106 30.40 ------------------------------Saturation indices------------------------------- Phase SI** log IAP log K(298 K, 1 atm) - H2(g) -12.65 -15.75 -3.10 H2 + H2(g) -12.81 -15.91 -3.10 H2 H2O(g) -1.52 -0.02 1.50 H2O Halite -1.87 -0.30 1.57 NaCl - O2(g) -58.02 -60.92 -2.89 O2 + O2(g) -57.70 -60.59 -2.89 O2 **For a gas, SI = log10(fugacity). Fugacity = pressure * phi / 1 atm. For ideal gases, phi = 1. @@ -166,7 +166,7 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ -------------------------------- -End of Run after 1.131 Seconds. -------------------------------- +------------------------------ +End of Run after 0.11 Seconds. +------------------------------ diff --git a/Tests/Output/Advect_cpp_units_worker.chem.txt b/Tests/Output/Advect_cpp_units_worker.chem.txt index 836b8c905..ce3d7521a 100644 --- a/Tests/Output/Advect_cpp_units_worker.chem.txt +++ b/Tests/Output/Advect_cpp_units_worker.chem.txt @@ -118,7 +118,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 1.118 Seconds. +End of Run after 0.105 Seconds. ------------------------------- Time: 0 @@ -162,9 +162,9 @@ Using solution 1. Activity of water = 0.964 Ionic strength (mol/kgw) = 1.062e+00 Mass of water (kg) = 1.955e-01 - Total alkalinity (eq/kg) = -2.121e-19 + Total alkalinity (eq/kg) = -2.127e-19 Temperature (°C) = 25.00 - Electrical balance (eq) = 7.597e-17 + Electrical balance (eq) = 1.592e-16 Percent error, 100*(Cat-|An|)/(Cat+|An|) = 0.00 Iterations = 6 Total H = 2.170705e+01 @@ -209,7 +209,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 1.114 Seconds. +End of Run after 0.104 Seconds. ------------------------------- Time: 0 @@ -300,6 +300,6 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 1.113 Seconds. +End of Run after 0.104 Seconds. ------------------------------- diff --git a/Tests/Output/Advect_cpp_utility.txt b/Tests/Output/Advect_cpp_utility.txt index 99303a785..5517f57a6 100644 --- a/Tests/Output/Advect_cpp_utility.txt +++ b/Tests/Output/Advect_cpp_utility.txt @@ -37,10 +37,10 @@ Using solution 1. Activity of water = 1.000 Ionic strength (mol/kgw) = 1.500e-03 Mass of water (kg) = 9.970e-01 - Total alkalinity (eq/kg) = -7.786e-19 + Total alkalinity (eq/kg) = -5.652e-19 Temperature (°C) = 15.00 Pressure (atm) = 3.00 - Electrical balance (eq) = -3.611e-17 + Electrical balance (eq) = -3.644e-17 Percent error, 100*(Cat-|An|)/(Cat+|An|) = -0.00 Iterations = 12 Total H = 1.106821e+02 @@ -91,6 +91,6 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 3.049 Seconds. +End of Run after 0.441 Seconds. ------------------------------- diff --git a/Tests/Output/Advect_f90.chem.txt b/Tests/Output/Advect_f90.chem.txt index 4a6760d4b..1c3d3adee 100644 --- a/Tests/Output/Advect_f90.chem.txt +++ b/Tests/Output/Advect_f90.chem.txt @@ -195,9 +195,9 @@ End of simulation. Reading input data for simulation 4. ------------------------------------ --------------------------------- -End of Run after 12.117 Seconds. --------------------------------- +------------------------------- +End of Run after 1.665 Seconds. +------------------------------- Number of threads: 3 Number of MPI processes: 1 @@ -270,10 +270,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.800e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = 3.269e-20 + Total alkalinity (eq/kg) = 3.124e-20 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = 1.044e-18 + Electrical balance (eq) = 1.045e-18 Percent error, 100*(Cat-|An|)/(Cat+|An|) = 0.00 Iterations = 2 Total H = 2.213642e+01 @@ -323,9 +323,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ --------------------------------- -End of Run after 12.471 Seconds. --------------------------------- +------------------------------- +End of Run after 1.699 Seconds. +------------------------------- Time: 10 Chemistry cell: 1 @@ -382,10 +382,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.800e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = -4.570e-20 + Total alkalinity (eq/kg) = 1.225e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = 7.899e-19 + Electrical balance (eq) = 7.565e-19 Percent error, 100*(Cat-|An|)/(Cat+|An|) = 0.00 Iterations = 5 Total H = 2.213642e+01 @@ -435,9 +435,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ --------------------------------- -End of Run after 12.475 Seconds. --------------------------------- +------------------------------- +End of Run after 1.699 Seconds. +------------------------------- Time: 10 Chemistry cell: 2 @@ -494,10 +494,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.800e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = 4.616e-19 + Total alkalinity (eq/kg) = 4.255e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = 1.099e-18 + Electrical balance (eq) = 1.106e-18 Percent error, 100*(Cat-|An|)/(Cat+|An|) = 0.00 Iterations = 6 Total H = 2.213642e+01 @@ -547,9 +547,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ --------------------------------- -End of Run after 12.479 Seconds. --------------------------------- +----------------------------- +End of Run after 1.7 Seconds. +----------------------------- Time: 10 Chemistry cell: 3 @@ -606,10 +606,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.800e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = 2.028e-19 + Total alkalinity (eq/kg) = 3.874e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = 6.271e-18 + Electrical balance (eq) = 6.016e-18 Percent error, 100*(Cat-|An|)/(Cat+|An|) = 0.00 Iterations = 6 Total H = 2.213642e+01 @@ -659,9 +659,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ --------------------------------- -End of Run after 12.482 Seconds. --------------------------------- +----------------------------- +End of Run after 1.7 Seconds. +----------------------------- Time: 10 Chemistry cell: 4 @@ -718,10 +718,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.758e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = -1.165e-19 + Total alkalinity (eq/kg) = 2.763e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = 2.787e-16 + Electrical balance (eq) = 2.788e-16 Percent error, 100*(Cat-|An|)/(Cat+|An|) = 0.00 Iterations = 7 Total H = 2.213642e+01 @@ -771,9 +771,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ --------------------------------- -End of Run after 12.486 Seconds. --------------------------------- +------------------------------- +End of Run after 1.701 Seconds. +------------------------------- Time: 10 Chemistry cell: 5 @@ -830,7 +830,7 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.211e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = 5.682e-19 + Total alkalinity (eq/kg) = 3.368e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 Electrical balance (eq) = 9.176e-14 @@ -884,7 +884,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 12.49 Seconds. +End of Run after 1.701 Seconds. ------------------------------- Time: 10 @@ -942,10 +942,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.200e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = -5.324e-19 + Total alkalinity (eq/kg) = 3.480e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = -7.021e-16 + Electrical balance (eq) = -7.020e-16 Percent error, 100*(Cat-|An|)/(Cat+|An|) = -0.00 Iterations = 6 Total H = 2.213642e+01 @@ -995,9 +995,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ --------------------------------- -End of Run after 12.471 Seconds. --------------------------------- +------------------------------- +End of Run after 1.702 Seconds. +------------------------------- Time: 10 Chemistry cell: 7 @@ -1054,7 +1054,7 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.200e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = 3.894e-18 + Total alkalinity (eq/kg) = 4.161e-18 Temperature (°C) = 20.00 Pressure (atm) = 2.00 Electrical balance (eq) = 7.519e-13 @@ -1107,9 +1107,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ --------------------------------- -End of Run after 12.475 Seconds. --------------------------------- +------------------------------- +End of Run after 1.699 Seconds. +------------------------------- Time: 10 Chemistry cell: 8 @@ -1166,7 +1166,7 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.200e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = -3.445e-19 + Total alkalinity (eq/kg) = -3.420e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 Electrical balance (eq) = 1.445e-13 @@ -1219,9 +1219,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ --------------------------------- -End of Run after 12.478 Seconds. --------------------------------- +------------------------------- +End of Run after 1.699 Seconds. +------------------------------- Time: 10 Chemistry cell: 9 @@ -1276,7 +1276,7 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.200e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = 2.102e-19 + Total alkalinity (eq/kg) = 2.175e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 Electrical balance (eq) = -1.555e-17 @@ -1326,9 +1326,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ --------------------------------- -End of Run after 12.483 Seconds. --------------------------------- +----------------------------- +End of Run after 1.7 Seconds. +----------------------------- Time: 10 Chemistry cell: 10 @@ -1441,9 +1441,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ --------------------------------- -End of Run after 12.488 Seconds. --------------------------------- +----------------------------- +End of Run after 1.7 Seconds. +----------------------------- Time: 10 Chemistry cell: 11 @@ -1556,9 +1556,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ --------------------------------- -End of Run after 12.469 Seconds. --------------------------------- +------------------------------- +End of Run after 1.699 Seconds. +------------------------------- Time: 10 Chemistry cell: 12 @@ -1671,9 +1671,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ --------------------------------- -End of Run after 12.472 Seconds. --------------------------------- +------------------------------- +End of Run after 1.699 Seconds. +------------------------------- Time: 10 Chemistry cell: 13 @@ -1786,9 +1786,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ --------------------------------- -End of Run after 12.476 Seconds. --------------------------------- +----------------------------- +End of Run after 1.7 Seconds. +----------------------------- Time: 10 Chemistry cell: 14 @@ -1901,9 +1901,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ --------------------------------- -End of Run after 12.479 Seconds. --------------------------------- +----------------------------- +End of Run after 1.7 Seconds. +----------------------------- Time: 10 Chemistry cell: 15 @@ -2016,9 +2016,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ --------------------------------- -End of Run after 12.482 Seconds. --------------------------------- +------------------------------- +End of Run after 1.701 Seconds. +------------------------------- Time: 10 Chemistry cell: 16 @@ -2131,9 +2131,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ --------------------------------- -End of Run after 12.486 Seconds. --------------------------------- +------------------------------- +End of Run after 1.701 Seconds. +------------------------------- Time: 10 Chemistry cell: 17 @@ -2247,7 +2247,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 12.49 Seconds. +End of Run after 1.702 Seconds. ------------------------------- Time: 10 @@ -2361,9 +2361,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ --------------------------------- -End of Run after 12.494 Seconds. --------------------------------- +------------------------------- +End of Run after 1.702 Seconds. +------------------------------- Time: 10 Chemistry cell: 19 @@ -2476,7 +2476,7 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ --------------------------------- -End of Run after 12.496 Seconds. --------------------------------- +------------------------------- +End of Run after 1.703 Seconds. +------------------------------- diff --git a/Tests/Output/Advect_f90.dmp b/Tests/Output/Advect_f90.dmp index a8c5c8e31..0066c47b3 100644 --- a/Tests/Output/Advect_f90.dmp +++ b/Tests/Output/Advect_f90.dmp @@ -4,7 +4,7 @@ -potential 0 -total_h 22.136415835711 -total_o 11.068314612239 - -cb 1.0443750803523e-18 + -cb 1.044659630483e-18 -density 0.99830524784931 -totals Ca 0.00011964290005151 @@ -17,7 +17,7 @@ -ah2o 0.99996484900903 -mass_water 0.19940483353499 -soln_vol 0.1997583605563 - -total_alkalinity 6.5181832269179e-21 + -total_alkalinity 6.2303243737494e-21 -activities Ca -3.3018013654974 Cl -2.9412141501733 @@ -33,20 +33,20 @@ -potential 0 -total_h 22.136415835711 -total_o 11.068314612239 - -cb 7.8988138437179e-19 + -cb 7.565327707961e-19 -density 0.9983052478494 -totals Ca 0.00011964289358375 Cl 0.00023928580016178 K 1.2994194958284e-11 Na 8.481956567961e-17 - -pH 7.0787960498574 + -pH 7.0787960498578 -pe 13.969354457273 -mu 0.0018000850370259 -ah2o 0.99996484900848 -mass_water 0.19940483353499 -soln_vol 0.19975836055653 - -total_alkalinity -9.1122216278842e-21 + -total_alkalinity 2.4434915294816e-20 -activities Ca -3.3018013883042 Cl -2.9412141499986 @@ -62,20 +62,20 @@ -potential 0 -total_h 22.136415835711 -total_o 11.068314612239 - -cb 1.0987373902093e-18 + -cb 1.1058743045344e-18 -density 0.99830524786079 -totals Ca 0.00011964205012403 Cl 0.00023928580016178 K 1.6998083304833e-09 Na 1.0538875139958e-13 - -pH 7.0787960691292 + -pH 7.0787960691291 -pe 13.969354437911 -mu 0.0018000808071463 -ah2o 0.99996484893657 -mass_water 0.19940483353499 -soln_vol 0.19975836058646 - -total_alkalinity 9.20354236751e-20 + -total_alkalinity 8.485549595814e-20 -activities Ca -3.3018043625499 Cl -2.9412141272248 @@ -91,28 +91,28 @@ -potential 0 -total_h 22.136415835711 -total_o 11.068314612239 - -cb 6.2707007138093e-18 + -cb 6.0161871654941e-18 -density 0.99830524888929 -totals Ca 0.00011955338067665 Cl 0.00023928580016178 K 1.7891516118651e-07 Na 1.236473010712e-10 - -pH 7.0787980954857 - -pe 13.96935240208 + -pH 7.0787980954862 + -pe 13.969352402079 -mu 0.0017996361373178 -ah2o 0.99996484137719 -mass_water 0.19940483353499 -soln_vol 0.19975836376483 - -total_alkalinity 4.0435897064042e-20 + -total_alkalinity 7.7255360490003e-20 -activities Ca -3.3021171525641 Cl -2.9412117329418 - E -13.96935240208 + E -13.969352402079 H(0) -45.224826752359 K -6.0675203126446 Na -9.2277061356486 - O(0) -3.5724441553504 + O(0) -3.5724441553505 -gammas SOLUTION_RAW 4 Solution after simulation 1. -temp 20 @@ -120,20 +120,20 @@ -potential 0 -total_h 22.136415835711 -total_o 11.068314612239 - -cb 2.7872394032201e-16 + -cb 2.7879249374245e-16 -density 0.99830534209357 -totals Ca 0.00011133610545412 Cl 0.0002392858001618 K 1.6474256281231e-05 Na 1.3933297261427e-07 - -pH 7.0789862884277 + -pH 7.0789862884286 -pe 13.969163331038 -mu 0.0017584271924268 -ah2o 0.9999641408255 -mass_water 0.19940483353527 -soln_vol 0.19975865667532 - -total_alkalinity -2.3233849045389e-20 + -total_alkalinity 5.5096846240932e-20 -activities Ca -3.3321851919421 Cl -2.9409884191375 @@ -149,20 +149,20 @@ -potential 0 -total_h 22.136415835711 -total_o 11.068314612239 - -cb 9.1761004766498e-14 + -cb 9.1760794050508e-14 -density 0.99830599410147 -totals Ca 2.123599725776e-06 Cl 0.00023928580016444 K 0.00021202857593434 Na 2.3010024870311e-05 - -pH 7.0815725817869 + -pH 7.0815725817863 -pe 13.966565367281 -mu 0.0012107356299958 -ah2o 0.9999548300763 -mass_water 0.19940483353921 -soln_vol 0.19976232777036 - -total_alkalinity 1.1330058286261e-19 + -total_alkalinity 6.7160448294405e-20 -activities Ca -5.0390564336998 Cl -2.9376960035395 @@ -199,7 +199,7 @@ # EXCHANGE_MODIFY candidate identifiers # -totals Ca 0.00011000000105815 - K 1.2339290295042e-12 + K 1.2339290295041e-12 Na 1.5595423306637e-18 X 0.00022000000335024 -charge_balance 0 @@ -239,7 +239,7 @@ # EXCHANGE_MODIFY candidate identifiers # -totals Ca 0.00010999150279292 - K 1.6995490133445e-08 + K 1.6995490133444e-08 Na 2.2742149528967e-12 X 0.00022000000335018 -charge_balance 0 @@ -280,7 +280,7 @@ -totals Ca 5.5298104778102e-05 K 0.0001071522305812 - Na 2.2515632130008e-06 + Na 2.2515632130007e-06 X 0.0002200000033504 -charge_balance 0 -la 1.9479117008937 @@ -298,24 +298,24 @@ -potential 0 -total_h 22.136415835711 -total_o 11.068314612239 - -cb -7.0212012534448e-16 + -cb -7.0204526549904e-16 -density 0.99830319084416 -totals Ca 2.9884730244861e-11 Cl 0.00023928580016178 K 0.00011419230022788 Na 0.00012509344016374 - -pH 7.081624629654 - -pe 13.966513092488 + -pH 7.0816246296562 + -pe 13.966513092486 -mu 0.001200086104411 -ah2o 0.99995464903458 -mass_water 0.19940483353929 -soln_vol 0.19976132221991 - -total_alkalinity -1.0615705109261e-19 + -total_alkalinity 6.9387218503398e-20 -activities Ca -9.8904037600017 Cl -2.9376246522544 - E -13.966513092488 + E -13.966513092486 H(0) -45.224801201513 K -3.2589310415102 Na -3.2191468857418 @@ -327,24 +327,24 @@ -potential 0 -total_h 22.136415835711 -total_o 11.068314612239 - -cb 7.5194462404135e-13 + -cb 7.5194435345403e-13 -density 0.99830135805566 -totals Ca 1.7725778672237e-17 Cl 0.00023928580016183 K 4.8038348237199e-05 Na 0.00019124745267654 - -pH 7.0816246304001 - -pe 13.966513091737 + -pH 7.0816246304008 + -pe 13.966513091736 -mu 0.0012000859564291 -ah2o 0.99995464903197 -mass_water 0.19940483353929 -soln_vol 0.19976062126398 - -total_alkalinity 7.7643142761167e-19 + -total_alkalinity 8.2971178522744e-19 -activities Ca -16.117247773866 Cl -2.9376246512605 - E -13.966513091737 + E -13.966513091736 H(0) -45.224801201503 K -3.6349797956543 Na -3.0347857616045 @@ -356,7 +356,7 @@ -potential 0 -total_h 22.136415835711 -total_o 11.068314612239 - -cb 1.444690125087e-13 + -cb 1.4446901226386e-13 -density 0.99830112934291 -totals Ca 3.5591651930458e-24 @@ -369,7 +369,7 @@ -ah2o 0.99995464903202 -mass_water 0.19940483353929 -soln_vol 0.19976053379225 - -total_alkalinity -6.8689078066403e-20 + -total_alkalinity -6.8199387143772e-20 -activities Ca -22.814504950571 Cl -2.9376246512502 @@ -385,22 +385,22 @@ -potential 0 -total_h 22.136415835711 -total_o 11.068314612323 - -cb -1.5551068307891e-17 + -cb -1.5551799535552e-17 -density 0.99830111534334 -totals Cl 0.00023928580016187 K 3.9277732649979e-05 Na 0.00020000806751188 - -pH 7.0816246303922 - -pe 13.96651317794 + -pH 7.0816246303923 + -pe 13.966513177939 -mu 0.0012000859545433 -ah2o 0.99995464902842 -mass_water 0.19940483353929 -soln_vol 0.19976052843919 - -total_alkalinity 4.1904969831936e-20 + -total_alkalinity 4.3374042599831e-20 -activities Cl -2.9376246512477 - E -13.96651317794 + E -13.966513177939 H(0) -45.224801382473 K -3.722421452022 Na -3.0153339071739 @@ -436,13 +436,43 @@ Na -3.0152984089092 O(0) -3.5724441064413 -gammas + SOLUTION_RAW 11 Solution after simulation 1. + -temp 20 + -pressure 2 + -potential 0 + -total_h 22.135866691547 + -total_o 11.068757891845 + -cb -6.8195595347844e-17 + -density 0.99831968732863 + -totals + K 3.9260409804847e-05 + N 0.00023927986413869 + Na 0.00020001945433377 + -pH 7.0816246305214 + -pe 13.966528092736 + -mu 0.0012000859545714 + -ah2o 0.99995464840361 + -mass_water 0.19939988684867 + -soln_vol 0.19975822125405 + -total_alkalinity -4.7080473488558e-19 + -activities + E -13.966528092736 + H(0) -45.224831203744 + K -3.7226022594356 + N(-3) -64.071413252857 + N(0) -19.539412420663 + N(3) -15.917214058769 + N(5) -2.9377614291833 + Na -3.0152984089092 + O(0) -3.5724441064413 + -gammas EXCHANGE_RAW 6 Exchange assemblage after simulation 1. # EXCHANGE_MODIFY candidate identifiers # -exchange_gammas 1 -component X # EXCHANGE_MODIFY candidate identifiers # -totals - Ca 7.6966420229132e-09 + Ca 7.6966420229133e-09 K 0.00018148921571547 Na 3.8495394417998e-05 X 0.00022000000341751 @@ -536,36 +566,27 @@ -n_solution -999 # Exchange workspace variables # -totals - SOLUTION_RAW 11 Solution after simulation 1. - -temp 20 - -pressure 2 - -potential 0 - -total_h 22.135866691547 - -total_o 11.068757891845 - -cb -6.8195595347844e-17 - -density 0.99831968732863 + EXCHANGE_RAW 11 Exchange assemblage after simulation 1. + # EXCHANGE_MODIFY candidate identifiers # + -exchange_gammas 1 + -component X + # EXCHANGE_MODIFY candidate identifiers # + -totals + H 1.5569735302542e-64 + K 0.00011075001006402 + N 3.8924338256354e-65 + Na 0.00010924999328635 + X 0.00022000000335037 + -charge_balance 0 + -la 2.6946830556585 + -phase_proportion 0 + -formula_z 0 + # EXCHANGE_MODIFY candidates with new_def=true # + -new_def 0 + -solution_equilibria 0 + -n_solution -999 + # Exchange workspace variables # -totals - K 3.9260409804847e-05 - N 0.00023927986413869 - Na 0.00020001945433377 - -pH 7.0816246305214 - -pe 13.966528092736 - -mu 0.0012000859545714 - -ah2o 0.99995464840361 - -mass_water 0.19939988684867 - -soln_vol 0.19975822125405 - -total_alkalinity -4.7080473488558e-19 - -activities - E -13.966528092736 - H(0) -45.224831203744 - K -3.7226022594356 - N(-3) -64.071413252857 - N(0) -19.539412420663 - N(3) -15.917214058769 - N(5) -2.9377614291833 - Na -3.0152984089092 - O(0) -3.5724441064413 - -gammas SOLUTION_RAW 12 Solution after simulation 1. -temp 20 -pressure 2 @@ -806,27 +827,6 @@ Na -3.0152984089092 O(0) -3.5724441064413 -gammas - EXCHANGE_RAW 11 Exchange assemblage after simulation 1. - # EXCHANGE_MODIFY candidate identifiers # - -exchange_gammas 1 - -component X - # EXCHANGE_MODIFY candidate identifiers # - -totals - H 1.5569735302542e-64 - K 0.00011075001006402 - N 3.8924338256354e-65 - Na 0.00010924999328635 - X 0.00022000000335037 - -charge_balance 0 - -la 2.6946830556585 - -phase_proportion 0 - -formula_z 0 - # EXCHANGE_MODIFY candidates with new_def=true # - -new_def 0 - -solution_equilibria 0 - -n_solution -999 - # Exchange workspace variables # - -totals EXCHANGE_RAW 12 Exchange assemblage after simulation 1. # EXCHANGE_MODIFY candidate identifiers # -exchange_gammas 1 diff --git a/Tests/Output/Advect_f90_utility.txt b/Tests/Output/Advect_f90_utility.txt index b275137ae..ee96dcfcf 100644 --- a/Tests/Output/Advect_f90_utility.txt +++ b/Tests/Output/Advect_f90_utility.txt @@ -37,10 +37,10 @@ Using solution 1. Activity of water = 1.000 Ionic strength (mol/kgw) = 1.500e-03 Mass of water (kg) = 9.970e-01 - Total alkalinity (eq/kg) = 4.407e-20 + Total alkalinity (eq/kg) = -1.657e-19 Temperature (°C) = 15.00 Pressure (atm) = 3.00 - Electrical balance (eq) = -3.522e-17 + Electrical balance (eq) = -3.675e-17 Percent error, 100*(Cat-|An|)/(Cat+|An|) = -0.00 Iterations = 12 Total H = 1.106821e+02 @@ -90,7 +90,7 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ --------------------------------- -End of Run after 12.547 Seconds. --------------------------------- +------------------------------- +End of Run after 1.883 Seconds. +------------------------------- diff --git a/Tests/Output/Gas_c.chem.txt b/Tests/Output/Gas_c.chem.txt index d2ffec235..d2e8bdc86 100644 --- a/Tests/Output/Gas_c.chem.txt +++ b/Tests/Output/Gas_c.chem.txt @@ -126,7 +126,7 @@ End of simulation. Reading input data for simulation 5. ------------------------------------ --------------------------------- -End of Run after 10.787 Seconds. --------------------------------- +------------------------------- +End of Run after 1.547 Seconds. +------------------------------- diff --git a/Tests/Output/Gas_cpp.chem.txt b/Tests/Output/Gas_cpp.chem.txt index 3bee2ce76..09b203571 100644 --- a/Tests/Output/Gas_cpp.chem.txt +++ b/Tests/Output/Gas_cpp.chem.txt @@ -126,7 +126,7 @@ End of simulation. Reading input data for simulation 5. ------------------------------------ --------------------------------- -End of Run after 10.306 Seconds. --------------------------------- +------------------------------- +End of Run after 1.498 Seconds. +------------------------------- diff --git a/Tests/Output/Gas_f90.chem.txt b/Tests/Output/Gas_f90.chem.txt index 4670d2160..89467f33d 100644 --- a/Tests/Output/Gas_f90.chem.txt +++ b/Tests/Output/Gas_f90.chem.txt @@ -126,7 +126,7 @@ End of simulation. Reading input data for simulation 5. ------------------------------------ --------------------------------- -End of Run after 13.767 Seconds. --------------------------------- +------------------------------- +End of Run after 2.054 Seconds. +------------------------------- diff --git a/Tests/Output/SimpleAdvect_c.chem.txt b/Tests/Output/SimpleAdvect_c.chem.txt index bbcc60844..fe13e9785 100644 --- a/Tests/Output/SimpleAdvect_c.chem.txt +++ b/Tests/Output/SimpleAdvect_c.chem.txt @@ -196,7 +196,7 @@ Reading input data for simulation 4. ------------------------------------ ------------------------------- -End of Run after 2.457 Seconds. +End of Run after 0.588 Seconds. ------------------------------- H @@ -263,10 +263,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.800e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = -4.978e-22 + Total alkalinity (eq/kg) = -8.678e-21 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = 1.075e-18 + Electrical balance (eq) = 1.077e-18 Percent error, 100*(Cat-|An|)/(Cat+|An|) = 0.00 Iterations = 2 Total H = 2.213642e+01 @@ -317,7 +317,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 2.659 Seconds. +End of Run after 0.612 Seconds. ------------------------------- Time: 10 @@ -375,10 +375,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.800e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = -1.954e-19 + Total alkalinity (eq/kg) = -5.106e-20 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = 8.407e-19 + Electrical balance (eq) = 7.850e-19 Percent error, 100*(Cat-|An|)/(Cat+|An|) = 0.00 Iterations = 5 Total H = 2.213642e+01 @@ -429,7 +429,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 2.662 Seconds. +End of Run after 0.612 Seconds. ------------------------------- Time: 10 @@ -487,10 +487,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.800e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = 1.656e-19 + Total alkalinity (eq/kg) = 3.834e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = 8.968e-19 + Electrical balance (eq) = 8.537e-19 Percent error, 100*(Cat-|An|)/(Cat+|An|) = 0.00 Iterations = 6 Total H = 2.213642e+01 @@ -541,7 +541,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 2.664 Seconds. +End of Run after 0.613 Seconds. ------------------------------- Time: 10 @@ -599,10 +599,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.800e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = 1.009e-18 + Total alkalinity (eq/kg) = 1.771e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = 5.877e-18 + Electrical balance (eq) = 6.041e-18 Percent error, 100*(Cat-|An|)/(Cat+|An|) = 0.00 Iterations = 6 Total H = 2.213642e+01 @@ -653,7 +653,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 2.667 Seconds. +End of Run after 0.613 Seconds. ------------------------------- Time: 10 @@ -711,7 +711,7 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.758e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = 5.691e-19 + Total alkalinity (eq/kg) = 5.826e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 Electrical balance (eq) = 2.786e-16 @@ -765,7 +765,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 2.669 Seconds. +End of Run after 0.613 Seconds. ------------------------------- Time: 10 @@ -823,7 +823,7 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.211e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = -4.274e-19 + Total alkalinity (eq/kg) = 3.295e-20 Temperature (°C) = 20.00 Pressure (atm) = 2.00 Electrical balance (eq) = 9.176e-14 @@ -877,7 +877,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 2.672 Seconds. +End of Run after 0.613 Seconds. ------------------------------- Time: 10 @@ -935,7 +935,7 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.200e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = -1.274e-19 + Total alkalinity (eq/kg) = 7.751e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 Electrical balance (eq) = -7.020e-16 @@ -989,7 +989,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 2.659 Seconds. +End of Run after 0.612 Seconds. ------------------------------- Time: 10 @@ -1047,7 +1047,7 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.200e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = 4.509e-18 + Total alkalinity (eq/kg) = 4.523e-18 Temperature (°C) = 20.00 Pressure (atm) = 2.00 Electrical balance (eq) = 7.519e-13 @@ -1101,7 +1101,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 2.662 Seconds. +End of Run after 0.612 Seconds. ------------------------------- Time: 10 @@ -1159,7 +1159,7 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.200e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = 1.023e-18 + Total alkalinity (eq/kg) = 6.863e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 Electrical balance (eq) = 1.445e-13 @@ -1213,7 +1213,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 2.664 Seconds. +End of Run after 0.612 Seconds. ------------------------------- Time: 10 @@ -1269,10 +1269,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.200e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = -9.905e-19 + Total alkalinity (eq/kg) = -1.143e-18 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = -1.555e-17 + Electrical balance (eq) = -1.553e-17 Percent error, 100*(Cat-|An|)/(Cat+|An|) = -0.00 Iterations = 2 Total H = 2.213642e+01 @@ -1320,7 +1320,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 2.667 Seconds. +End of Run after 0.613 Seconds. ------------------------------- Time: 10 @@ -1435,7 +1435,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 2.661 Seconds. +End of Run after 0.613 Seconds. ------------------------------- Time: 10 @@ -1550,7 +1550,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 2.663 Seconds. +End of Run after 0.612 Seconds. ------------------------------- Time: 10 @@ -1665,7 +1665,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 2.665 Seconds. +End of Run after 0.612 Seconds. ------------------------------- Time: 10 @@ -1780,7 +1780,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 2.668 Seconds. +End of Run after 0.612 Seconds. ------------------------------- Time: 10 @@ -1894,9 +1894,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 2.67 Seconds. ------------------------------- +------------------------------- +End of Run after 0.613 Seconds. +------------------------------- Time: 10 Chemistry cell: 15 @@ -2010,7 +2010,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 2.672 Seconds. +End of Run after 0.613 Seconds. ------------------------------- Time: 10 @@ -2125,7 +2125,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 2.676 Seconds. +End of Run after 0.613 Seconds. ------------------------------- Time: 10 @@ -2239,9 +2239,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 2.68 Seconds. ------------------------------- +------------------------------- +End of Run after 0.613 Seconds. +------------------------------- Time: 10 Chemistry cell: 18 @@ -2355,7 +2355,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 2.684 Seconds. +End of Run after 0.614 Seconds. ------------------------------- Time: 10 @@ -2470,6 +2470,6 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 2.687 Seconds. +End of Run after 0.614 Seconds. ------------------------------- diff --git a/Tests/Output/SimpleAdvect_cpp.chem.txt b/Tests/Output/SimpleAdvect_cpp.chem.txt index 2da8b8932..7a9aef81d 100644 --- a/Tests/Output/SimpleAdvect_cpp.chem.txt +++ b/Tests/Output/SimpleAdvect_cpp.chem.txt @@ -196,7 +196,7 @@ Reading input data for simulation 4. ------------------------------------ ------------------------------- -End of Run after 1.548 Seconds. +End of Run after 0.175 Seconds. ------------------------------- H @@ -263,10 +263,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.800e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = -4.978e-22 + Total alkalinity (eq/kg) = -8.678e-21 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = 1.075e-18 + Electrical balance (eq) = 1.077e-18 Percent error, 100*(Cat-|An|)/(Cat+|An|) = 0.00 Iterations = 2 Total H = 2.213642e+01 @@ -317,7 +317,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 1.876 Seconds. +End of Run after 0.206 Seconds. ------------------------------- Time: 10 @@ -375,10 +375,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.800e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = -1.954e-19 + Total alkalinity (eq/kg) = -5.106e-20 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = 8.407e-19 + Electrical balance (eq) = 7.850e-19 Percent error, 100*(Cat-|An|)/(Cat+|An|) = 0.00 Iterations = 5 Total H = 2.213642e+01 @@ -429,7 +429,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 1.879 Seconds. +End of Run after 0.207 Seconds. ------------------------------- Time: 10 @@ -487,10 +487,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.800e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = 1.656e-19 + Total alkalinity (eq/kg) = 3.834e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = 8.968e-19 + Electrical balance (eq) = 8.537e-19 Percent error, 100*(Cat-|An|)/(Cat+|An|) = 0.00 Iterations = 6 Total H = 2.213642e+01 @@ -541,7 +541,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 1.882 Seconds. +End of Run after 0.207 Seconds. ------------------------------- Time: 10 @@ -599,10 +599,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.800e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = 1.009e-18 + Total alkalinity (eq/kg) = 1.771e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = 5.877e-18 + Electrical balance (eq) = 6.041e-18 Percent error, 100*(Cat-|An|)/(Cat+|An|) = 0.00 Iterations = 6 Total H = 2.213642e+01 @@ -653,7 +653,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 1.885 Seconds. +End of Run after 0.208 Seconds. ------------------------------- Time: 10 @@ -711,7 +711,7 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.758e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = 5.691e-19 + Total alkalinity (eq/kg) = 5.826e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 Electrical balance (eq) = 2.786e-16 @@ -765,7 +765,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 1.889 Seconds. +End of Run after 0.209 Seconds. ------------------------------- Time: 10 @@ -823,7 +823,7 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.211e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = -4.274e-19 + Total alkalinity (eq/kg) = 3.295e-20 Temperature (°C) = 20.00 Pressure (atm) = 2.00 Electrical balance (eq) = 9.176e-14 @@ -877,7 +877,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 1.876 Seconds. +End of Run after 0.209 Seconds. ------------------------------- Time: 10 @@ -935,7 +935,7 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.200e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = -1.274e-19 + Total alkalinity (eq/kg) = 7.751e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 Electrical balance (eq) = -7.020e-16 @@ -989,7 +989,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------ -End of Run after 1.88 Seconds. +End of Run after 0.21 Seconds. ------------------------------ Time: 10 @@ -1047,7 +1047,7 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.200e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = 4.509e-18 + Total alkalinity (eq/kg) = 4.523e-18 Temperature (°C) = 20.00 Pressure (atm) = 2.00 Electrical balance (eq) = 7.519e-13 @@ -1101,7 +1101,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 1.884 Seconds. +End of Run after 0.206 Seconds. ------------------------------- Time: 10 @@ -1159,7 +1159,7 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.200e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = 1.023e-18 + Total alkalinity (eq/kg) = 6.863e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 Electrical balance (eq) = 1.445e-13 @@ -1213,7 +1213,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 1.889 Seconds. +End of Run after 0.206 Seconds. ------------------------------- Time: 10 @@ -1269,10 +1269,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.200e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = -9.905e-19 + Total alkalinity (eq/kg) = -1.143e-18 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = -1.555e-17 + Electrical balance (eq) = -1.553e-17 Percent error, 100*(Cat-|An|)/(Cat+|An|) = -0.00 Iterations = 2 Total H = 2.213642e+01 @@ -1320,7 +1320,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 1.875 Seconds. +End of Run after 0.207 Seconds. ------------------------------- Time: 10 @@ -1435,7 +1435,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 1.882 Seconds. +End of Run after 0.207 Seconds. ------------------------------- Time: 10 @@ -1550,7 +1550,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 1.886 Seconds. +End of Run after 0.207 Seconds. ------------------------------- Time: 10 @@ -1664,9 +1664,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 1.89 Seconds. ------------------------------- +------------------------------- +End of Run after 0.206 Seconds. +------------------------------- Time: 10 Chemistry cell: 13 @@ -1780,7 +1780,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 1.893 Seconds. +End of Run after 0.206 Seconds. ------------------------------- Time: 10 @@ -1895,7 +1895,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 1.895 Seconds. +End of Run after 0.207 Seconds. ------------------------------- Time: 10 @@ -2010,7 +2010,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 1.897 Seconds. +End of Run after 0.207 Seconds. ------------------------------- Time: 10 @@ -2125,7 +2125,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 1.899 Seconds. +End of Run after 0.207 Seconds. ------------------------------- Time: 10 @@ -2240,7 +2240,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 1.902 Seconds. +End of Run after 0.207 Seconds. ------------------------------- Time: 10 @@ -2355,7 +2355,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 1.905 Seconds. +End of Run after 0.208 Seconds. ------------------------------- Time: 10 @@ -2470,6 +2470,6 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 1.907 Seconds. +End of Run after 0.208 Seconds. ------------------------------- diff --git a/Tests/Output/SimpleAdvect_f90.chem.txt b/Tests/Output/SimpleAdvect_f90.chem.txt index 7e0bfc418..b3efb028a 100644 --- a/Tests/Output/SimpleAdvect_f90.chem.txt +++ b/Tests/Output/SimpleAdvect_f90.chem.txt @@ -195,9 +195,9 @@ End of simulation. Reading input data for simulation 4. ------------------------------------ --------------------------------- -End of Run after 11.351 Seconds. --------------------------------- +------------------------------- +End of Run after 1.594 Seconds. +------------------------------- H O @@ -262,10 +262,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.800e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = 3.269e-20 + Total alkalinity (eq/kg) = 3.124e-20 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = 1.044e-18 + Electrical balance (eq) = 1.045e-18 Percent error, 100*(Cat-|An|)/(Cat+|An|) = 0.00 Iterations = 2 Total H = 2.213642e+01 @@ -315,9 +315,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ --------------------------------- -End of Run after 11.758 Seconds. --------------------------------- +------------------------------- +End of Run after 1.621 Seconds. +------------------------------- Time: 10 Chemistry cell: 1 @@ -374,10 +374,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.800e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = -4.570e-20 + Total alkalinity (eq/kg) = 1.225e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = 7.899e-19 + Electrical balance (eq) = 7.565e-19 Percent error, 100*(Cat-|An|)/(Cat+|An|) = 0.00 Iterations = 5 Total H = 2.213642e+01 @@ -427,9 +427,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ --------------------------------- -End of Run after 11.762 Seconds. --------------------------------- +------------------------------- +End of Run after 1.622 Seconds. +------------------------------- Time: 10 Chemistry cell: 2 @@ -486,10 +486,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.800e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = 4.616e-19 + Total alkalinity (eq/kg) = 4.255e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = 1.099e-18 + Electrical balance (eq) = 1.106e-18 Percent error, 100*(Cat-|An|)/(Cat+|An|) = 0.00 Iterations = 6 Total H = 2.213642e+01 @@ -539,9 +539,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ --------------------------------- -End of Run after 11.766 Seconds. --------------------------------- +------------------------------- +End of Run after 1.622 Seconds. +------------------------------- Time: 10 Chemistry cell: 3 @@ -598,10 +598,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.800e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = 2.028e-19 + Total alkalinity (eq/kg) = 3.874e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = 6.271e-18 + Electrical balance (eq) = 6.016e-18 Percent error, 100*(Cat-|An|)/(Cat+|An|) = 0.00 Iterations = 6 Total H = 2.213642e+01 @@ -652,7 +652,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 11.77 Seconds. +End of Run after 1.623 Seconds. ------------------------------- Time: 10 @@ -710,10 +710,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.758e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = -1.165e-19 + Total alkalinity (eq/kg) = 2.763e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = 2.787e-16 + Electrical balance (eq) = 2.788e-16 Percent error, 100*(Cat-|An|)/(Cat+|An|) = 0.00 Iterations = 7 Total H = 2.213642e+01 @@ -763,9 +763,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ --------------------------------- -End of Run after 11.774 Seconds. --------------------------------- +------------------------------- +End of Run after 1.623 Seconds. +------------------------------- Time: 10 Chemistry cell: 5 @@ -822,7 +822,7 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.211e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = 5.682e-19 + Total alkalinity (eq/kg) = 3.368e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 Electrical balance (eq) = 9.176e-14 @@ -875,9 +875,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ --------------------------------- -End of Run after 11.777 Seconds. --------------------------------- +------------------------------- +End of Run after 1.621 Seconds. +------------------------------- Time: 10 Chemistry cell: 6 @@ -934,10 +934,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.200e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = -5.324e-19 + Total alkalinity (eq/kg) = 3.480e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = -7.021e-16 + Electrical balance (eq) = -7.020e-16 Percent error, 100*(Cat-|An|)/(Cat+|An|) = -0.00 Iterations = 6 Total H = 2.213642e+01 @@ -987,9 +987,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ --------------------------------- -End of Run after 11.758 Seconds. --------------------------------- +------------------------------- +End of Run after 1.622 Seconds. +------------------------------- Time: 10 Chemistry cell: 7 @@ -1046,7 +1046,7 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.200e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = 3.894e-18 + Total alkalinity (eq/kg) = 4.161e-18 Temperature (°C) = 20.00 Pressure (atm) = 2.00 Electrical balance (eq) = 7.519e-13 @@ -1099,9 +1099,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ --------------------------------- -End of Run after 11.762 Seconds. --------------------------------- +------------------------------- +End of Run after 1.622 Seconds. +------------------------------- Time: 10 Chemistry cell: 8 @@ -1158,7 +1158,7 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.200e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = -3.445e-19 + Total alkalinity (eq/kg) = -3.420e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 Electrical balance (eq) = 1.445e-13 @@ -1211,9 +1211,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ --------------------------------- -End of Run after 11.765 Seconds. --------------------------------- +------------------------------- +End of Run after 1.623 Seconds. +------------------------------- Time: 10 Chemistry cell: 9 @@ -1268,7 +1268,7 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.200e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = 2.102e-19 + Total alkalinity (eq/kg) = 2.175e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 Electrical balance (eq) = -1.555e-17 @@ -1319,7 +1319,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 11.77 Seconds. +End of Run after 1.623 Seconds. ------------------------------- Time: 10 @@ -1433,9 +1433,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ --------------------------------- -End of Run after 11.775 Seconds. --------------------------------- +------------------------------- +End of Run after 1.622 Seconds. +------------------------------- Time: 10 Chemistry cell: 11 @@ -1548,9 +1548,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ --------------------------------- -End of Run after 11.758 Seconds. --------------------------------- +------------------------------- +End of Run after 1.622 Seconds. +------------------------------- Time: 10 Chemistry cell: 12 @@ -1663,9 +1663,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ --------------------------------- -End of Run after 11.762 Seconds. --------------------------------- +------------------------------- +End of Run after 1.623 Seconds. +------------------------------- Time: 10 Chemistry cell: 13 @@ -1778,9 +1778,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ --------------------------------- -End of Run after 11.766 Seconds. --------------------------------- +------------------------------- +End of Run after 1.623 Seconds. +------------------------------- Time: 10 Chemistry cell: 14 @@ -1893,9 +1893,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ --------------------------------- -End of Run after 11.769 Seconds. --------------------------------- +------------------------------- +End of Run after 1.623 Seconds. +------------------------------- Time: 10 Chemistry cell: 15 @@ -2008,9 +2008,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ --------------------------------- -End of Run after 11.773 Seconds. --------------------------------- +------------------------------- +End of Run after 1.623 Seconds. +------------------------------- Time: 10 Chemistry cell: 16 @@ -2123,9 +2123,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ --------------------------------- -End of Run after 11.776 Seconds. --------------------------------- +------------------------------- +End of Run after 1.624 Seconds. +------------------------------- Time: 10 Chemistry cell: 17 @@ -2238,9 +2238,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ --------------------------------- -End of Run after 11.779 Seconds. --------------------------------- +------------------------------- +End of Run after 1.624 Seconds. +------------------------------- Time: 10 Chemistry cell: 18 @@ -2353,9 +2353,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ --------------------------------- -End of Run after 11.782 Seconds. --------------------------------- +------------------------------- +End of Run after 1.624 Seconds. +------------------------------- Time: 10 Chemistry cell: 19 @@ -2468,7 +2468,7 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ --------------------------------- -End of Run after 11.785 Seconds. --------------------------------- +------------------------------- +End of Run after 1.625 Seconds. +------------------------------- diff --git a/Tests/Output/Species_c.chem.txt b/Tests/Output/Species_c.chem.txt index 785e6a981..414711754 100644 --- a/Tests/Output/Species_c.chem.txt +++ b/Tests/Output/Species_c.chem.txt @@ -196,7 +196,7 @@ Reading input data for simulation 4. ------------------------------------ ------------------------------- -End of Run after 7.664 Seconds. +End of Run after 1.356 Seconds. ------------------------------- Number of threads: 3 @@ -320,10 +320,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.800e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = 3.946e-20 + Total alkalinity (eq/kg) = 3.124e-20 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = 1.067e-18 + Electrical balance (eq) = 1.069e-18 Percent error, 100*(Cat-|An|)/(Cat+|An|) = 0.00 Iterations = 2 Total H = 2.213642e+01 @@ -374,7 +374,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 8.174 Seconds. +End of Run after 1.386 Seconds. ------------------------------- Time: 10 @@ -432,10 +432,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.800e-03 Mass of water (kg) = 1.996e-01 - Total alkalinity (eq/kg) = -2.501e-19 + Total alkalinity (eq/kg) = -2.590e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = 8.120e-19 + Electrical balance (eq) = 8.138e-19 Percent error, 100*(Cat-|An|)/(Cat+|An|) = 0.00 Iterations = 5 Total H = 2.216319e+01 @@ -486,7 +486,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 8.178 Seconds. +End of Run after 1.387 Seconds. ------------------------------- Time: 10 @@ -544,10 +544,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.800e-03 Mass of water (kg) = 1.996e-01 - Total alkalinity (eq/kg) = -3.510e-19 + Total alkalinity (eq/kg) = -3.090e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = 1.167e-18 + Electrical balance (eq) = 1.159e-18 Percent error, 100*(Cat-|An|)/(Cat+|An|) = 0.00 Iterations = 6 Total H = 2.216319e+01 @@ -598,7 +598,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 8.181 Seconds. +End of Run after 1.387 Seconds. ------------------------------- Time: 10 @@ -656,10 +656,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.800e-03 Mass of water (kg) = 1.996e-01 - Total alkalinity (eq/kg) = 4.709e-19 + Total alkalinity (eq/kg) = 3.679e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = 6.374e-18 + Electrical balance (eq) = 6.394e-18 Percent error, 100*(Cat-|An|)/(Cat+|An|) = 0.00 Iterations = 6 Total H = 2.216319e+01 @@ -710,7 +710,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 8.185 Seconds. +End of Run after 1.388 Seconds. ------------------------------- Time: 10 @@ -768,10 +768,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.759e-03 Mass of water (kg) = 1.996e-01 - Total alkalinity (eq/kg) = 2.829e-19 + Total alkalinity (eq/kg) = 2.740e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = 2.795e-16 + Electrical balance (eq) = 2.793e-16 Percent error, 100*(Cat-|An|)/(Cat+|An|) = 0.00 Iterations = 7 Total H = 2.216319e+01 @@ -822,7 +822,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 8.189 Seconds. +End of Run after 1.388 Seconds. ------------------------------- Time: 10 @@ -880,7 +880,7 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.211e-03 Mass of water (kg) = 1.996e-01 - Total alkalinity (eq/kg) = 1.398e-18 + Total alkalinity (eq/kg) = 1.021e-18 Temperature (°C) = 20.00 Pressure (atm) = 2.00 Electrical balance (eq) = 1.029e-13 @@ -934,7 +934,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 8.175 Seconds. +End of Run after 1.386 Seconds. ------------------------------- Time: 10 @@ -992,10 +992,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.200e-03 Mass of water (kg) = 1.996e-01 - Total alkalinity (eq/kg) = -9.207e-19 + Total alkalinity (eq/kg) = -6.978e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = -7.169e-16 + Electrical balance (eq) = -7.168e-16 Percent error, 100*(Cat-|An|)/(Cat+|An|) = -0.00 Iterations = 6 Total H = 2.216281e+01 @@ -1045,9 +1045,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 8.18 Seconds. ------------------------------- +------------------------------- +End of Run after 1.387 Seconds. +------------------------------- Time: 10 Chemistry cell: 7 @@ -1104,7 +1104,7 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.200e-03 Mass of water (kg) = 1.996e-01 - Total alkalinity (eq/kg) = 4.349e-18 + Total alkalinity (eq/kg) = 4.418e-18 Temperature (°C) = 20.00 Pressure (atm) = 2.00 Electrical balance (eq) = 7.587e-13 @@ -1158,7 +1158,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 8.184 Seconds. +End of Run after 1.387 Seconds. ------------------------------- Time: 10 @@ -1216,7 +1216,7 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.200e-03 Mass of water (kg) = 1.996e-01 - Total alkalinity (eq/kg) = 6.109e-19 + Total alkalinity (eq/kg) = 3.444e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 Electrical balance (eq) = 1.476e-13 @@ -1270,7 +1270,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 8.188 Seconds. +End of Run after 1.388 Seconds. ------------------------------- Time: 10 @@ -1326,7 +1326,7 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.200e-03 Mass of water (kg) = 1.996e-01 - Total alkalinity (eq/kg) = -3.858e-19 + Total alkalinity (eq/kg) = -3.774e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 Electrical balance (eq) = -1.856e-17 @@ -1377,7 +1377,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 8.192 Seconds. +End of Run after 1.388 Seconds. ------------------------------- Time: 10 @@ -1492,7 +1492,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 8.173 Seconds. +End of Run after 1.386 Seconds. ------------------------------- Time: 10 @@ -1607,7 +1607,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 8.178 Seconds. +End of Run after 1.387 Seconds. ------------------------------- Time: 10 @@ -1722,7 +1722,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 8.183 Seconds. +End of Run after 1.388 Seconds. ------------------------------- Time: 10 @@ -1837,7 +1837,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 8.188 Seconds. +End of Run after 1.388 Seconds. ------------------------------- Time: 10 @@ -1952,7 +1952,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 8.192 Seconds. +End of Run after 1.388 Seconds. ------------------------------- Time: 10 @@ -2067,7 +2067,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 8.195 Seconds. +End of Run after 1.389 Seconds. ------------------------------- Time: 10 @@ -2181,9 +2181,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ -------------------------------- -End of Run after 8.197 Seconds. -------------------------------- +------------------------------ +End of Run after 1.39 Seconds. +------------------------------ Time: 10 Chemistry cell: 17 @@ -2296,9 +2296,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ ------------------------------ -End of Run after 8.2 Seconds. ------------------------------ +------------------------------- +End of Run after 1.391 Seconds. +------------------------------- Time: 10 Chemistry cell: 18 @@ -2412,7 +2412,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 8.203 Seconds. +End of Run after 1.391 Seconds. ------------------------------- Time: 10 @@ -2527,6 +2527,6 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 8.205 Seconds. +End of Run after 1.392 Seconds. ------------------------------- diff --git a/Tests/Output/Species_c.dmp b/Tests/Output/Species_c.dmp index 075126dbb..1bb215ef1 100644 --- a/Tests/Output/Species_c.dmp +++ b/Tests/Output/Species_c.dmp @@ -4,7 +4,7 @@ -potential 0 -total_h 22.136415505852 -total_o 11.068314447308 - -cb 1.0672118827037e-18 + -cb 1.0688397741492e-18 -density 0.99830524784931 -totals Ca 0.0001196428982687 @@ -17,7 +17,7 @@ -ah2o 0.99996484900903 -mass_water 0.19940483056363 -soln_vol 0.19975835757967 - -total_alkalinity 7.8681419866044e-21 + -total_alkalinity 6.2303243737494e-21 -activities Ca -3.3018013654974 Cl -2.9412141501733 @@ -29,16 +29,16 @@ -gammas -species_map 28 0.00059893709687918 - 34 1.0387679456948e-09 + 34 1.0387679456947e-09 63 0.0011978762715883 - 118 8.6997192838593e-08 + 118 8.6997192838597e-08 119 0 121 55.407983273659 178 2.9410943074934e-13 216 2.5173245006726e-19 - 221 1.9728267683721e-36 + 221 1.972826768372e-36 225 0.00026705861804021 - 226 8.5958424892938e-08 + 226 8.5958424892934e-08 -log_gamma_map 28 -0.079951862409805 34 -0.020310467757975 @@ -55,7 +55,7 @@ 28 -3.2218495030876 34 -8.9827121765703 63 -2.920818754098 - 118 -7.0597254769237 + 118 -7.0597254769236 119 -45.225006779998 121 -1.5266149722127e-05 178 -12.530721765698 @@ -69,7 +69,7 @@ -potential 0 -total_h 22.163193344261 -total_o 11.081703495578 - -cb 8.1204651606576e-19 + -cb 8.1381668257662e-19 -density 0.9983052478494 -totals Ca 0.00011978762070388 @@ -82,7 +82,7 @@ -ah2o 0.99996484900849 -mass_water 0.19964604533164 -soln_vol 0.20000000000022 - -total_alkalinity -4.9925313051251e-20 + -total_alkalinity -5.1705405729465e-20 -activities Ca -3.3018013881279 Cl -2.94121415 @@ -94,16 +94,16 @@ -gammas -species_map 28 0.00059893706475084 - 34 1.0387678915019e-09 + 34 1.0387678915018e-09 63 0.001197876271587 - 118 8.6997192778913e-08 + 118 8.6997192778918e-08 119 0 121 55.407983273596 178 6.4549103997718e-11 216 4.2051407471526e-16 - 221 3.2955680662589e-33 + 221 3.2955680662587e-33 225 0.0002670586180417 - 226 8.5958424887162e-08 + 226 8.5958424887157e-08 -log_gamma_map 28 -0.079951861744341 34 -0.020310467586335 @@ -134,20 +134,20 @@ -potential 0 -total_h 22.163193343984 -total_o 11.081703495439 - -cb 1.1672775757654e-18 + -cb 1.158932977746e-18 -density 0.99830524786068 -totals Ca 0.00011978678400211 Cl 0.00023957525431466 K 1.6862061887295e-09 Na 1.0424816621896e-13 - -pH 7.0787960689485 + -pH 7.0787960689486 -pe 13.969354438095 -mu 0.0018000808463647 -ah2o 0.99996484893724 -mass_water 0.19964604532914 -soln_vol 0.2000000000274 - -total_alkalinity -7.0082050217943e-20 + -total_alkalinity -6.1687821361755e-20 -activities Ca -3.3018043349734 Cl -2.941214127436 @@ -159,16 +159,16 @@ -gammas -species_map 28 0.00059893288116766 - 34 1.0387608350181e-09 + 34 1.0387608350183e-09 63 0.0011978762714092 - 118 8.6997184988903e-08 + 118 8.6997184988882e-08 119 0 121 55.407983265371 178 8.4310309424923e-09 216 5.2124083102337e-13 - 221 4.0849638691088e-30 - 225 0.0002670586180054 - 226 8.5958424153534e-08 + 221 4.0849638691098e-30 + 225 0.00026705861800541 + 226 8.5958424153555e-08 -log_gamma_map 28 -0.079951775091035 34 -0.020310445236317 @@ -183,36 +183,36 @@ 226 -0.020461180246083 -log_molalities_map 28 -3.2218525598823 - 34 -8.9827151493909 + 34 -8.9827151493908 63 -2.920818754098 - 118 -7.0597255160448 + 118 -7.0597255160449 119 -45.2250067794 121 -1.5266180902365e-05 178 -8.0733500330121 216 -12.282192287692 - 221 -29.388042496593 + 221 -29.388042496592 225 -3.5726241189557 - 226 -7.0649422710888 + 226 -7.0649422710887 SOLUTION_RAW 3 Solution after simulation 1. -temp 20 -pressure 2 -potential 0 -total_h 22.163193308929 -total_o 11.081703477912 - -cb 6.3737045524069e-18 + -cb 6.3941623833166e-18 -density 0.99830524887905 -totals Ca 0.0001196988835515 Cl 0.00023957525393573 K 1.7736475327239e-07 Na 1.2207945707724e-10 - -pH 7.0787980753021 + -pH 7.0787980753019 -pe 13.969352422362 -mu 0.0017996405665282 -ah2o 0.99996484145249 -mass_water 0.19964604501337 -soln_vol 0.20000000286188 - -total_alkalinity 9.4007422255426e-20 + -total_alkalinity 7.3440403504908e-20 -activities Ca -3.3021140357943 Cl -2.9412117567921 @@ -224,16 +224,16 @@ -gammas -species_map 28 0.00059849337117391 - 34 1.0380195046585e-09 + 34 1.0380195046579e-09 63 0.0011978762525378 - 118 8.6996366452149e-08 + 118 8.69963664522e-08 119 0 121 55.407982392471 178 8.8682375367203e-07 216 6.1039727665178e-10 - 221 4.7837308807761e-27 + 221 4.7837308807733e-27 225 0.00026705861380309 - 226 8.5958346947961e-08 + 226 8.595834694791e-08 -log_gamma_map 28 -0.079942671013776 34 -0.020308097074793 @@ -248,36 +248,36 @@ 226 -0.020458793913119 -log_molalities_map 28 -3.2221713647806 - 34 -8.9830251952705 + 34 -8.9830251952707 63 -2.920818754098 - 118 -7.0597295954002 + 118 -7.0597295954 119 -45.225006716613 121 -1.5269431603765e-05 178 -6.0513933921429 216 -9.2136181220636 - 221 -26.319463969883 + 221 -26.319463969884 225 -3.5726241189476 - 226 -7.0649426543189 + 226 -7.0649426543191 SOLUTION_RAW 4 Solution after simulation 1. -temp 20 -pressure 2 -potential 0 -total_h 22.163189663733 -total_o 11.081701655296 - -cb 2.7954750780964e-16 + -cb 2.793315441866e-16 -density 0.9983053411377 -totals Ca 0.00011155692478476 Cl 0.00023957521453264 K 1.6324039795999e-05 Na 1.3732516740036e-07 - -pH 7.078984313373 + -pH 7.0789843133729 -pe 13.969165315294 -mu 0.0017588587513626 -ah2o 0.999964148162 -mass_water 0.19964601217772 -soln_vol 0.2000002602005 - -total_alkalinity 5.6476583502671e-20 + -total_alkalinity 5.4703108269357e-20 -activities Ca -3.3318586843358 Cl -2.9409907725944 @@ -289,16 +289,16 @@ -gammas -species_map 28 0.00055778292901468 - 34 9.6923087435944e-10 + 34 9.6923087435939e-10 63 0.0011978745142255 - 118 8.69202306013e-08 + 118 8.6920230601305e-08 119 0 121 55.407901986594 178 8.1620092792052e-05 216 6.8662494370105e-07 - 221 5.3861626178648e-24 + 221 5.3861626178645e-24 225 0.00026705822625182 - 226 8.5950999727223e-08 + 226 8.5950999727219e-08 -log_gamma_map 28 -0.079093823721207 34 -0.02008919274014 @@ -323,6 +323,71 @@ 221 -23.267950617736 225 -3.572624118958 226 -7.0649791466463 + SOLUTION_RAW 5 Solution after simulation 1. + -temp 20 + -pressure 2 + -potential 0 + -total_h 22.162948776699 + -total_o 11.081581210618 + -cb 1.0286532152621e-13 + -density 0.99830599745848 + -totals + Ca 2.1789424969625e-06 + Cl 0.00023957261064281 + K 0.00021232055257124 + Na 2.2894173180509e-05 + -pH 7.0815712902218 + -pe 13.966566664474 + -mu 0.0012110000876024 + -ah2o 0.99995483457207 + -mass_water 0.19964384227126 + -soln_vol 0.20000176462488 + -total_alkalinity 2.0380737676572e-19 + -activities + Ca -5.0284103997467 + Cl -2.9376977710625 + E -13.966566664474 + H(0) -45.22480166662 + K -2.9901694145148 + Na -3.95724839021 + O(0) -3.5725030189783 + -gammas + -species_map + 28 1.0894596898392e-05 + 34 1.9461865001162e-11 + 63 0.0011978524844126 + 118 8.5824609739284e-08 + 119 0 + 121 55.406882994103 + 178 0.0010615933962856 + 216 0.00011446985592077 + 221 9.1014482447723e-22 + 225 0.0002670533148347 + 226 8.5805147875301e-08 + -log_gamma_map + 28 -0.066399473606212 + 34 -0.016823593711558 + 63 -0.016879016960186 + 118 -0.01596103544148 + 119 0.00012110000876024 + 121 0 + 178 -0.016905530757508 + 216 -0.01671743433463 + 221 0.00012110000876024 + 225 0.00012110000876024 + 226 -0.016923695758822 + -log_molalities_map + 28 -4.9620109261405 + 34 -10.710037636352 + 63 -2.9208187541023 + 118 -7.0656102547803 + 119 -45.224922766629 + 121 -1.9615539096873e-05 + 178 -2.9732638837573 + 216 -3.9405309558754 + 221 -21.04011158824 + 225 -3.5726241189871 + 226 -7.0657087479588 EXCHANGE_RAW 0 Exchange assemblage after simulation 1. # EXCHANGE_MODIFY candidate identifiers # -exchange_gammas 1 @@ -330,8 +395,8 @@ # EXCHANGE_MODIFY candidate identifiers # -totals Ca 0.00011000000007735 - K 5.5789786827676e-15 - Na 9.2458165879821e-22 + K 5.5789786827677e-15 + Na 9.2458165879822e-22 X 0.00022000000016027 -charge_balance 0 -la 1.2218455551817 @@ -423,91 +488,46 @@ -n_solution -999 # Exchange workspace variables # -totals - SOLUTION_RAW 5 Solution after simulation 1. - -temp 20 - -pressure 2 - -potential 0 - -total_h 22.162948776699 - -total_o 11.081581210618 - -cb 1.0286522969262e-13 - -density 0.99830599745848 + EXCHANGE_RAW 5 Exchange assemblage after simulation 1. + # EXCHANGE_MODIFY candidate identifiers # + -exchange_gammas 1 + -component X + # EXCHANGE_MODIFY candidate identifiers # + -totals + Ca 5.5744648454769e-05 + K 0.00010629152689824 + Na 2.2191763238232e-06 + X 0.0002200000001316 + -charge_balance 0 + -la 1.944331735805 + -phase_proportion 0 + -formula_z 0 + # EXCHANGE_MODIFY candidates with new_def=true # + -new_def 0 + -solution_equilibria 0 + -n_solution -999 + # Exchange workspace variables # -totals - Ca 2.1789424969625e-06 - Cl 0.00023957261064281 - K 0.00021232055257124 - Na 2.2894173180509e-05 - -pH 7.0815712902228 - -pe 13.966566664473 - -mu 0.0012110000876024 - -ah2o 0.99995483457207 - -mass_water 0.19964384227126 - -soln_vol 0.20000176462488 - -total_alkalinity 2.7906757761824e-19 - -activities - Ca -5.0284103997467 - Cl -2.9376977710625 - E -13.966566664473 - H(0) -45.22480166662 - K -2.9901694145148 - Na -3.95724839021 - O(0) -3.5725030189783 - -gammas - -species_map - 28 1.0894596898392e-05 - 34 1.9461865001205e-11 - 63 0.0011978524844126 - 118 8.5824609739096e-08 - 119 0 - 121 55.406882994103 - 178 0.0010615933962856 - 216 0.00011446985592077 - 221 9.1014482447923e-22 - 225 0.00026705331483471 - 226 8.5805147875489e-08 - -log_gamma_map - 28 -0.066399473606212 - 34 -0.016823593711558 - 63 -0.016879016960186 - 118 -0.01596103544148 - 119 0.00012110000876024 - 121 0 - 178 -0.016905530757508 - 216 -0.01671743433463 - 221 0.00012110000876024 - 225 0.00012110000876024 - 226 -0.016923695758822 - -log_molalities_map - 28 -4.9620109261405 - 34 -10.710037636351 - 63 -2.9208187541023 - 118 -7.0656102547813 - 119 -45.224922766629 - 121 -1.9615539096873e-05 - 178 -2.9732638837573 - 216 -3.9405309558754 - 221 -21.040111588239 - 225 -3.5726241189871 - 226 -7.0657087479578 SOLUTION_RAW 6 Solution after simulation 1. -temp 20 -pressure 2 -potential 0 -total_h 22.162814051683 -total_o 11.08151384746 - -cb -7.1685647037984e-16 + -cb -7.1677030132107e-16 -density 0.99830319874272 -totals - Ca 3.0770063517678e-11 + Ca 3.0770063517677e-11 Cl 0.0002395711543166 K 0.0001146139134111 Na 0.00012495717936466 - -pH 7.0816246296322 + -pH 7.0816246296327 -pe 13.966513092513 -mu 0.001200086108667 -ah2o 0.99995464903465 -mass_water 0.1996426286684 -soln_vol 0.19999954549488 - -total_alkalinity -1.8380614955418e-19 + -total_alkalinity -1.3930383259883e-19 -activities Ca -9.8782423055853 Cl -2.937624652283 @@ -519,16 +539,16 @@ -gammas -species_map 28 1.5385039221625e-10 - 34 2.7500171010732e-16 + 34 2.7500171010767e-16 63 0.0011978584937471 - 118 8.5801577531154e-08 + 118 8.5801577531043e-08 119 0 121 55.407160957595 178 0.0005730708693737 216 0.00062478731666847 - 221 4.9690985756583e-21 - 225 0.00026705465459975 - 226 8.5801577255229e-08 + 221 4.9690985756647e-21 + 225 0.00026705465459974 + 226 8.580157725534e-08 -log_gamma_map 28 -0.066116642519664 34 -0.016751009808874 @@ -545,34 +565,34 @@ 28 -9.8121256630657 34 -15.559888876299 63 -2.9208187541073 - 118 -7.0657289980367 + 118 -7.0657289980373 119 -45.22492121013 121 -1.9696120623295e-05 178 -3.2410159380693 216 -3.2034920661357 221 -20.302946658563 225 -3.5726241189538 - 226 -7.0657289994333 + 226 -7.0657289994328 SOLUTION_RAW 7 Solution after simulation 1. -temp 20 -pressure 2 -potential 0 -total_h 22.162929110459 -total_o 11.081571377403 - -cb 7.5870575412177e-13 + -cb 7.5870580138687e-13 -density 0.99830135953731 -totals Ca 1.8226464640498e-17 Cl 0.000239572398056 K 4.8149428626833e-05 Na 0.00019142297018784 - -pH 7.0816246304012 + -pH 7.0816246304014 -pe 13.966513091729 -mu 0.0012000859564438 -ah2o 0.99995464903196 -mass_water 0.19964366511785 -soln_vol 0.19999987954471 - -total_alkalinity 8.6818560987851e-19 + -total_alkalinity 8.8207893544695e-19 -activities Ca -16.105670511637 Cl -2.9376246512606 @@ -583,17 +603,17 @@ O(0) -3.5725041104048 -gammas -species_map - 28 9.1132215194016e-17 - 34 1.6289536138431e-22 + 28 9.1132215194017e-17 + 34 1.6289536138438e-22 63 0.0011978627117245 - 118 8.5801879328601e-08 + 118 8.5801879328566e-08 119 0 121 55.407356060892 178 0.00024074728813059 216 0.0009571154273873 - 221 7.6121918606964e-21 + 221 7.6121918606995e-21 225 0.00026705559494129 - 226 8.5801879332934e-08 + 226 8.5801879332968e-08 -log_gamma_map 28 -0.06611663856489 34 -0.016751008794 @@ -610,38 +630,38 @@ 28 -16.039553873072 34 -21.787317082581 63 -2.9208187541072 - 118 -7.0657289997204 + 118 -7.0657289997206 119 -45.224921210085 121 -1.9696121789103e-05 178 -3.6176643963109 216 -3.018261483559 221 -20.117716074193 225 -3.5726241190004 - 226 -7.0657289996985 + 226 -7.0657289996983 SOLUTION_RAW 8 Solution after simulation 1. -temp 20 -pressure 2 -potential 0 -total_h 22.162951281141 -total_o 11.081582462851 - -cb 1.4762040071978e-13 + -cb 1.4762023758653e-13 -density 0.99830112943876 -totals - Ca 3.6343034277183e-24 + Ca 3.6343034277184e-24 Cl 0.00023957263771222 K 3.9834209206973e-05 Na 0.00019973842865287 - -pH 7.0816246303923 - -pe 13.966513091744 + -pH 7.0816246303917 + -pe 13.966513091745 -mu 0.0012000859549133 -ah2o 0.99995464903202 -mass_water 0.19964386483136 -soln_vol 0.19999999150733 - -total_alkalinity 1.2196612695972e-19 + -total_alkalinity 6.8761869960308e-20 -activities Ca -22.805952199731 Cl -2.9376246512503 - E -13.966513091744 + E -13.966513091745 H(0) -45.224801201502 K -3.7168319491067 Na -3.0164400792113 @@ -649,16 +669,16 @@ -gammas -species_map 28 1.8171485429378e-23 - 34 3.2480837646132e-29 + 34 3.2480837646081e-29 63 0.0011978632394264 - 118 8.5801917127367e-08 + 118 8.58019171275e-08 119 0 121 55.407380469834 178 0.00019917105449233 216 0.00099869218567215 - 221 7.942862803801e-21 - 225 0.00026705571260414 - 226 8.5801917127969e-08 + 221 7.9428628037887e-21 + 225 0.00026705571260415 + 226 8.5801917127836e-08 -log_gamma_map 28 -0.066116638525128 34 -0.016751008783797 @@ -673,35 +693,35 @@ 226 -0.016850181701258 -log_molalities_map 28 -22.739835561206 - 34 -28.487598770694 + 34 -28.487598770695 63 -2.9208187541072 - 118 -7.0657289997207 + 118 -7.06572899972 119 -45.224921210097 121 -1.9696121766613e-05 178 -3.6999997686947 216 -2.9997943396725 - 221 -20.099248930305 + 221 -20.099248930306 225 -3.5726241189757 - 226 -7.0657289997177 + 226 -7.0657289997183 SOLUTION_RAW 9 Solution after simulation 1. -temp 20 -pressure 2 -potential 0 -total_h 22.162952787702 -total_o 11.081583216224 - -cb -1.8556708472941e-17 + -cb -1.8557548888443e-17 -density 0.99830111534656 -totals Cl 0.0002395726539976 K 3.9324934918955e-05 Na 0.00020024771907863 - -pH 7.0816246303907 + -pH 7.0816246303908 -pe 13.966513177942 -mu 0.0012000859545433 -ah2o 0.99995464902842 -mass_water 0.19964387840246 -soln_vol 0.19999999970769 - -total_alkalinity -7.7020441196038e-20 + -total_alkalinity -7.533630146888e-20 -activities Cl -2.9376246512477 E -13.966513177942 @@ -712,14 +732,14 @@ -gammas -species_map 63 0.0011978632717387 - 118 8.5801919441726e-08 + 118 8.5801919441722e-08 119 0 121 55.407381964433 178 0.00019662467488215 216 0.0010012385968565 - 221 7.9631150846907e-21 + 221 7.9631150846911e-21 225 0.00026705593182137 - 226 8.5801919441333e-08 + 226 8.5801919441338e-08 -log_gamma_map 63 -0.016805897140598 118 -0.015895630669395 @@ -732,7 +752,7 @@ 226 -0.016850181698759 -log_molalities_map 63 -2.9208187541071 - 118 -7.0657289997213 + 118 -7.0657289997214 119 -45.22492138249 121 -1.9696123329303e-05 178 -3.7055879855852 @@ -740,105 +760,6 @@ 221 -20.098143010822 225 -3.5726237741928 226 -7.0657289997233 - EXCHANGE_RAW 5 Exchange assemblage after simulation 1. - # EXCHANGE_MODIFY candidate identifiers # - -exchange_gammas 1 - -component X - # EXCHANGE_MODIFY candidate identifiers # - -totals - Ca 5.5744648454769e-05 - K 0.00010629152689824 - Na 2.2191763238232e-06 - X 0.0002200000001316 - -charge_balance 0 - -la 1.944331735805 - -phase_proportion 0 - -formula_z 0 - # EXCHANGE_MODIFY candidates with new_def=true # - -new_def 0 - -solution_equilibria 0 - -n_solution -999 - # Exchange workspace variables # - -totals - EXCHANGE_RAW 6 Exchange assemblage after simulation 1. - # EXCHANGE_MODIFY candidate identifiers # - -exchange_gammas 1 - -component X - # EXCHANGE_MODIFY candidate identifiers # - -totals - Ca 7.8889599963695e-09 - K 0.00018164031591582 - Na 3.8343906364582e-05 - X 0.0002200000002004 - -charge_balance 0 - -la 2.4447973951359 - -phase_proportion 0 - -formula_z 0 - # EXCHANGE_MODIFY candidates with new_def=true # - -new_def 0 - -solution_equilibria 0 - -n_solution -999 - # Exchange workspace variables # - -totals - EXCHANGE_RAW 7 Exchange assemblage after simulation 1. - # EXCHANGE_MODIFY candidate identifiers # - -exchange_gammas 1 - -component X - # EXCHANGE_MODIFY candidate identifiers # - -totals - Ca 1.2401487591103e-14 - K 0.00012430966894713 - Na 9.5690331159543e-05 - X 0.00022000000013147 - -charge_balance 0 - -la 2.6567385148108 - -phase_proportion 0 - -formula_z 0 - # EXCHANGE_MODIFY candidates with new_def=true # - -new_def 0 - -solution_equilibria 0 - -n_solution -999 - # Exchange workspace variables # - -totals - EXCHANGE_RAW 8 Exchange assemblage after simulation 1. - # EXCHANGE_MODIFY candidate identifiers # - -exchange_gammas 1 - -component X - # EXCHANGE_MODIFY candidate identifiers # - -totals - Ca 2.9132510369212e-21 - K 0.00011162525008285 - Na 0.00010837475004853 - X 0.00022000000013137 - -charge_balance 0 - -la 2.6923314222035 - -phase_proportion 0 - -formula_z 0 - # EXCHANGE_MODIFY candidates with new_def=true # - -new_def 0 - -solution_equilibria 0 - -n_solution -999 - # Exchange workspace variables # - -totals - EXCHANGE_RAW 9 Exchange assemblage after simulation 1. - # EXCHANGE_MODIFY candidate identifiers # - -exchange_gammas 1 - -component X - # EXCHANGE_MODIFY candidate identifiers # - -totals - K 0.00011077759538494 - Na 0.00010922240474649 - X 0.00022000000013143 - -charge_balance 0 - -la 2.6946091280289 - -phase_proportion 0 - -formula_z 0 - # EXCHANGE_MODIFY candidates with new_def=true # - -new_def 0 - -solution_equilibria 0 - -n_solution -999 - # Exchange workspace variables # - -totals SOLUTION_RAW 10 Solution after simulation 1. -temp 20 -pressure 2 @@ -983,6 +904,127 @@ 221 -20.098107260029 225 -3.5725641150874 226 -7.0657289998583 + EXCHANGE_RAW 6 Exchange assemblage after simulation 1. + # EXCHANGE_MODIFY candidate identifiers # + -exchange_gammas 1 + -component X + # EXCHANGE_MODIFY candidate identifiers # + -totals + Ca 7.8889599963695e-09 + K 0.00018164031591582 + Na 3.8343906364582e-05 + X 0.0002200000002004 + -charge_balance 0 + -la 2.4447973951359 + -phase_proportion 0 + -formula_z 0 + # EXCHANGE_MODIFY candidates with new_def=true # + -new_def 0 + -solution_equilibria 0 + -n_solution -999 + # Exchange workspace variables # + -totals + EXCHANGE_RAW 7 Exchange assemblage after simulation 1. + # EXCHANGE_MODIFY candidate identifiers # + -exchange_gammas 1 + -component X + # EXCHANGE_MODIFY candidate identifiers # + -totals + Ca 1.2401487591103e-14 + K 0.00012430966894713 + Na 9.5690331159543e-05 + X 0.00022000000013147 + -charge_balance 0 + -la 2.6567385148108 + -phase_proportion 0 + -formula_z 0 + # EXCHANGE_MODIFY candidates with new_def=true # + -new_def 0 + -solution_equilibria 0 + -n_solution -999 + # Exchange workspace variables # + -totals + EXCHANGE_RAW 8 Exchange assemblage after simulation 1. + # EXCHANGE_MODIFY candidate identifiers # + -exchange_gammas 1 + -component X + # EXCHANGE_MODIFY candidate identifiers # + -totals + Ca 2.9132510369212e-21 + K 0.00011162525008285 + Na 0.00010837475004853 + X 0.00022000000013137 + -charge_balance 0 + -la 2.6923314222035 + -phase_proportion 0 + -formula_z 0 + # EXCHANGE_MODIFY candidates with new_def=true # + -new_def 0 + -solution_equilibria 0 + -n_solution -999 + # Exchange workspace variables # + -totals + EXCHANGE_RAW 9 Exchange assemblage after simulation 1. + # EXCHANGE_MODIFY candidate identifiers # + -exchange_gammas 1 + -component X + # EXCHANGE_MODIFY candidate identifiers # + -totals + K 0.00011077759538494 + Na 0.00010922240474649 + X 0.00022000000013143 + -charge_balance 0 + -la 2.6946091280289 + -phase_proportion 0 + -formula_z 0 + # EXCHANGE_MODIFY candidates with new_def=true # + -new_def 0 + -solution_equilibria 0 + -n_solution -999 + # Exchange workspace variables # + -totals + EXCHANGE_RAW 10 Exchange assemblage after simulation 1. + # EXCHANGE_MODIFY candidate identifiers # + -exchange_gammas 1 + -component X + # EXCHANGE_MODIFY candidate identifiers # + -totals + H 1.5569735078322e-64 + K 0.0001107500084442 + N 3.8924337695805e-65 + Na 0.00010924999168717 + X 0.00022000000013137 + -charge_balance 0 + -la 2.6946830555387 + -phase_proportion 0 + -formula_z 0 + # EXCHANGE_MODIFY candidates with new_def=true # + -new_def 0 + -solution_equilibria 0 + -n_solution -999 + # Exchange workspace variables # + -totals + EXCHANGE_RAW 11 Exchange assemblage after simulation 1. + # EXCHANGE_MODIFY candidate identifiers # + -exchange_gammas 1 + -component X + # EXCHANGE_MODIFY candidate identifiers # + -totals + H 1.5569735078322e-64 + K 0.0001107500084442 + N 3.8924337695805e-65 + Na 0.00010924999168717 + X 0.00022000000013137 + -charge_balance 0 + -la 2.6946830555387 + -phase_proportion 0 + -formula_z 0 + # EXCHANGE_MODIFY candidates with new_def=true # + -new_def 0 + -solution_equilibria 0 + -n_solution -999 + # Exchange workspace variables # + -totals SOLUTION_RAW 12 Solution after simulation 1. -temp 20 -pressure 2 @@ -1559,48 +1601,6 @@ 221 -20.098107260029 225 -3.5725641150874 226 -7.0657289998583 - EXCHANGE_RAW 10 Exchange assemblage after simulation 1. - # EXCHANGE_MODIFY candidate identifiers # - -exchange_gammas 1 - -component X - # EXCHANGE_MODIFY candidate identifiers # - -totals - H 1.5569735078322e-64 - K 0.0001107500084442 - N 3.8924337695805e-65 - Na 0.00010924999168717 - X 0.00022000000013137 - -charge_balance 0 - -la 2.6946830555387 - -phase_proportion 0 - -formula_z 0 - # EXCHANGE_MODIFY candidates with new_def=true # - -new_def 0 - -solution_equilibria 0 - -n_solution -999 - # Exchange workspace variables # - -totals - EXCHANGE_RAW 11 Exchange assemblage after simulation 1. - # EXCHANGE_MODIFY candidate identifiers # - -exchange_gammas 1 - -component X - # EXCHANGE_MODIFY candidate identifiers # - -totals - H 1.5569735078322e-64 - K 0.0001107500084442 - N 3.8924337695805e-65 - Na 0.00010924999168717 - X 0.00022000000013137 - -charge_balance 0 - -la 2.6946830555387 - -phase_proportion 0 - -formula_z 0 - # EXCHANGE_MODIFY candidates with new_def=true # - -new_def 0 - -solution_equilibria 0 - -n_solution -999 - # Exchange workspace variables # - -totals EXCHANGE_RAW 12 Exchange assemblage after simulation 1. # EXCHANGE_MODIFY candidate identifiers # -exchange_gammas 1 diff --git a/Tests/Output/Species_c_utility.txt b/Tests/Output/Species_c_utility.txt index 46b844f3f..6fe21923b 100644 --- a/Tests/Output/Species_c_utility.txt +++ b/Tests/Output/Species_c_utility.txt @@ -37,7 +37,7 @@ Using solution 1. Activity of water = 1.000 Ionic strength (mol/kgw) = 1.500e-03 Mass of water (kg) = 9.982e-01 - Total alkalinity (eq/kg) = -9.221e-20 + Total alkalinity (eq/kg) = -9.539e-20 Temperature (°C) = 15.00 Pressure (atm) = 3.00 Electrical balance (eq) = -4.304e-17 @@ -91,6 +91,6 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 9.982 Seconds. +End of Run after 1.449 Seconds. ------------------------------- diff --git a/Tests/Output/Species_cpp.chem.txt b/Tests/Output/Species_cpp.chem.txt index 1738b1816..34f7aec58 100644 --- a/Tests/Output/Species_cpp.chem.txt +++ b/Tests/Output/Species_cpp.chem.txt @@ -196,7 +196,7 @@ Reading input data for simulation 4. ------------------------------------ ------------------------------- -End of Run after 5.989 Seconds. +End of Run after 0.758 Seconds. ------------------------------- Number of threads: 3 @@ -362,10 +362,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.800e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = 3.946e-20 + Total alkalinity (eq/kg) = 3.124e-20 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = 1.067e-18 + Electrical balance (eq) = 1.069e-18 Percent error, 100*(Cat-|An|)/(Cat+|An|) = 0.00 Iterations = 2 Total H = 2.213642e+01 @@ -416,7 +416,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 6.387 Seconds. +End of Run after 0.796 Seconds. ------------------------------- Time: 10 @@ -474,10 +474,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.800e-03 Mass of water (kg) = 1.996e-01 - Total alkalinity (eq/kg) = -2.501e-19 + Total alkalinity (eq/kg) = -2.590e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = 8.120e-19 + Electrical balance (eq) = 8.138e-19 Percent error, 100*(Cat-|An|)/(Cat+|An|) = 0.00 Iterations = 5 Total H = 2.216319e+01 @@ -528,7 +528,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 6.392 Seconds. +End of Run after 0.796 Seconds. ------------------------------- Time: 10 @@ -586,10 +586,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.800e-03 Mass of water (kg) = 1.996e-01 - Total alkalinity (eq/kg) = -3.510e-19 + Total alkalinity (eq/kg) = -3.090e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = 1.167e-18 + Electrical balance (eq) = 1.159e-18 Percent error, 100*(Cat-|An|)/(Cat+|An|) = 0.00 Iterations = 6 Total H = 2.216319e+01 @@ -640,7 +640,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 6.396 Seconds. +End of Run after 0.797 Seconds. ------------------------------- Time: 10 @@ -698,10 +698,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.800e-03 Mass of water (kg) = 1.996e-01 - Total alkalinity (eq/kg) = 4.709e-19 + Total alkalinity (eq/kg) = 3.679e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = 6.374e-18 + Electrical balance (eq) = 6.394e-18 Percent error, 100*(Cat-|An|)/(Cat+|An|) = 0.00 Iterations = 6 Total H = 2.216319e+01 @@ -751,9 +751,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ ------------------------------ -End of Run after 6.4 Seconds. ------------------------------ +------------------------------- +End of Run after 0.797 Seconds. +------------------------------- Time: 10 Chemistry cell: 4 @@ -810,10 +810,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.759e-03 Mass of water (kg) = 1.996e-01 - Total alkalinity (eq/kg) = 2.829e-19 + Total alkalinity (eq/kg) = 2.740e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = 2.795e-16 + Electrical balance (eq) = 2.793e-16 Percent error, 100*(Cat-|An|)/(Cat+|An|) = 0.00 Iterations = 7 Total H = 2.216319e+01 @@ -864,7 +864,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 6.405 Seconds. +End of Run after 0.797 Seconds. ------------------------------- Time: 10 @@ -922,7 +922,7 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.211e-03 Mass of water (kg) = 1.996e-01 - Total alkalinity (eq/kg) = 1.398e-18 + Total alkalinity (eq/kg) = 1.021e-18 Temperature (°C) = 20.00 Pressure (atm) = 2.00 Electrical balance (eq) = 1.029e-13 @@ -976,7 +976,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 6.408 Seconds. +End of Run after 0.796 Seconds. ------------------------------- Time: 10 @@ -1034,10 +1034,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.200e-03 Mass of water (kg) = 1.996e-01 - Total alkalinity (eq/kg) = -9.207e-19 + Total alkalinity (eq/kg) = -6.978e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = -7.169e-16 + Electrical balance (eq) = -7.168e-16 Percent error, 100*(Cat-|An|)/(Cat+|An|) = -0.00 Iterations = 6 Total H = 2.216281e+01 @@ -1088,7 +1088,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 6.387 Seconds. +End of Run after 0.797 Seconds. ------------------------------- Time: 10 @@ -1146,7 +1146,7 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.200e-03 Mass of water (kg) = 1.996e-01 - Total alkalinity (eq/kg) = 4.349e-18 + Total alkalinity (eq/kg) = 4.418e-18 Temperature (°C) = 20.00 Pressure (atm) = 2.00 Electrical balance (eq) = 7.587e-13 @@ -1200,7 +1200,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 6.391 Seconds. +End of Run after 0.797 Seconds. ------------------------------- Time: 10 @@ -1258,7 +1258,7 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.200e-03 Mass of water (kg) = 1.996e-01 - Total alkalinity (eq/kg) = 6.109e-19 + Total alkalinity (eq/kg) = 3.444e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 Electrical balance (eq) = 1.476e-13 @@ -1312,7 +1312,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 6.395 Seconds. +End of Run after 0.798 Seconds. ------------------------------- Time: 10 @@ -1368,7 +1368,7 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.200e-03 Mass of water (kg) = 1.996e-01 - Total alkalinity (eq/kg) = -3.858e-19 + Total alkalinity (eq/kg) = -3.774e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 Electrical balance (eq) = -1.856e-17 @@ -1418,9 +1418,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ ------------------------------ -End of Run after 6.4 Seconds. ------------------------------ +------------------------------- +End of Run after 0.798 Seconds. +------------------------------- Time: 10 Chemistry cell: 10 @@ -1534,7 +1534,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 6.405 Seconds. +End of Run after 0.799 Seconds. ------------------------------- Time: 10 @@ -1649,7 +1649,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 6.387 Seconds. +End of Run after 0.796 Seconds. ------------------------------- Time: 10 @@ -1764,7 +1764,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 6.391 Seconds. +End of Run after 0.796 Seconds. ------------------------------- Time: 10 @@ -1879,7 +1879,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 6.394 Seconds. +End of Run after 0.797 Seconds. ------------------------------- Time: 10 @@ -1994,7 +1994,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 6.398 Seconds. +End of Run after 0.797 Seconds. ------------------------------- Time: 10 @@ -2109,7 +2109,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 6.402 Seconds. +End of Run after 0.797 Seconds. ------------------------------- Time: 10 @@ -2224,7 +2224,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 6.407 Seconds. +End of Run after 0.797 Seconds. ------------------------------- Time: 10 @@ -2339,7 +2339,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 6.409 Seconds. +End of Run after 0.798 Seconds. ------------------------------- Time: 10 @@ -2454,7 +2454,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 6.413 Seconds. +End of Run after 0.798 Seconds. ------------------------------- Time: 10 @@ -2569,6 +2569,6 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 6.419 Seconds. +End of Run after 0.798 Seconds. ------------------------------- diff --git a/Tests/Output/Species_cpp.dmp b/Tests/Output/Species_cpp.dmp index 5b8ed8565..6a9f531dd 100644 --- a/Tests/Output/Species_cpp.dmp +++ b/Tests/Output/Species_cpp.dmp @@ -4,7 +4,7 @@ -potential 0 -total_h 22.136415505852 -total_o 11.068314447308 - -cb 1.0672118827037e-18 + -cb 1.0688397741492e-18 -density 0.99830524784931 -totals Ca 0.0001196428982687 @@ -17,7 +17,7 @@ -ah2o 0.99996484900903 -mass_water 0.19940483056363 -soln_vol 0.19975835757967 - -total_alkalinity 7.8681419866044e-21 + -total_alkalinity 6.2303243737494e-21 -activities Ca -3.3018013654974 Cl -2.9412141501733 @@ -29,16 +29,16 @@ -gammas -species_map 28 0.00059893709687918 - 34 1.0387679456948e-09 + 34 1.0387679456947e-09 63 0.0011978762715883 - 118 8.6997192838593e-08 + 118 8.6997192838597e-08 119 0 121 55.407983273659 178 2.9410943074934e-13 216 2.5173245006726e-19 - 221 1.9728267683721e-36 + 221 1.972826768372e-36 225 0.00026705861804021 - 226 8.5958424892938e-08 + 226 8.5958424892934e-08 -log_gamma_map 28 -0.079951862409805 34 -0.020310467757975 @@ -55,7 +55,7 @@ 28 -3.2218495030876 34 -8.9827121765703 63 -2.920818754098 - 118 -7.0597254769237 + 118 -7.0597254769236 119 -45.225006779998 121 -1.5266149722127e-05 178 -12.530721765698 @@ -69,7 +69,7 @@ -potential 0 -total_h 22.163193344261 -total_o 11.081703495578 - -cb 8.1204651606576e-19 + -cb 8.1381668257662e-19 -density 0.9983052478494 -totals Ca 0.00011978762070388 @@ -82,7 +82,7 @@ -ah2o 0.99996484900849 -mass_water 0.19964604533164 -soln_vol 0.20000000000022 - -total_alkalinity -4.9925313051251e-20 + -total_alkalinity -5.1705405729465e-20 -activities Ca -3.3018013881279 Cl -2.94121415 @@ -94,16 +94,16 @@ -gammas -species_map 28 0.00059893706475084 - 34 1.0387678915019e-09 + 34 1.0387678915018e-09 63 0.001197876271587 - 118 8.6997192778913e-08 + 118 8.6997192778918e-08 119 0 121 55.407983273596 178 6.4549103997718e-11 216 4.2051407471526e-16 - 221 3.2955680662589e-33 + 221 3.2955680662587e-33 225 0.0002670586180417 - 226 8.5958424887162e-08 + 226 8.5958424887157e-08 -log_gamma_map 28 -0.079951861744341 34 -0.020310467586335 @@ -134,20 +134,20 @@ -potential 0 -total_h 22.163193343984 -total_o 11.081703495439 - -cb 1.1672775757654e-18 + -cb 1.158932977746e-18 -density 0.99830524786068 -totals Ca 0.00011978678400211 Cl 0.00023957525431466 K 1.6862061887295e-09 Na 1.0424816621896e-13 - -pH 7.0787960689485 + -pH 7.0787960689486 -pe 13.969354438095 -mu 0.0018000808463647 -ah2o 0.99996484893724 -mass_water 0.19964604532914 -soln_vol 0.2000000000274 - -total_alkalinity -7.0082050217943e-20 + -total_alkalinity -6.1687821361755e-20 -activities Ca -3.3018043349734 Cl -2.941214127436 @@ -159,16 +159,16 @@ -gammas -species_map 28 0.00059893288116766 - 34 1.0387608350181e-09 + 34 1.0387608350183e-09 63 0.0011978762714092 - 118 8.6997184988903e-08 + 118 8.6997184988882e-08 119 0 121 55.407983265371 178 8.4310309424923e-09 216 5.2124083102337e-13 - 221 4.0849638691088e-30 - 225 0.0002670586180054 - 226 8.5958424153534e-08 + 221 4.0849638691098e-30 + 225 0.00026705861800541 + 226 8.5958424153555e-08 -log_gamma_map 28 -0.079951775091035 34 -0.020310445236317 @@ -183,36 +183,36 @@ 226 -0.020461180246083 -log_molalities_map 28 -3.2218525598823 - 34 -8.9827151493909 + 34 -8.9827151493908 63 -2.920818754098 - 118 -7.0597255160448 + 118 -7.0597255160449 119 -45.2250067794 121 -1.5266180902365e-05 178 -8.0733500330121 216 -12.282192287692 - 221 -29.388042496593 + 221 -29.388042496592 225 -3.5726241189557 - 226 -7.0649422710888 + 226 -7.0649422710887 SOLUTION_RAW 3 Solution after simulation 1. -temp 20 -pressure 2 -potential 0 -total_h 22.163193308929 -total_o 11.081703477912 - -cb 6.3737045524069e-18 + -cb 6.3941623833166e-18 -density 0.99830524887905 -totals Ca 0.0001196988835515 Cl 0.00023957525393573 K 1.7736475327239e-07 Na 1.2207945707724e-10 - -pH 7.0787980753021 + -pH 7.0787980753019 -pe 13.969352422362 -mu 0.0017996405665282 -ah2o 0.99996484145249 -mass_water 0.19964604501337 -soln_vol 0.20000000286188 - -total_alkalinity 9.4007422255426e-20 + -total_alkalinity 7.3440403504908e-20 -activities Ca -3.3021140357943 Cl -2.9412117567921 @@ -224,16 +224,16 @@ -gammas -species_map 28 0.00059849337117391 - 34 1.0380195046585e-09 + 34 1.0380195046579e-09 63 0.0011978762525378 - 118 8.6996366452149e-08 + 118 8.69963664522e-08 119 0 121 55.407982392471 178 8.8682375367203e-07 216 6.1039727665178e-10 - 221 4.7837308807761e-27 + 221 4.7837308807733e-27 225 0.00026705861380309 - 226 8.5958346947961e-08 + 226 8.595834694791e-08 -log_gamma_map 28 -0.079942671013776 34 -0.020308097074793 @@ -248,36 +248,36 @@ 226 -0.020458793913119 -log_molalities_map 28 -3.2221713647806 - 34 -8.9830251952705 + 34 -8.9830251952707 63 -2.920818754098 - 118 -7.0597295954002 + 118 -7.0597295954 119 -45.225006716613 121 -1.5269431603765e-05 178 -6.0513933921429 216 -9.2136181220636 - 221 -26.319463969883 + 221 -26.319463969884 225 -3.5726241189476 - 226 -7.0649426543189 + 226 -7.0649426543191 SOLUTION_RAW 4 Solution after simulation 1. -temp 20 -pressure 2 -potential 0 -total_h 22.163189663733 -total_o 11.081701655296 - -cb 2.7954750780964e-16 + -cb 2.793315441866e-16 -density 0.9983053411377 -totals Ca 0.00011155692478476 Cl 0.00023957521453264 K 1.6324039795999e-05 Na 1.3732516740036e-07 - -pH 7.078984313373 + -pH 7.0789843133729 -pe 13.969165315294 -mu 0.0017588587513626 -ah2o 0.999964148162 -mass_water 0.19964601217772 -soln_vol 0.2000002602005 - -total_alkalinity 5.6476583502671e-20 + -total_alkalinity 5.4703108269357e-20 -activities Ca -3.3318586843358 Cl -2.9409907725944 @@ -289,16 +289,16 @@ -gammas -species_map 28 0.00055778292901468 - 34 9.6923087435944e-10 + 34 9.6923087435939e-10 63 0.0011978745142255 - 118 8.69202306013e-08 + 118 8.6920230601305e-08 119 0 121 55.407901986594 178 8.1620092792052e-05 216 6.8662494370105e-07 - 221 5.3861626178648e-24 + 221 5.3861626178645e-24 225 0.00026705822625182 - 226 8.5950999727223e-08 + 226 8.5950999727219e-08 -log_gamma_map 28 -0.079093823721207 34 -0.02008919274014 @@ -329,24 +329,24 @@ -potential 0 -total_h 22.162948776699 -total_o 11.081581210618 - -cb 1.0286522969262e-13 + -cb 1.0286532152621e-13 -density 0.99830599745848 -totals Ca 2.1789424969625e-06 Cl 0.00023957261064281 K 0.00021232055257124 Na 2.2894173180509e-05 - -pH 7.0815712902228 - -pe 13.966566664473 + -pH 7.0815712902218 + -pe 13.966566664474 -mu 0.0012110000876024 -ah2o 0.99995483457207 -mass_water 0.19964384227126 -soln_vol 0.20000176462488 - -total_alkalinity 2.7906757761824e-19 + -total_alkalinity 2.0380737676572e-19 -activities Ca -5.0284103997467 Cl -2.9376977710625 - E -13.966566664473 + E -13.966566664474 H(0) -45.22480166662 K -2.9901694145148 Na -3.95724839021 @@ -354,16 +354,16 @@ -gammas -species_map 28 1.0894596898392e-05 - 34 1.9461865001205e-11 + 34 1.9461865001162e-11 63 0.0011978524844126 - 118 8.5824609739096e-08 + 118 8.5824609739284e-08 119 0 121 55.406882994103 178 0.0010615933962856 216 0.00011446985592077 - 221 9.1014482447923e-22 - 225 0.00026705331483471 - 226 8.5805147875489e-08 + 221 9.1014482447723e-22 + 225 0.0002670533148347 + 226 8.5805147875301e-08 -log_gamma_map 28 -0.066399473606212 34 -0.016823593711558 @@ -378,16 +378,16 @@ 226 -0.016923695758822 -log_molalities_map 28 -4.9620109261405 - 34 -10.710037636351 + 34 -10.710037636352 63 -2.9208187541023 - 118 -7.0656102547813 + 118 -7.0656102547803 119 -45.224922766629 121 -1.9615539096873e-05 178 -2.9732638837573 216 -3.9405309558754 - 221 -21.040111588239 + 221 -21.04011158824 225 -3.5726241189871 - 226 -7.0657087479578 + 226 -7.0657087479588 EXCHANGE_RAW 0 Exchange assemblage after simulation 1. # EXCHANGE_MODIFY candidate identifiers # -exchange_gammas 1 @@ -395,8 +395,8 @@ # EXCHANGE_MODIFY candidate identifiers # -totals Ca 0.00011000000007735 - K 5.5789786827676e-15 - Na 9.2458165879821e-22 + K 5.5789786827677e-15 + Na 9.2458165879822e-22 X 0.00022000000016027 -charge_balance 0 -la 1.2218455551817 @@ -514,20 +514,20 @@ -potential 0 -total_h 22.162814051683 -total_o 11.08151384746 - -cb -7.1685647037984e-16 + -cb -7.1677030132107e-16 -density 0.99830319874272 -totals - Ca 3.0770063517678e-11 + Ca 3.0770063517677e-11 Cl 0.0002395711543166 K 0.0001146139134111 Na 0.00012495717936466 - -pH 7.0816246296322 + -pH 7.0816246296327 -pe 13.966513092513 -mu 0.001200086108667 -ah2o 0.99995464903465 -mass_water 0.1996426286684 -soln_vol 0.19999954549488 - -total_alkalinity -1.8380614955418e-19 + -total_alkalinity -1.3930383259883e-19 -activities Ca -9.8782423055853 Cl -2.937624652283 @@ -539,16 +539,16 @@ -gammas -species_map 28 1.5385039221625e-10 - 34 2.7500171010732e-16 + 34 2.7500171010767e-16 63 0.0011978584937471 - 118 8.5801577531154e-08 + 118 8.5801577531043e-08 119 0 121 55.407160957595 178 0.0005730708693737 216 0.00062478731666847 - 221 4.9690985756583e-21 - 225 0.00026705465459975 - 226 8.5801577255229e-08 + 221 4.9690985756647e-21 + 225 0.00026705465459974 + 226 8.580157725534e-08 -log_gamma_map 28 -0.066116642519664 34 -0.016751009808874 @@ -565,34 +565,34 @@ 28 -9.8121256630657 34 -15.559888876299 63 -2.9208187541073 - 118 -7.0657289980367 + 118 -7.0657289980373 119 -45.22492121013 121 -1.9696120623295e-05 178 -3.2410159380693 216 -3.2034920661357 221 -20.302946658563 225 -3.5726241189538 - 226 -7.0657289994333 + 226 -7.0657289994328 SOLUTION_RAW 7 Solution after simulation 1. -temp 20 -pressure 2 -potential 0 -total_h 22.162929110459 -total_o 11.081571377403 - -cb 7.5870575412177e-13 + -cb 7.5870580138687e-13 -density 0.99830135953731 -totals Ca 1.8226464640498e-17 Cl 0.000239572398056 K 4.8149428626833e-05 Na 0.00019142297018784 - -pH 7.0816246304012 + -pH 7.0816246304014 -pe 13.966513091729 -mu 0.0012000859564438 -ah2o 0.99995464903196 -mass_water 0.19964366511785 -soln_vol 0.19999987954471 - -total_alkalinity 8.6818560987851e-19 + -total_alkalinity 8.8207893544695e-19 -activities Ca -16.105670511637 Cl -2.9376246512606 @@ -603,17 +603,17 @@ O(0) -3.5725041104048 -gammas -species_map - 28 9.1132215194016e-17 - 34 1.6289536138431e-22 + 28 9.1132215194017e-17 + 34 1.6289536138438e-22 63 0.0011978627117245 - 118 8.5801879328601e-08 + 118 8.5801879328566e-08 119 0 121 55.407356060892 178 0.00024074728813059 216 0.0009571154273873 - 221 7.6121918606964e-21 + 221 7.6121918606995e-21 225 0.00026705559494129 - 226 8.5801879332934e-08 + 226 8.5801879332968e-08 -log_gamma_map 28 -0.06611663856489 34 -0.016751008794 @@ -630,38 +630,38 @@ 28 -16.039553873072 34 -21.787317082581 63 -2.9208187541072 - 118 -7.0657289997204 + 118 -7.0657289997206 119 -45.224921210085 121 -1.9696121789103e-05 178 -3.6176643963109 216 -3.018261483559 221 -20.117716074193 225 -3.5726241190004 - 226 -7.0657289996985 + 226 -7.0657289996983 SOLUTION_RAW 8 Solution after simulation 1. -temp 20 -pressure 2 -potential 0 -total_h 22.162951281141 -total_o 11.081582462851 - -cb 1.4762040071978e-13 + -cb 1.4762023758653e-13 -density 0.99830112943876 -totals - Ca 3.6343034277183e-24 + Ca 3.6343034277184e-24 Cl 0.00023957263771222 K 3.9834209206973e-05 Na 0.00019973842865287 - -pH 7.0816246303923 - -pe 13.966513091744 + -pH 7.0816246303917 + -pe 13.966513091745 -mu 0.0012000859549133 -ah2o 0.99995464903202 -mass_water 0.19964386483136 -soln_vol 0.19999999150733 - -total_alkalinity 1.2196612695972e-19 + -total_alkalinity 6.8761869960308e-20 -activities Ca -22.805952199731 Cl -2.9376246512503 - E -13.966513091744 + E -13.966513091745 H(0) -45.224801201502 K -3.7168319491067 Na -3.0164400792113 @@ -669,16 +669,16 @@ -gammas -species_map 28 1.8171485429378e-23 - 34 3.2480837646132e-29 + 34 3.2480837646081e-29 63 0.0011978632394264 - 118 8.5801917127367e-08 + 118 8.58019171275e-08 119 0 121 55.407380469834 178 0.00019917105449233 216 0.00099869218567215 - 221 7.942862803801e-21 - 225 0.00026705571260414 - 226 8.5801917127969e-08 + 221 7.9428628037887e-21 + 225 0.00026705571260415 + 226 8.5801917127836e-08 -log_gamma_map 28 -0.066116638525128 34 -0.016751008783797 @@ -693,35 +693,35 @@ 226 -0.016850181701258 -log_molalities_map 28 -22.739835561206 - 34 -28.487598770694 + 34 -28.487598770695 63 -2.9208187541072 - 118 -7.0657289997207 + 118 -7.06572899972 119 -45.224921210097 121 -1.9696121766613e-05 178 -3.6999997686947 216 -2.9997943396725 - 221 -20.099248930305 + 221 -20.099248930306 225 -3.5726241189757 - 226 -7.0657289997177 + 226 -7.0657289997183 SOLUTION_RAW 9 Solution after simulation 1. -temp 20 -pressure 2 -potential 0 -total_h 22.162952787702 -total_o 11.081583216224 - -cb -1.8556708472941e-17 + -cb -1.8557548888443e-17 -density 0.99830111534656 -totals Cl 0.0002395726539976 K 3.9324934918955e-05 Na 0.00020024771907863 - -pH 7.0816246303907 + -pH 7.0816246303908 -pe 13.966513177942 -mu 0.0012000859545433 -ah2o 0.99995464902842 -mass_water 0.19964387840246 -soln_vol 0.19999999970769 - -total_alkalinity -7.7020441196038e-20 + -total_alkalinity -7.533630146888e-20 -activities Cl -2.9376246512477 E -13.966513177942 @@ -732,14 +732,14 @@ -gammas -species_map 63 0.0011978632717387 - 118 8.5801919441726e-08 + 118 8.5801919441722e-08 119 0 121 55.407381964433 178 0.00019662467488215 216 0.0010012385968565 - 221 7.9631150846907e-21 + 221 7.9631150846911e-21 225 0.00026705593182137 - 226 8.5801919441333e-08 + 226 8.5801919441338e-08 -log_gamma_map 63 -0.016805897140598 118 -0.015895630669395 @@ -752,7 +752,7 @@ 226 -0.016850181698759 -log_molalities_map 63 -2.9208187541071 - 118 -7.0657289997213 + 118 -7.0657289997214 119 -45.22492138249 121 -1.9696123329303e-05 178 -3.7055879855852 @@ -760,6 +760,85 @@ 221 -20.098143010822 225 -3.5726237741928 226 -7.0657289997233 + EXCHANGE_RAW 6 Exchange assemblage after simulation 1. + # EXCHANGE_MODIFY candidate identifiers # + -exchange_gammas 1 + -component X + # EXCHANGE_MODIFY candidate identifiers # + -totals + Ca 7.8889599963695e-09 + K 0.00018164031591582 + Na 3.8343906364582e-05 + X 0.0002200000002004 + -charge_balance 0 + -la 2.4447973951359 + -phase_proportion 0 + -formula_z 0 + # EXCHANGE_MODIFY candidates with new_def=true # + -new_def 0 + -solution_equilibria 0 + -n_solution -999 + # Exchange workspace variables # + -totals + EXCHANGE_RAW 7 Exchange assemblage after simulation 1. + # EXCHANGE_MODIFY candidate identifiers # + -exchange_gammas 1 + -component X + # EXCHANGE_MODIFY candidate identifiers # + -totals + Ca 1.2401487591103e-14 + K 0.00012430966894713 + Na 9.5690331159543e-05 + X 0.00022000000013147 + -charge_balance 0 + -la 2.6567385148108 + -phase_proportion 0 + -formula_z 0 + # EXCHANGE_MODIFY candidates with new_def=true # + -new_def 0 + -solution_equilibria 0 + -n_solution -999 + # Exchange workspace variables # + -totals + EXCHANGE_RAW 8 Exchange assemblage after simulation 1. + # EXCHANGE_MODIFY candidate identifiers # + -exchange_gammas 1 + -component X + # EXCHANGE_MODIFY candidate identifiers # + -totals + Ca 2.9132510369212e-21 + K 0.00011162525008285 + Na 0.00010837475004853 + X 0.00022000000013137 + -charge_balance 0 + -la 2.6923314222035 + -phase_proportion 0 + -formula_z 0 + # EXCHANGE_MODIFY candidates with new_def=true # + -new_def 0 + -solution_equilibria 0 + -n_solution -999 + # Exchange workspace variables # + -totals + EXCHANGE_RAW 9 Exchange assemblage after simulation 1. + # EXCHANGE_MODIFY candidate identifiers # + -exchange_gammas 1 + -component X + # EXCHANGE_MODIFY candidate identifiers # + -totals + K 0.00011077759538494 + Na 0.00010922240474649 + X 0.00022000000013143 + -charge_balance 0 + -la 2.6946091280289 + -phase_proportion 0 + -formula_z 0 + # EXCHANGE_MODIFY candidates with new_def=true # + -new_def 0 + -solution_equilibria 0 + -n_solution -999 + # Exchange workspace variables # + -totals SOLUTION_RAW 10 Solution after simulation 1. -temp 20 -pressure 2 @@ -904,127 +983,6 @@ 221 -20.098107260029 225 -3.5725641150874 226 -7.0657289998583 - EXCHANGE_RAW 6 Exchange assemblage after simulation 1. - # EXCHANGE_MODIFY candidate identifiers # - -exchange_gammas 1 - -component X - # EXCHANGE_MODIFY candidate identifiers # - -totals - Ca 7.8889599963695e-09 - K 0.00018164031591582 - Na 3.8343906364582e-05 - X 0.0002200000002004 - -charge_balance 0 - -la 2.4447973951359 - -phase_proportion 0 - -formula_z 0 - # EXCHANGE_MODIFY candidates with new_def=true # - -new_def 0 - -solution_equilibria 0 - -n_solution -999 - # Exchange workspace variables # - -totals - EXCHANGE_RAW 7 Exchange assemblage after simulation 1. - # EXCHANGE_MODIFY candidate identifiers # - -exchange_gammas 1 - -component X - # EXCHANGE_MODIFY candidate identifiers # - -totals - Ca 1.2401487591103e-14 - K 0.00012430966894713 - Na 9.5690331159543e-05 - X 0.00022000000013147 - -charge_balance 0 - -la 2.6567385148108 - -phase_proportion 0 - -formula_z 0 - # EXCHANGE_MODIFY candidates with new_def=true # - -new_def 0 - -solution_equilibria 0 - -n_solution -999 - # Exchange workspace variables # - -totals - EXCHANGE_RAW 8 Exchange assemblage after simulation 1. - # EXCHANGE_MODIFY candidate identifiers # - -exchange_gammas 1 - -component X - # EXCHANGE_MODIFY candidate identifiers # - -totals - Ca 2.9132510369212e-21 - K 0.00011162525008285 - Na 0.00010837475004853 - X 0.00022000000013137 - -charge_balance 0 - -la 2.6923314222035 - -phase_proportion 0 - -formula_z 0 - # EXCHANGE_MODIFY candidates with new_def=true # - -new_def 0 - -solution_equilibria 0 - -n_solution -999 - # Exchange workspace variables # - -totals - EXCHANGE_RAW 9 Exchange assemblage after simulation 1. - # EXCHANGE_MODIFY candidate identifiers # - -exchange_gammas 1 - -component X - # EXCHANGE_MODIFY candidate identifiers # - -totals - K 0.00011077759538494 - Na 0.00010922240474649 - X 0.00022000000013143 - -charge_balance 0 - -la 2.6946091280289 - -phase_proportion 0 - -formula_z 0 - # EXCHANGE_MODIFY candidates with new_def=true # - -new_def 0 - -solution_equilibria 0 - -n_solution -999 - # Exchange workspace variables # - -totals - EXCHANGE_RAW 10 Exchange assemblage after simulation 1. - # EXCHANGE_MODIFY candidate identifiers # - -exchange_gammas 1 - -component X - # EXCHANGE_MODIFY candidate identifiers # - -totals - H 1.5569735078322e-64 - K 0.0001107500084442 - N 3.8924337695805e-65 - Na 0.00010924999168717 - X 0.00022000000013137 - -charge_balance 0 - -la 2.6946830555387 - -phase_proportion 0 - -formula_z 0 - # EXCHANGE_MODIFY candidates with new_def=true # - -new_def 0 - -solution_equilibria 0 - -n_solution -999 - # Exchange workspace variables # - -totals - EXCHANGE_RAW 11 Exchange assemblage after simulation 1. - # EXCHANGE_MODIFY candidate identifiers # - -exchange_gammas 1 - -component X - # EXCHANGE_MODIFY candidate identifiers # - -totals - H 1.5569735078322e-64 - K 0.0001107500084442 - N 3.8924337695805e-65 - Na 0.00010924999168717 - X 0.00022000000013137 - -charge_balance 0 - -la 2.6946830555387 - -phase_proportion 0 - -formula_z 0 - # EXCHANGE_MODIFY candidates with new_def=true # - -new_def 0 - -solution_equilibria 0 - -n_solution -999 - # Exchange workspace variables # - -totals SOLUTION_RAW 12 Solution after simulation 1. -temp 20 -pressure 2 @@ -1601,6 +1559,48 @@ 221 -20.098107260029 225 -3.5725641150874 226 -7.0657289998583 + EXCHANGE_RAW 10 Exchange assemblage after simulation 1. + # EXCHANGE_MODIFY candidate identifiers # + -exchange_gammas 1 + -component X + # EXCHANGE_MODIFY candidate identifiers # + -totals + H 1.5569735078322e-64 + K 0.0001107500084442 + N 3.8924337695805e-65 + Na 0.00010924999168717 + X 0.00022000000013137 + -charge_balance 0 + -la 2.6946830555387 + -phase_proportion 0 + -formula_z 0 + # EXCHANGE_MODIFY candidates with new_def=true # + -new_def 0 + -solution_equilibria 0 + -n_solution -999 + # Exchange workspace variables # + -totals + EXCHANGE_RAW 11 Exchange assemblage after simulation 1. + # EXCHANGE_MODIFY candidate identifiers # + -exchange_gammas 1 + -component X + # EXCHANGE_MODIFY candidate identifiers # + -totals + H 1.5569735078322e-64 + K 0.0001107500084442 + N 3.8924337695805e-65 + Na 0.00010924999168717 + X 0.00022000000013137 + -charge_balance 0 + -la 2.6946830555387 + -phase_proportion 0 + -formula_z 0 + # EXCHANGE_MODIFY candidates with new_def=true # + -new_def 0 + -solution_equilibria 0 + -n_solution -999 + # Exchange workspace variables # + -totals EXCHANGE_RAW 12 Exchange assemblage after simulation 1. # EXCHANGE_MODIFY candidate identifiers # -exchange_gammas 1 diff --git a/Tests/Output/Species_cpp_utility.txt b/Tests/Output/Species_cpp_utility.txt index f1eddb3a1..2e7fa00dc 100644 --- a/Tests/Output/Species_cpp_utility.txt +++ b/Tests/Output/Species_cpp_utility.txt @@ -37,7 +37,7 @@ Using solution 1. Activity of water = 1.000 Ionic strength (mol/kgw) = 1.500e-03 Mass of water (kg) = 9.982e-01 - Total alkalinity (eq/kg) = -9.221e-20 + Total alkalinity (eq/kg) = -9.539e-20 Temperature (°C) = 15.00 Pressure (atm) = 3.00 Electrical balance (eq) = -4.304e-17 @@ -91,6 +91,6 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 7.277 Seconds. +End of Run after 1.312 Seconds. ------------------------------- diff --git a/Tests/Output/Species_f90.chem.txt b/Tests/Output/Species_f90.chem.txt index bf77f5321..813fb8277 100644 --- a/Tests/Output/Species_f90.chem.txt +++ b/Tests/Output/Species_f90.chem.txt @@ -195,9 +195,9 @@ End of simulation. Reading input data for simulation 4. ------------------------------------ --------------------------------- -End of Run after 12.892 Seconds. --------------------------------- +------------------------------- +End of Run after 1.922 Seconds. +------------------------------- Number of threads: 3 Number of MPI processes: 1 @@ -320,7 +320,7 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.800e-03 Mass of water (kg) = 1.994e-01 - Total alkalinity (eq/kg) = 9.007e-20 + Total alkalinity (eq/kg) = 8.827e-20 Temperature (°C) = 20.00 Pressure (atm) = 2.00 Electrical balance (eq) = 1.033e-18 @@ -373,9 +373,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ --------------------------------- -End of Run after 13.294 Seconds. --------------------------------- +------------------------------- +End of Run after 1.952 Seconds. +------------------------------- Time: 10 Chemistry cell: 1 @@ -432,10 +432,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.800e-03 Mass of water (kg) = 1.996e-01 - Total alkalinity (eq/kg) = 9.765e-20 + Total alkalinity (eq/kg) = 9.874e-20 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = 7.515e-19 + Electrical balance (eq) = 7.513e-19 Percent error, 100*(Cat-|An|)/(Cat+|An|) = 0.00 Iterations = 5 Total H = 2.216319e+01 @@ -485,9 +485,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ --------------------------------- -End of Run after 13.299 Seconds. --------------------------------- +------------------------------- +End of Run after 1.952 Seconds. +------------------------------- Time: 10 Chemistry cell: 2 @@ -544,10 +544,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.800e-03 Mass of water (kg) = 1.996e-01 - Total alkalinity (eq/kg) = -5.008e-19 + Total alkalinity (eq/kg) = -1.717e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = 1.177e-18 + Electrical balance (eq) = 1.329e-18 Percent error, 100*(Cat-|An|)/(Cat+|An|) = 0.00 Iterations = 6 Total H = 2.216319e+01 @@ -597,9 +597,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ --------------------------------- -End of Run after 13.304 Seconds. --------------------------------- +------------------------------- +End of Run after 1.953 Seconds. +------------------------------- Time: 10 Chemistry cell: 3 @@ -656,10 +656,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.800e-03 Mass of water (kg) = 1.996e-01 - Total alkalinity (eq/kg) = 2.934e-19 + Total alkalinity (eq/kg) = 5.721e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = 6.340e-18 + Electrical balance (eq) = 6.285e-18 Percent error, 100*(Cat-|An|)/(Cat+|An|) = 0.00 Iterations = 6 Total H = 2.216319e+01 @@ -709,9 +709,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ --------------------------------- -End of Run after 13.308 Seconds. --------------------------------- +------------------------------- +End of Run after 1.953 Seconds. +------------------------------- Time: 10 Chemistry cell: 4 @@ -768,10 +768,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.759e-03 Mass of water (kg) = 1.996e-01 - Total alkalinity (eq/kg) = 4.248e-20 + Total alkalinity (eq/kg) = 2.320e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = 2.796e-16 + Electrical balance (eq) = 2.795e-16 Percent error, 100*(Cat-|An|)/(Cat+|An|) = 0.00 Iterations = 7 Total H = 2.216319e+01 @@ -821,9 +821,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ --------------------------------- -End of Run after 13.313 Seconds. --------------------------------- +------------------------------- +End of Run after 1.953 Seconds. +------------------------------- Time: 10 Chemistry cell: 5 @@ -880,7 +880,7 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.211e-03 Mass of water (kg) = 1.996e-01 - Total alkalinity (eq/kg) = 2.567e-19 + Total alkalinity (eq/kg) = 3.826e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 Electrical balance (eq) = 1.029e-13 @@ -933,9 +933,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ --------------------------------- -End of Run after 13.295 Seconds. --------------------------------- +------------------------------- +End of Run after 1.954 Seconds. +------------------------------- Time: 10 Chemistry cell: 6 @@ -992,10 +992,10 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.200e-03 Mass of water (kg) = 1.996e-01 - Total alkalinity (eq/kg) = -5.571e-19 + Total alkalinity (eq/kg) = 4.301e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 - Electrical balance (eq) = -7.172e-16 + Electrical balance (eq) = -7.173e-16 Percent error, 100*(Cat-|An|)/(Cat+|An|) = -0.00 Iterations = 6 Total H = 2.216281e+01 @@ -1045,9 +1045,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 13.3 Seconds. ------------------------------- +------------------------------- +End of Run after 1.952 Seconds. +------------------------------- Time: 10 Chemistry cell: 7 @@ -1104,7 +1104,7 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.200e-03 Mass of water (kg) = 1.996e-01 - Total alkalinity (eq/kg) = 3.529e-18 + Total alkalinity (eq/kg) = 3.269e-18 Temperature (°C) = 20.00 Pressure (atm) = 2.00 Electrical balance (eq) = 7.587e-13 @@ -1157,9 +1157,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ --------------------------------- -End of Run after 13.304 Seconds. --------------------------------- +------------------------------- +End of Run after 1.953 Seconds. +------------------------------- Time: 10 Chemistry cell: 8 @@ -1216,7 +1216,7 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.200e-03 Mass of water (kg) = 1.996e-01 - Total alkalinity (eq/kg) = 7.898e-19 + Total alkalinity (eq/kg) = 7.966e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 Electrical balance (eq) = 1.476e-13 @@ -1269,9 +1269,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ --------------------------------- -End of Run after 13.308 Seconds. --------------------------------- +------------------------------- +End of Run after 1.953 Seconds. +------------------------------- Time: 10 Chemistry cell: 9 @@ -1326,7 +1326,7 @@ X 2.200e-04 mol Activity of water = 1.000 Ionic strength (mol/kgw) = 1.200e-03 Mass of water (kg) = 1.996e-01 - Total alkalinity (eq/kg) = 9.446e-19 + Total alkalinity (eq/kg) = 9.534e-19 Temperature (°C) = 20.00 Pressure (atm) = 2.00 Electrical balance (eq) = -1.799e-17 @@ -1376,9 +1376,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ --------------------------------- -End of Run after 13.315 Seconds. --------------------------------- +------------------------------- +End of Run after 1.954 Seconds. +------------------------------- Time: 10 Chemistry cell: 10 @@ -1491,9 +1491,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ --------------------------------- -End of Run after 13.294 Seconds. --------------------------------- +------------------------------- +End of Run after 1.955 Seconds. +------------------------------- Time: 10 Chemistry cell: 11 @@ -1606,9 +1606,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ --------------------------------- -End of Run after 13.298 Seconds. --------------------------------- +------------------------------- +End of Run after 1.952 Seconds. +------------------------------- Time: 10 Chemistry cell: 12 @@ -1721,9 +1721,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ --------------------------------- -End of Run after 13.302 Seconds. --------------------------------- +------------------------------- +End of Run after 1.953 Seconds. +------------------------------- Time: 10 Chemistry cell: 13 @@ -1836,9 +1836,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ --------------------------------- -End of Run after 13.305 Seconds. --------------------------------- +------------------------------- +End of Run after 1.953 Seconds. +------------------------------- Time: 10 Chemistry cell: 14 @@ -1951,9 +1951,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ --------------------------------- -End of Run after 13.308 Seconds. --------------------------------- +------------------------------- +End of Run after 1.954 Seconds. +------------------------------- Time: 10 Chemistry cell: 15 @@ -2066,9 +2066,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ --------------------------------- -End of Run after 13.313 Seconds. --------------------------------- +------------------------------- +End of Run after 1.954 Seconds. +------------------------------- Time: 10 Chemistry cell: 16 @@ -2181,9 +2181,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ --------------------------------- -End of Run after 13.317 Seconds. --------------------------------- +------------------------------- +End of Run after 1.955 Seconds. +------------------------------- Time: 10 Chemistry cell: 17 @@ -2297,7 +2297,7 @@ Reading input data for simulation 2. ------------------------------------ ------------------------------- -End of Run after 13.32 Seconds. +End of Run after 1.955 Seconds. ------------------------------- Time: 10 @@ -2411,9 +2411,9 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ --------------------------------- -End of Run after 13.322 Seconds. --------------------------------- +------------------------------- +End of Run after 1.956 Seconds. +------------------------------- Time: 10 Chemistry cell: 19 @@ -2526,7 +2526,7 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ --------------------------------- -End of Run after 13.324 Seconds. --------------------------------- +------------------------------- +End of Run after 1.957 Seconds. +------------------------------- diff --git a/Tests/Output/Species_f90.dmp b/Tests/Output/Species_f90.dmp index a69bf46cf..69b98addc 100644 --- a/Tests/Output/Species_f90.dmp +++ b/Tests/Output/Species_f90.dmp @@ -4,7 +4,7 @@ -potential 0 -total_h 22.136415835711 -total_o 11.068314612239 - -cb 1.0329996925685e-18 + -cb 1.0333570345931e-18 -density 0.99830524784931 -totals Ca 0.00011964290005151 @@ -17,7 +17,7 @@ -ah2o 0.99996484900903 -mass_water 0.19940483353499 -soln_vol 0.1997583605563 - -total_alkalinity 1.7959745459751e-20 + -total_alkalinity 1.7602403435128e-20 -activities Ca -3.3018013654974 Cl -2.9412141501733 @@ -29,16 +29,16 @@ -gammas -species_map 28 0.00059893709687918 - 34 1.0387679456951e-09 + 34 1.038767945695e-09 63 0.0011978762715883 - 118 8.6997192838568e-08 + 118 8.6997192838569e-08 119 0 121 55.407983273659 178 2.9410943074934e-13 216 2.5173245006726e-19 - 221 1.9728267683727e-36 - 225 0.00026705861804014 - 226 8.5958424892963e-08 + 221 1.9728267683726e-36 + 225 0.00026705861804013 + 226 8.5958424892962e-08 -log_gamma_map 28 -0.079951862409805 34 -0.020310467757975 @@ -69,7 +69,7 @@ -potential 0 -total_h 22.163193674519 -total_o 11.081703660708 - -cb 7.5147373416972e-19 + -cb 7.5125866721046e-19 -density 0.9983052478494 -totals Ca 0.00011978762248885 @@ -82,7 +82,7 @@ -ah2o 0.99996484900849 -mass_water 0.1996460483066 -soln_vol 0.20000000298045 - -total_alkalinity 1.949499267665e-20 + -total_alkalinity 1.9713368358364e-20 -activities Ca -3.3018013881279 Cl -2.94121415 @@ -96,14 +96,14 @@ 28 0.00059893706475084 34 1.038767891504e-09 63 0.001197876271587 - 118 8.699719277874e-08 + 118 8.6997192778739e-08 119 0 121 55.407983273596 178 6.454910399772e-11 216 4.2051407471527e-16 221 3.2955680662655e-33 225 0.00026705861804126 - 226 8.5958424887333e-08 + 226 8.5958424887334e-08 -log_gamma_map 28 -0.079951861744341 34 -0.020310467586335 @@ -134,24 +134,24 @@ -potential 0 -total_h 22.163193674241 -total_o 11.081703660569 - -cb 1.1772864611773e-18 + -cb 1.3288292581195e-18 -density 0.99830524786068 -totals Ca 0.00011978678578707 Cl 0.00023957525788461 K 1.6862062138559e-09 Na 1.0424816777238e-13 - -pH 7.0787960689481 - -pe 13.969354438095 + -pH 7.0787960689489 + -pe 13.969354438094 -mu 0.0018000808463647 -ah2o 0.99996484893724 -mass_water 0.1996460483041 -soln_vol 0.20000000300763 - -total_alkalinity -9.9976357555609e-20 + -total_alkalinity -3.4284982029098e-20 -activities Ca -3.3018043349734 Cl -2.941214127436 - E -13.969354438095 + E -13.969354438094 H(0) -45.224826771315 K -8.0937842120455 Na -12.302349720429 @@ -159,16 +159,16 @@ -gammas -species_map 28 0.00059893288116766 - 34 1.0387608350172e-09 + 34 1.0387608350191e-09 63 0.0011978762714092 - 118 8.6997184988978e-08 + 118 8.6997184988813e-08 119 0 121 55.407983265371 178 8.4310309424924e-09 - 216 5.2124083102338e-13 - 221 4.0849638691054e-30 + 216 5.2124083102339e-13 + 221 4.0849638691131e-30 225 0.00026705861800496 - 226 8.5958424153461e-08 + 226 8.5958424153623e-08 -log_gamma_map 28 -0.079951775091035 34 -0.020310445236317 @@ -183,40 +183,40 @@ 226 -0.020461180246083 -log_molalities_map 28 -3.2218525598823 - 34 -8.9827151493913 + 34 -8.9827151493905 63 -2.920818754098 - 118 -7.0597255160444 + 118 -7.0597255160452 119 -45.2250067794 121 -1.5266180902326e-05 178 -8.0733500330121 216 -12.282192287691 - 221 -29.388042496593 + 221 -29.388042496592 225 -3.5726241189564 - 226 -7.0649422710892 + 226 -7.0649422710884 SOLUTION_RAW 3 Solution after simulation 1. -temp 20 -pressure 2 -potential 0 -total_h 22.163193639187 -total_o 11.081703643042 - -cb 6.3402632946026e-18 + -cb 6.2853186495944e-18 -density 0.99830524887905 -totals Ca 0.00011969888533516 Cl 0.00023957525750568 K 1.7736475591533e-07 Na 1.2207945889637e-10 - -pH 7.0787980753017 - -pe 13.969352422364 + -pH 7.0787980753024 + -pe 13.969352422363 -mu 0.0017996405665282 -ah2o 0.99996484145249 -mass_water 0.19964604798833 -soln_vol 0.20000000584211 - -total_alkalinity 5.8571004813655e-20 + -total_alkalinity 1.1422371642622e-19 -activities Ca -3.3021140357943 Cl -2.9412117567921 - E -13.969352422364 + E -13.969352422363 H(0) -45.22482675256 K -6.0718251914475 Na -9.233773240851 @@ -224,16 +224,16 @@ -gammas -species_map 28 0.00059849337117391 - 34 1.0380195046574e-09 + 34 1.0380195046591e-09 63 0.0011978762525378 - 118 8.6996366452238e-08 + 118 8.6996366452098e-08 119 0 121 55.407982392471 178 8.8682375367202e-07 - 216 6.1039727665178e-10 - 221 4.7837308807712e-27 - 225 0.0002670586138071 - 226 8.5958346947873e-08 + 216 6.1039727665177e-10 + 221 4.7837308807788e-27 + 225 0.00026705861380709 + 226 8.595834694801e-08 -log_gamma_map 28 -0.079942671013776 34 -0.020308097074793 @@ -248,36 +248,36 @@ 226 -0.020458793913119 -log_molalities_map 28 -3.2221713647806 - 34 -8.9830251952709 + 34 -8.9830251952702 63 -2.920818754098 - 118 -7.0597295953998 + 118 -7.0597295954005 119 -45.225006716616 121 -1.526943160379e-05 178 -6.0513933921429 216 -9.2136181220636 - 221 -26.319463969884 + 221 -26.319463969883 225 -3.5726241189411 - 226 -7.0649426543193 + 226 -7.0649426543186 SOLUTION_RAW 4 Solution after simulation 1. -temp 20 -pressure 2 -potential 0 -total_h 22.16318999399 -total_o 11.081701820426 - -cb 2.7960032825484e-16 + -cb 2.7951497314179e-16 -density 0.9983053411377 -totals Ca 0.00011155692644709 Cl 0.00023957521810259 K 1.6324040039246e-05 Na 1.3732516944667e-07 - -pH 7.0789843133724 + -pH 7.0789843133728 -pe 13.969165315291 -mu 0.0017588587513626 -ah2o 0.999964148162 -mass_water 0.19964601515267 -soln_vol 0.20000026318074 - -total_alkalinity 8.4802556398936e-21 + -total_alkalinity 4.6308879413169e-20 -activities Ca -3.3318586843358 Cl -2.9409907725944 @@ -289,16 +289,16 @@ -gammas -species_map 28 0.00055778292901468 - 34 9.6923087435811e-10 + 34 9.6923087435916e-10 63 0.0011978745142255 - 118 8.692023060142e-08 + 118 8.6920230601326e-08 119 0 121 55.407901986594 - 178 8.1620092792051e-05 + 178 8.1620092792052e-05 216 6.8662494370105e-07 - 221 5.3861626178573e-24 + 221 5.3861626178633e-24 225 0.0002670582262425 - 226 8.5950999727105e-08 + 226 8.5950999727198e-08 -log_gamma_map 28 -0.079093823721207 34 -0.02008919274014 @@ -313,157 +313,57 @@ 226 -0.020236355863584 -log_molalities_map 28 -3.2527648606146 - 34 -9.0128028392189 + 34 -9.0128028392184 63 -2.9208187540985 - 118 -7.0601092092917 + 118 -7.0601092092922 119 -45.225000900431 121 -1.5570534527945e-05 178 -4.0874329949581 216 -6.1625105027153 - 221 -23.267950617737 + 221 -23.267950617736 225 -3.5726241189731 - 226 -7.0649791466469 - EXCHANGE_RAW 0 Exchange assemblage after simulation 1. - # EXCHANGE_MODIFY candidate identifiers # - -exchange_gammas 1 - -component X - # EXCHANGE_MODIFY candidate identifiers # - -totals - Ca 0.00011000000171647 - K 5.578978765901e-15 - Na 9.2458167257557e-22 - X 0.00022000000343853 - -charge_balance 0 - -la 1.2218455551817 - -phase_proportion 0 - -formula_z 0 - # EXCHANGE_MODIFY candidates with new_def=true # - -new_def 0 - -solution_equilibria 0 - -n_solution -999 - # Exchange workspace variables # - -totals - EXCHANGE_RAW 1 Exchange assemblage after simulation 1. - # EXCHANGE_MODIFY candidate identifiers # - -exchange_gammas 1 - -component X - # EXCHANGE_MODIFY candidate identifiers # - -totals - Ca 0.0001100000010629 - K 1.2244357080309e-12 - Na 1.5444954181836e-18 - X 0.00022000000335024 - -charge_balance 0 - -la 1.2218455656268 - -phase_proportion 0 - -formula_z 0 - # EXCHANGE_MODIFY candidates with new_def=true # - -new_def 0 - -solution_equilibria 0 - -n_solution -999 - # Exchange workspace variables # - -totals - EXCHANGE_RAW 2 Exchange assemblage after simulation 1. - # EXCHANGE_MODIFY candidate identifiers # - -exchange_gammas 1 - -component X - # EXCHANGE_MODIFY candidate identifiers # - -totals - Ca 0.00010999992174006 - K 1.5992921724064e-10 - Na 1.9144581484123e-15 - X 0.00022000000341125 - -charge_balance 0 - -la 1.2218469257425 - -phase_proportion 0 - -formula_z 0 - # EXCHANGE_MODIFY candidates with new_def=true # - -new_def 0 - -solution_equilibria 0 - -n_solution -999 - # Exchange workspace variables # - -totals - EXCHANGE_RAW 3 Exchange assemblage after simulation 1. - # EXCHANGE_MODIFY candidate identifiers # - -exchange_gammas 1 - -component X - # EXCHANGE_MODIFY candidate identifiers # - -totals - Ca 0.00010999158668225 - K 1.6827802271301e-08 - Na 2.2426576926996e-12 - X 0.00022000000340942 - -charge_balance 0 - -la 1.2219898736055 - -phase_proportion 0 - -formula_z 0 - # EXCHANGE_MODIFY candidates with new_def=true # - -new_def 0 - -solution_equilibria 0 - -n_solution -999 - # Exchange workspace variables # - -totals - EXCHANGE_RAW 4 Exchange assemblage after simulation 1. - # EXCHANGE_MODIFY candidate identifiers # - -exchange_gammas 1 - -component X - # EXCHANGE_MODIFY candidate identifiers # - -totals - Ca 0.00010919944563952 - K 1.5985088154449e-06 - Na 2.6037413630759e-09 - X 0.00022000000383586 - -charge_balance 0 - -la 1.2357171184409 - -phase_proportion 0 - -formula_z 0 - # EXCHANGE_MODIFY candidates with new_def=true # - -new_def 0 - -solution_equilibria 0 - -n_solution -999 - # Exchange workspace variables # - -totals + 226 -7.0649791466464 SOLUTION_RAW 5 Solution after simulation 1. -temp 20 -pressure 2 -potential 0 -total_h 22.162949106953 -total_o 11.081581375747 - -cb 1.0286486018773e-13 + -cb 1.0286476630935e-13 -density 0.99830599745848 -totals Ca 2.1789425294313e-06 Cl 0.00023957261421272 K 0.00021232055573506 Na 2.2894173521659e-05 - -pH 7.0815712902199 - -pe 13.966566664476 + -pH 7.0815712902202 + -pe 13.966566664475 -mu 0.0012110000876024 -ah2o 0.99995483457207 -mass_water 0.19964384524619 -soln_vol 0.20000176760513 - -total_alkalinity 5.1248802031335e-20 + -total_alkalinity 7.6378549040696e-20 -activities Ca -5.0284103997467 Cl -2.9376977710625 - E -13.966566664476 + E -13.966566664475 H(0) -45.22480166662 K -2.9901694145148 Na -3.95724839021 O(0) -3.5725030189789 -gammas -species_map - 28 1.0894596898393e-05 - 34 1.9461865001077e-11 + 28 1.0894596898392e-05 + 34 1.946186500109e-11 63 0.0011978524844126 - 118 8.5824609739665e-08 + 118 8.5824609739602e-08 119 0 121 55.406882994103 178 0.0010615933962856 216 0.00011446985592077 - 221 9.1014482447319e-22 + 221 9.1014482447386e-22 225 0.00026705331483431 - 226 8.5805147874919e-08 + 226 8.5805147874982e-08 -log_gamma_map 28 -0.066399473606212 34 -0.016823593711558 @@ -480,38 +380,38 @@ 28 -4.9620109261405 34 -10.710037636354 63 -2.9208187541023 - 118 -7.0656102547784 + 118 -7.0656102547787 119 -45.224922766629 121 -1.9615539096887e-05 178 -2.9732638837573 216 -3.9405309558754 221 -21.040111588242 225 -3.5726241189877 - 226 -7.0657087479607 + 226 -7.0657087479604 SOLUTION_RAW 6 Solution after simulation 1. -temp 20 -pressure 2 -potential 0 -total_h 22.162814381934 -total_o 11.081514012588 - -cb -7.1718988041498e-16 + -cb -7.1726132235013e-16 -density 0.99830319874272 -totals Ca 3.0770063976187e-11 Cl 0.00023957115788649 K 0.00011461391511898 Na 0.00012495718122667 - -pH 7.0816246296331 - -pe 13.966513092508 + -pH 7.0816246296356 + -pe 13.966513092506 -mu 0.001200086108667 -ah2o 0.99995464903465 -mass_water 0.1996426316433 -soln_vol 0.19999954847511 - -total_alkalinity -1.1122932260878e-19 + -total_alkalinity 8.5861347583004e-20 -activities Ca -9.8782423055853 Cl -2.937624652283 - E -13.966513092508 + E -13.966513092506 H(0) -45.224801201512 K -3.2578481195171 Na -3.220137806687 @@ -519,16 +419,16 @@ -gammas -species_map 28 1.5385039221625e-10 - 34 2.750017101079e-16 + 34 2.7500171010947e-16 63 0.0011978584937471 - 118 8.5801577530973e-08 + 118 8.580157753048e-08 119 0 121 55.407160957595 178 0.0005730708693737 216 0.00062478731666847 - 221 4.9690985756688e-21 - 225 0.00026705465459048 - 226 8.580157725541e-08 + 221 4.9690985756973e-21 + 225 0.00026705465459049 + 226 8.5801577255903e-08 -log_gamma_map 28 -0.066116642519664 34 -0.016751009808874 @@ -543,36 +443,176 @@ 226 -0.016850182739422 -log_molalities_map 28 -9.8121256630657 - 34 -15.559888876299 + 34 -15.559888876296 63 -2.9208187541073 - 118 -7.0657289980376 + 118 -7.0657289980401 119 -45.224921210123 121 -1.9696120623193e-05 178 -3.2410159380693 216 -3.2034920661357 - 221 -20.302946658562 + 221 -20.30294665856 225 -3.5726241189689 - 226 -7.0657289994324 + 226 -7.0657289994299 + EXCHANGE_RAW 0 Exchange assemblage after simulation 1. + # EXCHANGE_MODIFY candidate identifiers # + -exchange_gammas 1 + -component X + # EXCHANGE_MODIFY candidate identifiers # + -totals + Ca 0.00011000000171647 + K 5.578978765901e-15 + Na 9.2458167257557e-22 + X 0.00022000000343853 + -charge_balance 0 + -la 1.2218455551817 + -phase_proportion 0 + -formula_z 0 + # EXCHANGE_MODIFY candidates with new_def=true # + -new_def 0 + -solution_equilibria 0 + -n_solution -999 + # Exchange workspace variables # + -totals + EXCHANGE_RAW 1 Exchange assemblage after simulation 1. + # EXCHANGE_MODIFY candidate identifiers # + -exchange_gammas 1 + -component X + # EXCHANGE_MODIFY candidate identifiers # + -totals + Ca 0.0001100000010629 + K 1.2244357080309e-12 + Na 1.5444954181836e-18 + X 0.00022000000335024 + -charge_balance 0 + -la 1.2218455656268 + -phase_proportion 0 + -formula_z 0 + # EXCHANGE_MODIFY candidates with new_def=true # + -new_def 0 + -solution_equilibria 0 + -n_solution -999 + # Exchange workspace variables # + -totals + EXCHANGE_RAW 2 Exchange assemblage after simulation 1. + # EXCHANGE_MODIFY candidate identifiers # + -exchange_gammas 1 + -component X + # EXCHANGE_MODIFY candidate identifiers # + -totals + Ca 0.00010999992174006 + K 1.5992921724064e-10 + Na 1.9144581484123e-15 + X 0.00022000000341125 + -charge_balance 0 + -la 1.2218469257425 + -phase_proportion 0 + -formula_z 0 + # EXCHANGE_MODIFY candidates with new_def=true # + -new_def 0 + -solution_equilibria 0 + -n_solution -999 + # Exchange workspace variables # + -totals + EXCHANGE_RAW 3 Exchange assemblage after simulation 1. + # EXCHANGE_MODIFY candidate identifiers # + -exchange_gammas 1 + -component X + # EXCHANGE_MODIFY candidate identifiers # + -totals + Ca 0.00010999158668225 + K 1.6827802271301e-08 + Na 2.2426576926996e-12 + X 0.00022000000340942 + -charge_balance 0 + -la 1.2219898736055 + -phase_proportion 0 + -formula_z 0 + # EXCHANGE_MODIFY candidates with new_def=true # + -new_def 0 + -solution_equilibria 0 + -n_solution -999 + # Exchange workspace variables # + -totals + EXCHANGE_RAW 4 Exchange assemblage after simulation 1. + # EXCHANGE_MODIFY candidate identifiers # + -exchange_gammas 1 + -component X + # EXCHANGE_MODIFY candidate identifiers # + -totals + Ca 0.00010919944563952 + K 1.5985088154449e-06 + Na 2.6037413630759e-09 + X 0.00022000000383586 + -charge_balance 0 + -la 1.2357171184409 + -phase_proportion 0 + -formula_z 0 + # EXCHANGE_MODIFY candidates with new_def=true # + -new_def 0 + -solution_equilibria 0 + -n_solution -999 + # Exchange workspace variables # + -totals + EXCHANGE_RAW 5 Exchange assemblage after simulation 1. + # EXCHANGE_MODIFY candidate identifiers # + -exchange_gammas 1 + -component X + # EXCHANGE_MODIFY candidate identifiers # + -totals + Ca 5.5744649285429e-05 + K 0.00010629152848211 + Na 2.2191763568915e-06 + X 0.00022000000340986 + -charge_balance 0 + -la 1.944331735805 + -phase_proportion 0 + -formula_z 0 + # EXCHANGE_MODIFY candidates with new_def=true # + -new_def 0 + -solution_equilibria 0 + -n_solution -999 + # Exchange workspace variables # + -totals + EXCHANGE_RAW 6 Exchange assemblage after simulation 1. + # EXCHANGE_MODIFY candidate identifiers # + -exchange_gammas 1 + -component X + # EXCHANGE_MODIFY candidate identifiers # + -totals + Ca 7.8889601139241e-09 + K 0.00018164031862247 + Na 3.8343906935951e-05 + X 0.00022000000347865 + -charge_balance 0 + -la 2.4447973951359 + -phase_proportion 0 + -formula_z 0 + # EXCHANGE_MODIFY candidates with new_def=true # + -new_def 0 + -solution_equilibria 0 + -n_solution -999 + # Exchange workspace variables # + -totals SOLUTION_RAW 7 Solution after simulation 1. -temp 20 -pressure 2 -potential 0 -total_h 22.162929440712 -total_o 11.081571542531 - -cb 7.5870556462793e-13 + -cb 7.5870548217788e-13 -density 0.99830135953731 -totals Ca 1.8226464912093e-17 Cl 0.00023957240162591 K 4.8149429344315e-05 Na 0.00019142297304026 - -pH 7.0816246303992 + -pH 7.0816246303985 -pe 13.966513091735 -mu 0.0012000859564438 -ah2o 0.99995464903196 -mass_water 0.19964366809278 -soln_vol 0.19999988252494 - -total_alkalinity 7.0450641898896e-19 + -total_alkalinity 6.5256278524308e-19 -activities Ca -16.105670511637 Cl -2.9376246512606 @@ -584,19 +624,19 @@ -gammas -species_map 28 9.1132215194015e-17 - 34 1.6289536138353e-22 + 34 1.6289536138328e-22 63 0.0011978627117245 - 118 8.580187932901e-08 + 118 8.580187932914e-08 119 0 121 55.407356060892 178 0.00024074728813059 216 0.0009571154273873 - 221 7.6121918606602e-21 - 225 0.00026705559494977 - 226 8.5801879332525e-08 + 221 7.6121918606486e-21 + 225 0.00026705559494978 + 226 8.5801879332395e-08 -log_gamma_map 28 -0.06611663856489 - 34 -0.016751008794001 + 34 -0.016751008794 63 -0.016805897153361 118 -0.015895630680815 119 0.00012000859564438 @@ -608,23 +648,23 @@ 226 -0.016850181711592 -log_molalities_map 28 -16.039553873072 - 34 -21.787317082583 + 34 -21.787317082584 63 -2.9208187541072 - 118 -7.0657289997183 + 118 -7.0657289997177 119 -45.224921210092 121 -1.9696121789171e-05 178 -3.6176643963109 216 -3.018261483559 - 221 -20.117716074195 + 221 -20.117716074196 225 -3.5726241189866 - 226 -7.0657289997005 + 226 -7.0657289997012 SOLUTION_RAW 8 Solution after simulation 1. -temp 20 -pressure 2 -potential 0 -total_h 22.162951611395 -total_o 11.08158262798 - -cb 1.4762011126612e-13 + -cb 1.4762011059445e-13 -density 0.99830112943876 -totals Ca 3.6343034818735e-24 @@ -637,7 +677,7 @@ -ah2o 0.99995464903202 -mass_water 0.19964386780629 -soln_vol 0.19999999448756 - -total_alkalinity 1.5768709453221e-19 + -total_alkalinity 1.5902712712454e-19 -activities Ca -22.805952199731 Cl -2.9376246512503 @@ -649,16 +689,16 @@ -gammas -species_map 28 1.8171485429377e-23 - 34 3.2480837646164e-29 + 34 3.2480837646166e-29 63 0.0011978632394264 - 118 8.5801917127278e-08 + 118 8.5801917127274e-08 119 0 121 55.407380469834 178 0.00019917105449233 216 0.00099869218567215 - 221 7.9428628038093e-21 + 221 7.9428628038095e-21 225 0.00026705571260374 - 226 8.5801917128058e-08 + 226 8.5801917128061e-08 -log_gamma_map 28 -0.066116638525128 34 -0.016751008783797 @@ -689,7 +729,7 @@ -potential 0 -total_h 22.162953117956 -total_o 11.081583381352 - -cb -1.7985345045349e-17 + -cb -1.7986221856798e-17 -density 0.99830111534656 -totals Cl 0.00023957265756751 @@ -701,7 +741,7 @@ -ah2o 0.99995464902842 -mass_water 0.19964388137738 -soln_vol 0.20000000268793 - -total_alkalinity 1.8857732732739e-19 + -total_alkalinity 1.90330950226e-19 -activities Cl -2.9376246512477 E -13.966513177935 @@ -712,14 +752,14 @@ -gammas -species_map 63 0.0011978632717387 - 118 8.5801919441062e-08 + 118 8.5801919441058e-08 119 0 121 55.407381964433 178 0.00019662467488215 216 0.0010012385968565 - 221 7.9631150847523e-21 + 221 7.9631150847527e-21 225 0.00026705593181208 - 226 8.5801919441997e-08 + 226 8.5801919442002e-08 -log_gamma_map 63 -0.016805897140598 118 -0.015895630669395 @@ -740,105 +780,6 @@ 221 -20.098143010819 225 -3.5726237742079 226 -7.06572899972 - EXCHANGE_RAW 5 Exchange assemblage after simulation 1. - # EXCHANGE_MODIFY candidate identifiers # - -exchange_gammas 1 - -component X - # EXCHANGE_MODIFY candidate identifiers # - -totals - Ca 5.5744649285429e-05 - K 0.00010629152848211 - Na 2.2191763568915e-06 - X 0.00022000000340986 - -charge_balance 0 - -la 1.944331735805 - -phase_proportion 0 - -formula_z 0 - # EXCHANGE_MODIFY candidates with new_def=true # - -new_def 0 - -solution_equilibria 0 - -n_solution -999 - # Exchange workspace variables # - -totals - EXCHANGE_RAW 6 Exchange assemblage after simulation 1. - # EXCHANGE_MODIFY candidate identifiers # - -exchange_gammas 1 - -component X - # EXCHANGE_MODIFY candidate identifiers # - -totals - Ca 7.8889601139241e-09 - K 0.00018164031862247 - Na 3.834390693595e-05 - X 0.00022000000347865 - -charge_balance 0 - -la 2.4447973951359 - -phase_proportion 0 - -formula_z 0 - # EXCHANGE_MODIFY candidates with new_def=true # - -new_def 0 - -solution_equilibria 0 - -n_solution -999 - # Exchange workspace variables # - -totals - EXCHANGE_RAW 7 Exchange assemblage after simulation 1. - # EXCHANGE_MODIFY candidate identifiers # - -exchange_gammas 1 - -component X - # EXCHANGE_MODIFY candidate identifiers # - -totals - Ca 1.2401487775899e-14 - K 0.00012430967079948 - Na 9.5690332585441e-05 - X 0.00022000000340973 - -charge_balance 0 - -la 2.6567385148108 - -phase_proportion 0 - -formula_z 0 - # EXCHANGE_MODIFY candidates with new_def=true # - -new_def 0 - -solution_equilibria 0 - -n_solution -999 - # Exchange workspace variables # - -totals - EXCHANGE_RAW 8 Exchange assemblage after simulation 1. - # EXCHANGE_MODIFY candidate identifiers # - -exchange_gammas 1 - -component X - # EXCHANGE_MODIFY candidate identifiers # - -totals - Ca 2.9132510803319e-21 - K 0.00011162525174619 - Na 0.00010837475166344 - X 0.00022000000340963 - -charge_balance 0 - -la 2.6923314222035 - -phase_proportion 0 - -formula_z 0 - # EXCHANGE_MODIFY candidates with new_def=true # - -new_def 0 - -solution_equilibria 0 - -n_solution -999 - # Exchange workspace variables # - -totals - EXCHANGE_RAW 9 Exchange assemblage after simulation 1. - # EXCHANGE_MODIFY candidate identifiers # - -exchange_gammas 1 - -component X - # EXCHANGE_MODIFY candidate identifiers # - -totals - K 0.00011077759703565 - Na 0.00010922240637403 - X 0.00022000000340969 - -charge_balance 0 - -la 2.6946091280289 - -phase_proportion 0 - -formula_z 0 - # EXCHANGE_MODIFY candidates with new_def=true # - -new_def 0 - -solution_equilibria 0 - -n_solution -999 - # Exchange workspace variables # - -totals SOLUTION_RAW 10 Solution after simulation 1. -temp 20 -pressure 2 @@ -983,6 +924,107 @@ 221 -20.098107260029 225 -3.5725641150886 226 -7.0657289998579 + EXCHANGE_RAW 7 Exchange assemblage after simulation 1. + # EXCHANGE_MODIFY candidate identifiers # + -exchange_gammas 1 + -component X + # EXCHANGE_MODIFY candidate identifiers # + -totals + Ca 1.2401487775899e-14 + K 0.00012430967079948 + Na 9.5690332585441e-05 + X 0.00022000000340973 + -charge_balance 0 + -la 2.6567385148108 + -phase_proportion 0 + -formula_z 0 + # EXCHANGE_MODIFY candidates with new_def=true # + -new_def 0 + -solution_equilibria 0 + -n_solution -999 + # Exchange workspace variables # + -totals + EXCHANGE_RAW 8 Exchange assemblage after simulation 1. + # EXCHANGE_MODIFY candidate identifiers # + -exchange_gammas 1 + -component X + # EXCHANGE_MODIFY candidate identifiers # + -totals + Ca 2.9132510803319e-21 + K 0.00011162525174619 + Na 0.00010837475166344 + X 0.00022000000340963 + -charge_balance 0 + -la 2.6923314222035 + -phase_proportion 0 + -formula_z 0 + # EXCHANGE_MODIFY candidates with new_def=true # + -new_def 0 + -solution_equilibria 0 + -n_solution -999 + # Exchange workspace variables # + -totals + EXCHANGE_RAW 9 Exchange assemblage after simulation 1. + # EXCHANGE_MODIFY candidate identifiers # + -exchange_gammas 1 + -component X + # EXCHANGE_MODIFY candidate identifiers # + -totals + K 0.00011077759703565 + Na 0.00010922240637403 + X 0.00022000000340969 + -charge_balance 0 + -la 2.6946091280289 + -phase_proportion 0 + -formula_z 0 + # EXCHANGE_MODIFY candidates with new_def=true # + -new_def 0 + -solution_equilibria 0 + -n_solution -999 + # Exchange workspace variables # + -totals + EXCHANGE_RAW 10 Exchange assemblage after simulation 1. + # EXCHANGE_MODIFY candidate identifiers # + -exchange_gammas 1 + -component X + # EXCHANGE_MODIFY candidate identifiers # + -totals + H 1.5569735310392e-64 + K 0.0001107500100945 + N 3.8924338275979e-65 + Na 0.00010924999331512 + X 0.00022000000340963 + -charge_balance 0 + -la 2.6946830555387 + -phase_proportion 0 + -formula_z 0 + # EXCHANGE_MODIFY candidates with new_def=true # + -new_def 0 + -solution_equilibria 0 + -n_solution -999 + # Exchange workspace variables # + -totals + EXCHANGE_RAW 11 Exchange assemblage after simulation 1. + # EXCHANGE_MODIFY candidate identifiers # + -exchange_gammas 1 + -component X + # EXCHANGE_MODIFY candidate identifiers # + -totals + H 1.5569735310392e-64 + K 0.0001107500100945 + N 3.8924338275979e-65 + Na 0.00010924999331512 + X 0.00022000000340963 + -charge_balance 0 + -la 2.6946830555387 + -phase_proportion 0 + -formula_z 0 + # EXCHANGE_MODIFY candidates with new_def=true # + -new_def 0 + -solution_equilibria 0 + -n_solution -999 + # Exchange workspace variables # + -totals SOLUTION_RAW 12 Solution after simulation 1. -temp 20 -pressure 2 @@ -1559,48 +1601,6 @@ 221 -20.098107260029 225 -3.5725641150886 226 -7.0657289998579 - EXCHANGE_RAW 10 Exchange assemblage after simulation 1. - # EXCHANGE_MODIFY candidate identifiers # - -exchange_gammas 1 - -component X - # EXCHANGE_MODIFY candidate identifiers # - -totals - H 1.5569735310392e-64 - K 0.0001107500100945 - N 3.8924338275979e-65 - Na 0.00010924999331512 - X 0.00022000000340963 - -charge_balance 0 - -la 2.6946830555387 - -phase_proportion 0 - -formula_z 0 - # EXCHANGE_MODIFY candidates with new_def=true # - -new_def 0 - -solution_equilibria 0 - -n_solution -999 - # Exchange workspace variables # - -totals - EXCHANGE_RAW 11 Exchange assemblage after simulation 1. - # EXCHANGE_MODIFY candidate identifiers # - -exchange_gammas 1 - -component X - # EXCHANGE_MODIFY candidate identifiers # - -totals - H 1.5569735310392e-64 - K 0.0001107500100945 - N 3.8924338275979e-65 - Na 0.00010924999331512 - X 0.00022000000340963 - -charge_balance 0 - -la 2.6946830555387 - -phase_proportion 0 - -formula_z 0 - # EXCHANGE_MODIFY candidates with new_def=true # - -new_def 0 - -solution_equilibria 0 - -n_solution -999 - # Exchange workspace variables # - -totals EXCHANGE_RAW 12 Exchange assemblage after simulation 1. # EXCHANGE_MODIFY candidate identifiers # -exchange_gammas 1 diff --git a/Tests/Output/Species_f90_utility.txt b/Tests/Output/Species_f90_utility.txt index f7652541f..e3424b48e 100644 --- a/Tests/Output/Species_f90_utility.txt +++ b/Tests/Output/Species_f90_utility.txt @@ -37,7 +37,7 @@ Using solution 1. Activity of water = 1.000 Ionic strength (mol/kgw) = 1.500e-03 Mass of water (kg) = 9.982e-01 - Total alkalinity (eq/kg) = 4.870e-19 + Total alkalinity (eq/kg) = 4.891e-19 Temperature (°C) = 15.00 Pressure (atm) = 3.00 Electrical balance (eq) = -4.257e-17 @@ -90,7 +90,7 @@ End of simulation. Reading input data for simulation 2. ------------------------------------ --------------------------------- -End of Run after 13.414 Seconds. --------------------------------- +------------------------------- +End of Run after 2.011 Seconds. +------------------------------- diff --git a/Tests/SimpleAdvect_c.c b/Tests/SimpleAdvect_c.c index b1007e330..2e40ace2a 100644 --- a/Tests/SimpleAdvect_c.c +++ b/Tests/SimpleAdvect_c.c @@ -253,7 +253,7 @@ void simpleadvection_c(double* c, double* bc_conc, int ncomps, int nxyz, int dim { int i, j; // Advect - for (i = nxyz / 2 - 1; i > 0; i--) + for (i = nxyz - 1; i > 0; i--) { for (j = 0; j < ncomps; j++) { diff --git a/Tests/SimpleAdvect_cpp.cpp b/Tests/SimpleAdvect_cpp.cpp index c86977f81..f0b964f53 100644 --- a/Tests/SimpleAdvect_cpp.cpp +++ b/Tests/SimpleAdvect_cpp.cpp @@ -186,7 +186,7 @@ int SimpleAdvect_cpp() void simpleadvection_cpp(std::vector& c, std::vector bc_conc, int ncomps, int nxyz, int dim) { - for (int i = nxyz / 2 - 1; i > 0; i--) + for (int i = nxyz - 1; i > 0; i--) { for (int j = 0; j < ncomps; j++) { diff --git a/Tests/SimpleAdvect_f90.F90 b/Tests/SimpleAdvect_f90.F90 index 0dcd8730e..d7b2be212 100644 --- a/Tests/SimpleAdvect_f90.F90 +++ b/Tests/SimpleAdvect_f90.F90 @@ -11,8 +11,8 @@ subroutine SimpleAdvect_f90() BIND(C, NAME='SimpleAdvect_f90') interface subroutine simpleadvection_f90(c, bc_conc, ncomps, nxyz) implicit none - double precision, dimension(:,:), allocatable, intent(inout) :: c - double precision, dimension(:,:), allocatable, intent(in) :: bc_conc + real(kind=8), dimension(:,:), allocatable, intent(inout) :: c + real(kind=8), dimension(:,:), allocatable, intent(in) :: bc_conc integer, intent(in) :: ncomps, nxyz end subroutine simpleadvection_f90 end interface @@ -24,7 +24,7 @@ end subroutine simpleadvection_f90 integer :: nthreads integer :: id integer :: status - double precision, dimension(:), allocatable :: por + real(kind=8), dimension(:), allocatable :: por integer, dimension(:), allocatable :: print_chemistry_mask integer :: nchem character(100) :: string @@ -33,11 +33,11 @@ end subroutine simpleadvection_f90 integer, dimension(:,:), allocatable :: ic1 integer :: nbound integer, dimension(:), allocatable :: bc1 - double precision, dimension(:,:), allocatable :: bc_conc - double precision, dimension(:,:), allocatable :: c - double precision :: time, time_step - double precision, dimension(:), allocatable :: temperature - double precision, dimension(:), allocatable :: pressure + real(kind=8), dimension(:,:), allocatable :: bc_conc + real(kind=8), dimension(:,:), allocatable :: c + real(kind=8) :: time, time_step + real(kind=8), dimension(:), allocatable :: temperature + real(kind=8), dimension(:), allocatable :: pressure integer :: isteps, nsteps ! -------------------------------------------------------------------------- ! Create PhreeqcRM @@ -200,12 +200,12 @@ end subroutine SimpleAdvect_F90 SUBROUTINE simpleadvection_f90(c, bc_conc, ncomps, nxyz) implicit none - double precision, dimension(:,:), allocatable, intent(inout) :: c - double precision, dimension(:,:), allocatable, intent(in) :: bc_conc + real(kind=8), dimension(:,:), allocatable, intent(inout) :: c + real(kind=8), dimension(:,:), allocatable, intent(in) :: bc_conc integer, intent(in) :: ncomps, nxyz integer :: i, j ! Advect - do i = nxyz/2, 2, -1 + do i = nxyz, 2, -1 do j = 1, ncomps c(i,j) = c(i-1,j) enddo diff --git a/Tests/Species_f90.F90 b/Tests/Species_f90.F90 index 3dd250cbd..0a152982b 100644 --- a/Tests/Species_f90.F90 +++ b/Tests/Species_f90.F90 @@ -11,8 +11,8 @@ subroutine Species_f90() BIND(C, NAME='Species_f90') interface subroutine speciesadvection_f90(c, bc_conc, ncomps, nxyz) implicit none - double precision, dimension(:,:), allocatable :: bc_conc - double precision, dimension(:,:), allocatable :: c + real(kind=8), dimension(:,:), allocatable :: bc_conc + real(kind=8), dimension(:,:), allocatable :: c integer :: ncomps, nxyz end subroutine speciesadvection_f90 end interface @@ -25,9 +25,9 @@ end subroutine speciesadvection_f90 integer :: nthreads integer :: id integer :: status - double precision, dimension(:), allocatable :: rv - double precision, dimension(:), allocatable :: por - double precision, dimension(:), allocatable :: sat + real(kind=8), dimension(:), allocatable :: rv + real(kind=8), dimension(:), allocatable :: por + real(kind=8), dimension(:), allocatable :: sat integer, dimension(:), allocatable :: print_chemistry_mask integer, dimension(:), allocatable :: grid2chem integer :: nchem @@ -35,34 +35,34 @@ end subroutine speciesadvection_f90 character(200) :: string1 integer :: ncomps, ncomps1 character(100), dimension(:), allocatable :: components - double precision, dimension(:), allocatable :: gfw + real(kind=8), dimension(:), allocatable :: gfw integer, dimension(:,:), allocatable :: ic1, ic2 - double precision, dimension(:,:), allocatable :: f1 + real(kind=8), dimension(:,:), allocatable :: f1 integer :: nbound integer, dimension(:), allocatable :: bc1, bc2 - double precision, dimension(:), allocatable :: bc_f1 + real(kind=8), dimension(:), allocatable :: bc_f1 integer, dimension(:), allocatable :: module_cells - double precision, dimension(:,:), allocatable :: bc_conc - double precision, dimension(:,:), allocatable :: c - double precision, dimension(:,:), allocatable :: species_c - double precision, dimension(:,:), allocatable :: species_log10gammas - double precision, dimension(:,:), allocatable :: species_log10molalities + real(kind=8), dimension(:,:), allocatable :: bc_conc + real(kind=8), dimension(:,:), allocatable :: c + real(kind=8), dimension(:,:), allocatable :: species_c + real(kind=8), dimension(:,:), allocatable :: species_log10gammas + real(kind=8), dimension(:,:), allocatable :: species_log10molalities integer :: nspecies - double precision, dimension(:), allocatable :: species_d - double precision, dimension(:), allocatable :: species_z - double precision :: time, time_step - double precision, dimension(:), allocatable :: density - double precision, dimension(:), allocatable :: volume - double precision, dimension(:), allocatable :: temperature - double precision, dimension(:), allocatable :: pressure + real(kind=8), dimension(:), allocatable :: species_d + real(kind=8), dimension(:), allocatable :: species_z + real(kind=8) :: time, time_step + real(kind=8), dimension(:), allocatable :: density + real(kind=8), dimension(:), allocatable :: volume + real(kind=8), dimension(:), allocatable :: temperature + real(kind=8), dimension(:), allocatable :: pressure integer :: isteps, nsteps - double precision, dimension(:,:), allocatable :: selected_out + real(kind=8), dimension(:,:), allocatable :: selected_out integer :: col, isel, n_user character(100) :: heading - double precision, dimension(:,:), allocatable :: c_well - double precision, dimension(:), allocatable :: tc, p_atm + real(kind=8), dimension(:,:), allocatable :: c_well + real(kind=8), dimension(:), allocatable :: tc, p_atm integer :: vtype - double precision :: pH + real(kind=8) :: pH character(100) :: svalue integer :: iphreeqc_id integer :: dump_on, append @@ -404,8 +404,8 @@ end subroutine species_f90 subroutine speciesadvection_f90(c, bc_conc, ncomps, nxyz) implicit none - double precision, dimension(:,:), allocatable :: bc_conc - double precision, dimension(:,:), allocatable :: c + real(kind=8), dimension(:,:), allocatable :: bc_conc + real(kind=8), dimension(:,:), allocatable :: c integer :: ncomps, nxyz integer :: i, j ! Advect diff --git a/Tests/WriteYAMLFile_cpp.cpp b/Tests/WriteYAMLFile_cpp.cpp index 20b5ca449..7096c8f02 100644 --- a/Tests/WriteYAMLFile_cpp.cpp +++ b/Tests/WriteYAMLFile_cpp.cpp @@ -17,7 +17,6 @@ void WriteYAMLFile_cpp(void) { YAMLPhreeqcRM yrm; - std::string YAML_filename = "AdvectBMI_cpp.yaml"; int nxyz = 40; // Set GridCellCount yrm.YAMLSetGridCellCount(nxyz); @@ -33,12 +32,12 @@ void WriteYAMLFile_cpp(void) yrm.YAMLOpenFiles(); // Set concentration units - yrm.YAMLSetUnitsSolution(2); // 1, mg/L); 2, mol/L); 3, kg/kgs - yrm.YAMLSetUnitsPPassemblage(1); // 0, mol/L cell); 1, mol/L water); 2 mol/L rock - yrm.YAMLSetUnitsExchange(1); // 0, mol/L cell); 1, mol/L water); 2 mol/L rock - yrm.YAMLSetUnitsSurface(1); // 0, mol/L cell); 1, mol/L water); 2 mol/L rock - yrm.YAMLSetUnitsGasPhase(1); // 0, mol/L cell); 1, mol/L water); 2 mol/L rock - yrm.YAMLSetUnitsSSassemblage(1); // 0, mol/L cell); 1, mol/L water); 2 mol/L rock + yrm.YAMLSetUnitsSolution(2); // 1, mg/L; 2, mol/L; 3, kg/kgs + yrm.YAMLSetUnitsPPassemblage(1); // 0, mol/L cell; 1, mol/L water; 2 mol/L rock + yrm.YAMLSetUnitsExchange(1); // 0, mol/L cell; 1, mol/L water; 2 mol/L rock + yrm.YAMLSetUnitsSurface(1); // 0, mol/L cell; 1, mol/L water; 2 mol/L rock + yrm.YAMLSetUnitsGasPhase(1); // 0, mol/L cell; 1, mol/L water; 2 mol/L rock + yrm.YAMLSetUnitsSSassemblage(1); // 0, mol/L cell; 1, mol/L water; 2 mol/L rock yrm.YAMLSetUnitsKinetics(1); // 0, mol/L cell; 1, mol/L water; 2 mol/L rock // Set conversion from seconds to user units (days) Only affects one print statement @@ -47,6 +46,9 @@ void WriteYAMLFile_cpp(void) // Set representative volume std::vector rv(nxyz, 1.0); yrm.YAMLSetRepresentativeVolume(rv); + // Set density + std::vector density(nxyz, 1.0); + yrm.YAMLSetDensity(density); // Set initial porosity std::vector por(nxyz, 0.2); yrm.YAMLSetPorosity(por); @@ -126,7 +128,8 @@ void WriteYAMLFile_cpp(void) yrm.YAMLSetTimeStep(86400); // Write YAML file + std::string YAML_filename = "AdvectBMI_cpp.yaml"; yrm.WriteYAMLDoc(YAML_filename); - yrm.clear(); + yrm.Clear(); }; #endif \ No newline at end of file diff --git a/Tests/WriteYAMLFile_f90.F90 b/Tests/WriteYAMLFile_f90.F90 new file mode 100644 index 000000000..b076e9f77 --- /dev/null +++ b/Tests/WriteYAMLFile_f90.F90 @@ -0,0 +1,141 @@ +#ifdef USE_YAML + subroutine WriteYAMLFile_f90() BIND(C, NAME='WriteYAMLFile_f90') + USE, intrinsic :: ISO_C_BINDING + USE YAML_interface + implicit none + integer :: id + integer :: status, i + integer :: nxyz + character(len=100) :: input, YAML_filename + real(kind=8) :: time_conversion + logical :: workers, initial_phreeqc, utility + real(kind=8) :: time, time_step + real(kind=8), allocatable, dimension(:) :: density + real(kind=8), allocatable, dimension(:) :: rv + real(kind=8), allocatable, dimension(:) :: por + real(kind=8), allocatable, dimension(:) :: sat + integer, allocatable, dimension(:) :: print_chemistry_mask + integer, allocatable, dimension(:) :: grid2chem + integer, allocatable, dimension(:,:) :: ic1 + integer, allocatable, dimension(:,:) :: ic2 + real(kind=8), allocatable, dimension(:,:) :: f1 + integer, allocatable, dimension(:) :: module_cells + ! Create YAMLPhreeqcRM document + id = CreateYAMLPhreeqcRM() + ! Number of cells + nxyz = 40; + ! Set GridCellCount + status = YAMLSetGridCellCount(id, nxyz) + ! Set some properties + status = YAMLSetErrorHandlerMode(id, 1) + status = YAMLSetComponentH2O(id, .false.) + status = YAMLSetRebalanceFraction(id, 0.5d0) + status = YAMLSetRebalanceByCell(id, .true.) + status = YAMLUseSolutionDensityVolume(id, .false.) + status = YAMLSetPartitionUZSolids(id, .false.) + status = YAMLSetFilePrefix(id, "AdvectBMI_f90") + status = YAMLOpenFiles(id) + ! Set concentration units + status = YAMLSetUnitsSolution(id, 2) ! 1, mg/L; 2, mol/L; 3, kg/kgs + status = YAMLSetUnitsPPassemblage(id, 1) ! 0, mol/L cell; 1, mol/L water; 2 mol/L rock + status = YAMLSetUnitsExchange(id, 1) ! 0, mol/L cell; 1, mol/L water; 2 mol/L rock + status = YAMLSetUnitsSurface(id, 1) ! 0, mol/L cell; 1, mol/L water; 2 mol/L rock + status = YAMLSetUnitsGasPhase(id, 1) ! 0, mol/L cell; 1, mol/L water; 2 mol/L rock + status = YAMLSetUnitsSSassemblage(id, 1) ! 0, mol/L cell; 1, mol/L water; 2 mol/L rock + status = YAMLSetUnitsKinetics(id, 1) ! 0, mol/L cell; 1, mol/L water; 2 mol/L rock + + ! Set conversion from seconds to user units (days) Only affects one print statement + time_conversion = 1.0d0 / 86400.0d0 + status = YAMLSetTimeConversion(id, time_conversion) + + ! Set representative volume + allocate(rv(nxyz)) + rv = 1.0d0 + status = YAMLSetRepresentativeVolume(id, rv) + ! Set initial density + allocate(density(nxyz)) + density = 1.0d0 + status = YAMLSetDensity(id, density) + ! Set initial porosity + allocate(por(nxyz)) + por = 0.2d0 + status = YAMLSetPorosity(id, por) + ! Set initial saturation + allocate(sat(nxyz)) + sat = 1.0d0 + status = YAMLSetSaturation(id, sat) + ! Set cells to print chemistry when print chemistry is turned on + allocate(print_chemistry_mask(nxyz)) + print_chemistry_mask = 0 + do i = 1, nxyz / 2 + print_chemistry_mask(i) = 1 + enddo + status = YAMLSetPrintChemistryMask(id, print_chemistry_mask) + ! Demonstation of mapping, two equivalent rows by symmetry + ! zero-based indexing + allocate(grid2chem(nxyz)) + grid2chem = -1 + do i = 1, nxyz / 2 + grid2chem(i) = i - 1 + grid2chem(i + nxyz / 2) = i - 1 + enddo + status = YAMLCreateMapping(id, grid2chem) + ! Set printing of chemistry file + status = YAMLSetPrintChemistryOn(id, .false., .true., .false.) ! workers, initial_phreeqc, utility + ! Load database + status = YAMLLoadDatabase(id, "phreeqc.dat") + ! Run file to define solutions and reactants for initial conditions, selected output + workers = .true. ! Worker instances do the reaction calculations for transport + initial_phreeqc = .true. ! InitialPhreeqc instance accumulates initial and boundary conditions + utility = .true. ! Utility instance is available for processing + status = YAMLRunFile(id, workers, initial_phreeqc, utility, "advect.pqi") + ! Clear contents of workers and utility + initial_phreeqc = .false. + input = "DELETE; -all" + status = YAMLRunString(id, workers, initial_phreeqc, utility, input) + ! Determine number of components to transport + status = YAMLFindComponents(id) + ! set array of initial conditions + allocate(ic1(nxyz,7), ic2(nxyz,7), f1(nxyz,7)) + ic1 = -1 + ic2 = -1 + f1 = 1.0d0 + do i = 1, nxyz + ic1(i,1) = 1 ! Solution 1 + ic1(i,2) = -1 ! Equilibrium phases none + ic1(i,3) = 1 ! Exchange 1 + ic1(i,4) = -1 ! Surface none + ic1(i,5) = -1 ! Gas phase none + ic1(i,6) = -1 ! Solid solutions none + ic1(i,7) = -1 ! Kinetics none + enddo + status = YAMLInitialPhreeqc2Module_mix(id, ic1, ic2, f1) + ! No mixing is defined, so the following is equivalent + !status = YAMLInitialPhreeqc2Module(id, id, ic1) + + ! alternative for setting initial conditions + ! cell number in first argument (id, -1 indicates last solution, 40 in this case) + ! in advect.pqi and any reactants with the same number-- + ! Equilibrium phases, exchange, surface, gas phase, solid solution, and (id, or) kinetics-- + ! will be written to cells 18 and 19 (id, 0 based) + allocate(module_cells(2)) + module_cells(1) = 18 + module_cells(2) = 19 + status = YAMLInitialPhreeqcCell2Module(id, -1, module_cells) + ! Initial equilibration of cells + time_step = 0.0d0 ! no kinetics + status = YAMLSetTimeStep(id, time_step) + time = 0.0d0 + status = YAMLSetTime(id, time) + status = YAMLRunCells(id) + time_step = 86400.0d0 + status = YAMLSetTimeStep(id, time_step) + + ! Write YAML file + YAML_filename = "AdvectBMI_f90.yaml" + status = WriteYAMLDoc(id, YAML_filename) + status = YAMLClear(id) + status = DestroyYAMLPhreeqcRM(id) + status = 0 + end subroutine WriteYAMLFile_f90 +#endif \ No newline at end of file diff --git a/Tests/check.mk b/Tests/autotools.mk similarity index 92% rename from Tests/check.mk rename to Tests/autotools.mk index 6fb276233..89d49386e 100644 --- a/Tests/check.mk +++ b/Tests/autotools.mk @@ -58,8 +58,8 @@ cleanfiles =\ Utility_cpp.out -test : $(objects) - $(CXX) -o test $(objects) -L$(LIBDIR) -lphreeqcrm -lyaml-cpp +autotools_test : $(objects) + $(CXX) -o autotools_test $(objects) -L$(LIBDIR) -lphreeqcrm -lyaml-cpp clean : rm -f $(objects) $(cleanfiles) test diff --git a/Tests/main.cpp b/Tests/main.cpp index 08bcf061d..d2be5058e 100644 --- a/Tests/main.cpp +++ b/Tests/main.cpp @@ -11,12 +11,14 @@ extern "C" { extern void Advect_c(void); extern void Advect_f90(void); +extern void AdvectBMI_f90(void); extern void Gas_c(void); extern void Gas_f90(void); extern void SimpleAdvect_c(void); extern void SimpleAdvect_f90(void); extern void Species_c(void); extern void Species_f90(void); +extern void WriteYAMLFile_f90(void); #if defined(__cplusplus) } @@ -85,6 +87,11 @@ int main(int argc, char* argv[]) if (root) std::cerr << "Done SimpleAdvect_f90.==================================" << std::endl; Advect_f90(); if (root) std::cerr << "Done Advect_f90.==================================" << std::endl; +#ifdef USE_YAML + WriteYAMLFile_f90(); + AdvectBMI_f90(); +#endif + if (root) std::cerr << "Done AdvectBMI_f90.==================================" << std::endl; Species_f90(); if (root) std::cerr << "Done Species_f90.====================================" << std::endl; Gas_f90(); diff --git a/Tests/pkgconfig.mk b/Tests/pkgconfig.mk new file mode 100644 index 000000000..21accfd05 --- /dev/null +++ b/Tests/pkgconfig.mk @@ -0,0 +1,70 @@ +PKGCONFIG= pkg-config +CPPFLAGS:= $(shell $(PKGCONFIG) --cflags phreeqcrm) +LDLIBS:= $(shell $(PKGCONFIG) --libs phreeqcrm) + +objects =\ + AdvectBMI_cpp.o\ + Advect_c.o\ + Advect_cpp.o\ + Gas_c.o\ + Gas_cpp.o\ + main.o\ + SimpleAdvect_c.o\ + SimpleAdvect_cpp.o\ + Species_c.o\ + Species_cpp.o\ + WriteYAMLFile_cpp.o + +cleanfiles =\ + Advect_c_utility.txt\ + Advect_c.chem.txt\ + Advect_c.dmp\ + Advect_c.log.txt\ + Advect_cpp_units_utility.txt\ + Advect_cpp_units_worker.chem.txt\ + Advect_cpp_units_worker.log.txt\ + Advect_cpp_units_worker.txt\ + Advect_cpp_utility.txt\ + Advect_cpp.chem.txt\ + Advect_cpp.dmp\ + Advect_cpp.log.txt\ + AdvectBMI_cpp_units_utility.txt\ + AdvectBMI_cpp_units_worker.txt\ + AdvectBMI_cpp_utility.txt\ + AdvectBMI_cpp.chem.txt\ + AdvectBMI_cpp.dmp\ + AdvectBMI_cpp.log.txt\ + AdvectBMI_cpp.yaml\ + Advectcpp_utility.txt\ + Advectcpp.dmp\ + Gas_c_utility.txt\ + Gas_c.chem.txt\ + Gas_c.dmp\ + Gas_c.log.txt\ + Gas_cpp_utility.txt\ + Gas_cpp.chem.txt\ + Gas_cpp.dmp\ + Gas_cpp.log.txt\ + SimpleAdvect_c.chem.txt\ + SimpleAdvect_c.log.txt\ + SimpleAdvect_cpp.chem.txt\ + SimpleAdvect_cpp.log.txt\ + Species_c_utility.txt\ + Species_c.chem.txt\ + Species_c.dmp\ + Species_c.log.txt\ + Species_cpp_utility.txt\ + Species_cpp.chem.txt\ + Species_cpp.dmp\ + Species_cpp.log.txt\ + Units_Worker.chem.txt\ + Units_Worker.log.txt\ + Utility_c.txt\ + Utility_cpp.out + + +pkgconfig_test : $(objects) + $(CXX) -o pkgconfig_test $(objects) $(LDLIBS) + +clean : + rm -f $(objects) $(cleanfiles) pkgconfig_test diff --git a/configure.ac b/configure.ac index 75609bc55..edb712032 100644 --- a/configure.ac +++ b/configure.ac @@ -20,23 +20,27 @@ AC_DEFINE([NDEBUG], , [Must be set for PhreeqcRM]) # check for --with-yaml-cpp AC_ARG_WITH([yaml-cpp], - AS_HELP_STRING([--with-yaml-cpp], - [compile with yaml-cpp support. @<:@default=check@:>@]), - [], [with_yaml_cpp=check]) - -AS_IF([test "x$with_yaml_cpp" != xno], [ - PKG_CHECK_MODULES([yaml_cpp], [yaml-cpp], [have_yaml_cpp=true], [have_yaml_cpp=false]) - if $have_yaml_cpp; then - AC_DEFINE([USE_YAML], [], [Enable yaml-cpp]) - CPPFLAGS="$yaml_cpp_CFLAGS $CPPFLAGS" - LDFLAGS="$yaml_cpp_LIBS $LDFLAGS" - else - AS_IF([test "x$with_yaml_cpp" != xcheck], [ - AC_MSG_FAILURE( - [--with-yaml-cpp was given, but test for yaml-cpp failed (try sudo apt install libyaml-cpp-dev)]) + [AS_HELP_STRING([--with-yaml-cpp], [enable yaml-cpp support. @<:@default=no@:>@])], + [], + [with_yaml_cpp=no]) + +useyaml_define="" +phreeqcrm_requires="" +AS_IF([test "x$with_yaml_cpp" != xno], + [PKG_CHECK_MODULES([YAML_CPP], [yaml-cpp], + [AC_DEFINE([USE_YAML],[1],[Enable yaml-cpp]) + useyaml_define="-DUSE_YAML" + phreeqcrm_requires="yaml-cpp" + CPPFLAGS="$YAML_CPP_CFLAGS $CPPFLAGS" + LDFLAGS="$YAML_CPP_LIBS $LDFLAGS" + ], + [AC_MSG_FAILURE([--with-yaml-cpp was given, but test for yaml-cpp failed]) ]) - fi -]) + ] +) +AC_SUBST(useyaml_define) +AC_SUBST(phreeqcrm_requires) +AM_CONDITIONAL([PHREEQCRM_WITH_YAMLCPP], [test x"$with_yaml_cpp" != xno]) # check for --with-mpi # If --with-mpi=auto is used, try to find MPI, but use standard C compiler if it is not found. @@ -63,13 +67,10 @@ AX_PROG_CXX_MPI([test x"$with_mpi" != xno],[use_mpi=yes],[ ]) AC_PROG_AWK AC_PROG_CPP +AC_PROG_LN_S -# c++11 is required by Darwin for yaml-cpp -if test "X$with_yaml_cpp" != "Xno"; then - if test "X$have_yaml_cpp" != "Xfalse"; then - AX_CXX_COMPILE_STDCXX(11, [ext], [mandatory]) - fi -fi +# c++11 is required +AX_CXX_COMPILE_STDCXX(11, [ext], [mandatory]) # Check if the fortran test should be included AC_MSG_CHECKING([if Fortran test is added]) @@ -253,9 +254,11 @@ fi AM_CONDITIONAL([BUILD_OPENMP], [test "X$enable_openmp" != "Xno"]) AM_CONDITIONAL([BUILD_MPI], [test "X$with_mpi" = "Xyes"]) +usempi_define="" if test "X$with_mpi" != "Xno"; then AC_DEFINE([USE_MPI], [], [Set to use MPI]) PHAST_SUFFIX=mpi + usempi_define="-DUSE_MPI" else if test "X$enable_openmp" != "Xno"; then if test "X$ac_cv_prog_cxx_openmp" != "Xunsupported"; then @@ -263,12 +266,14 @@ else fi fi fi +AC_SUBST(usempi_define) AC_CONFIG_FILES([ Makefile database/Makefile doc/Makefile Doxygen/Makefile + phreeqcrm.pc Tests/Makefile Tests/advect.pqi:Tests/advect.pqi Tests/gas.pqi:Tests/gas.pqi @@ -295,13 +300,5 @@ else echo "Enable OpenMP = no" fi echo "Enable MPI = $with_mpi" -if test "X$with_yaml_cpp" != "Xno"; then - if test "X$have_yaml_cpp" != "Xfalse"; then - echo "Enable YAML-CPP = yes" - else - echo "Enable YAML-CPP = no" - fi -else - echo "Enable YAML-CPP = no" -fi +echo "Enable YAML-CPP = $with_yaml_cpp" echo "*************************************" diff --git a/phreeqcrm.cmake.in b/phreeqcrm.cmake.in new file mode 100644 index 000000000..1e95e6afe --- /dev/null +++ b/phreeqcrm.cmake.in @@ -0,0 +1,12 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=${prefix} +libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@ +includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@ + +Name: PhreeqcRM +Description: A reaction module for transport simulators based on the geochemical model PHREEQC +URL: https://github.com/usgs-coupled/phreeqcrm +Version: @PROJECT_VERSION@ +Requires: +Libs: -L${libdir} -lPhreeqcRM +Cflags: -I${includedir} @useyaml_define@ @usempi_define@ diff --git a/phreeqcrm.pc.in b/phreeqcrm.pc.in new file mode 100644 index 000000000..131861e4e --- /dev/null +++ b/phreeqcrm.pc.in @@ -0,0 +1,13 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: PhreeqcRM +Description: A reaction module for transport simulators based on the geochemical model PHREEQC +URL: https://github.com/usgs-coupled/phreeqcrm +Version: @VERSION@ +Requires: @phreeqcrm_requires@ +Libs.private: @LIBS@ +Libs: -L${libdir} -lphreeqcrm +Cflags: -I${includedir} @useyaml_define@ @usempi_define@ diff --git a/src/BMIPhreeqcRM.cpp b/src/BMIPhreeqcRM.cpp new file mode 100644 index 000000000..ee9f2fbe9 --- /dev/null +++ b/src/BMIPhreeqcRM.cpp @@ -0,0 +1,1027 @@ +#include "BMIPhreeqcRM.h" +#include "BMI_Var.h" +#include "bmi.hxx" +#include +#include +#include +#include +#include + +#include "Phreeqc.h" +#include "IPhreeqcPhast.h" +#include "PhreeqcRM.h" +#include "VarManager.h" + +std::map BMIPhreeqcRM::Instances; +size_t BMIPhreeqcRM::InstancesIndex = 0; + +//// static BMIPhreeqcRM methods +/* ---------------------------------------------------------------------- */ +void +BMIPhreeqcRM::CleanupBMIModuleInstances(void) +/* ---------------------------------------------------------------------- */ +{ + std::map::iterator it = BMIPhreeqcRM::Instances.begin(); + std::vector bmirm_list; + for (; it != BMIPhreeqcRM::Instances.end(); it++) + { + bmirm_list.push_back(it->second); + } + for (size_t i = 0; i < bmirm_list.size(); i++) + { + delete bmirm_list[i]; + } +} +/* ---------------------------------------------------------------------- */ +int +BMIPhreeqcRM::CreateBMIModule(int nxyz, MP_TYPE nthreads) +/* ---------------------------------------------------------------------- */ +{ + //_CrtSetDbgbool ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); + //_crtBreakAlloc = 5144; + int n = IRM_OUTOFMEMORY; + try + { + BMIPhreeqcRM* bmirm_ptr = new BMIPhreeqcRM(nxyz, nthreads); + if (bmirm_ptr) + { + n = (int)bmirm_ptr->GetWorkers()[0]->Get_Index(); + BMIPhreeqcRM::Instances[n] = bmirm_ptr; + bmirm_ptr->language = "F90"; + return n; + } + } + catch (...) + { + return IRM_OUTOFMEMORY; + } + return IRM_OUTOFMEMORY; +} +/* ---------------------------------------------------------------------- */ +IRM_RESULT +BMIPhreeqcRM::DestroyBMIModule(int id) +/* ---------------------------------------------------------------------- */ +{ + IRM_RESULT retval = IRM_BADINSTANCE; + std::map::iterator it = BMIPhreeqcRM::Instances.find(size_t(id)); + if (it != BMIPhreeqcRM::Instances.end()) + { + delete (*it).second; + retval = IRM_OK; + } + return retval; +} +/* ---------------------------------------------------------------------- */ +BMIPhreeqcRM* +BMIPhreeqcRM::GetInstance(int id) +/* ---------------------------------------------------------------------- */ +{ + std::map::iterator it = BMIPhreeqcRM::Instances.find(size_t(id)); + if (it != BMIPhreeqcRM::Instances.end()) + { + return (*it).second; + } + return 0; +} +// Constructor +BMIPhreeqcRM::BMIPhreeqcRM(int nxyz, int nthreads) : +PhreeqcRM(nxyz, nthreads) +{ + std::map::value_type instance(this->GetWorkers()[0]->Get_Index(), this); + BMIPhreeqcRM::Instances.insert(instance); + + this->var_man = new VarManager((PhreeqcRM*)this); + this->language = "cpp"; +} +// Model control functions. +void BMIPhreeqcRM::Initialize(std::string config_file) +{ +#ifdef USE_YAML + this->InitializeYAML(config_file); +#endif +} +void BMIPhreeqcRM::Update() +{ + this->RunCells(); + this->SetTime(this->GetTime() + this->GetTimeStep()); + this->UpdateVariables(); +} +void BMIPhreeqcRM::UpdateVariables() +{ + this->var_man->task = VarManager::VAR_TASKS::Update; + std::set& UpdateSet = this->var_man->UpdateSet; + for (auto it = this->var_man->UpdateSet.begin(); it != UpdateSet.end(); it++) + { + VarManager::VarFunction fn = this->var_man->GetFn(*it); + // ((*this).*f)(); + // ((*this->var_man).*fn)(); + ((*this->var_man).*fn)(); + } +} +void BMIPhreeqcRM::UpdateUntil(double time) +{ + double time_step = time - this->GetTime(); + if (time_step >= 0) + { + this->SetTimeStep(time_step); + this->RunCells(); + this->SetTime(time); + this->UpdateVariables(); + } +} +void BMIPhreeqcRM::Finalize() +{ + this->CloseFiles(); +} +int BMIPhreeqcRM::GetInputItemCount() +{ + int count = 0; + for (auto it = this->var_man->VariantMap.begin(); + it != this->var_man->VariantMap.end(); it++) + { + BMIVariant& bv = it->second; + if (!bv.GetInitialized()) + { + this->var_man->task = VarManager::VAR_TASKS::Info; + //((*this->var_man).*bv.GetFn())(); + ((*this->var_man).*bv.GetFn())(); + } + if (bv.GetHasSetter()) + { + count++; + } + } + return count; +} +int BMIPhreeqcRM::GetOutputItemCount() +{ + int count = 0; + for (auto it = this->var_man->VariantMap.begin(); + it != this->var_man->VariantMap.end(); it++) + { + BMIVariant& bv = it->second; + if (!bv.GetInitialized()) + { + this->var_man->task = VarManager::VAR_TASKS::Info; + ((*this->var_man).*bv.GetFn())(); + } + if (bv.GetHasGetter()) + { + count++; + } + } + return count; +} +int BMIPhreeqcRM::GetPointableItemCount() +{ + int count = 0; + for (auto it = this->var_man->VariantMap.begin(); + it != this->var_man->VariantMap.end(); it++) + { + BMIVariant& bv = it->second; + if (!bv.GetInitialized()) + { + this->var_man->task = VarManager::VAR_TASKS::Info; + ((*this->var_man).*bv.GetFn())(); + } + if (bv.GetHasPtr()) + { + count++; + } + } + return count; +} +std::vector BMIPhreeqcRM::GetInputVarNames() +{ + std::vector names; + for (auto it = this->var_man->VariantMap.begin(); + it != this->var_man->VariantMap.end(); it++) + { + BMIVariant& bv = it->second; + if (!bv.GetInitialized()) + { + this->var_man->task = VarManager::VAR_TASKS::Info; + ((*this->var_man).*bv.GetFn())(); + } + if (bv.GetHasSetter()) + { + names.push_back(bv.GetName()); + } + } + return names; +} +std::vector BMIPhreeqcRM::GetOutputVarNames() +{ + std::vector names; + for (auto it = this->var_man->VariantMap.begin(); + it != this->var_man->VariantMap.end(); it++) + { + BMIVariant& bv = it->second; + if (!bv.GetInitialized()) + { + this->var_man->task = VarManager::VAR_TASKS::Info; + ((*this->var_man).*bv.GetFn())(); + } + if (bv.GetHasGetter()) + { + names.push_back(bv.GetName()); + } + } + return names; +} +std::vector BMIPhreeqcRM::GetPointableVarNames() +{ + std::vector names; + for (auto it = this->var_man->VariantMap.begin(); + it != this->var_man->VariantMap.end(); it++) + { + BMIVariant& bv = it->second; + if (!bv.GetInitialized()) + { + this->var_man->task = VarManager::VAR_TASKS::Info; + ((*this->var_man).*bv.GetFn())(); + } + if (it->first == RMVARS::InputVarNames) + { + continue; + } + if (it->first == RMVARS::OutputVarNames) + { + continue; + } + if (bv.GetHasPtr()) + { + names.push_back(bv.GetName()); + } + } + return names; +} +std::string BMIPhreeqcRM::GetVarType(const std::string name) +{ + RMVARS v_enum = this->var_man->GetEnum(name); + if (v_enum != RMVARS::NotFound) + { + BMIVariant& bv = this->var_man->VariantMap[v_enum]; + //VarManager::VarFunction fn = this->var_man->GetFn(v_enum); + if (!bv.GetInitialized()) + { + this->var_man->task = VarManager::VAR_TASKS::Info; + ((*this->var_man).*bv.GetFn())(); + } + if (this->language == "cpp") + { + return bv.GetCType(); + } + else if (this->language == "F90") + { + return bv.GetFType(); + } + else if (this->language == "Py") + { + return bv.GetPType(); + } + } + assert(false); + return "Unknown language."; +} +std::string BMIPhreeqcRM::GetVarUnits(const std::string name) +{ + RMVARS v_enum = this->var_man->GetEnum(name); + if (v_enum != RMVARS::NotFound) + { + BMIVariant& bv = this->var_man->VariantMap[v_enum]; + //VarManager::VarFunction fn = this->var_man->GetFn(v_enum); + if (!bv.GetInitialized()) + { + this->var_man->task = VarManager::VAR_TASKS::Info; + ((*this->var_man).*bv.GetFn())(); + } + return bv.GetUnits(); + } + assert(false); + return ""; +} + +int BMIPhreeqcRM::GetVarItemsize(const std::string name) +{ + RMVARS v_enum = this->var_man->GetEnum(name); + if (v_enum != RMVARS::NotFound) + { + BMIVariant& bv = this->var_man->VariantMap[v_enum]; + //VarManager::VarFunction fn = this->var_man->GetFn(v_enum); + if (!bv.GetInitialized()) + { + this->var_man->task = VarManager::VAR_TASKS::Info; + ((*this->var_man).*bv.GetFn())(); + } + return bv.GetItemsize(); + } + assert(false); + return 0; +} + +int BMIPhreeqcRM::GetVarNbytes(const std::string name) +{ + RMVARS v_enum = this->var_man->GetEnum(name); + if (v_enum != RMVARS::NotFound) + { + BMIVariant& bv = this->var_man->VariantMap[v_enum]; + //VarManager::VarFunction fn = this->var_man->GetFn(v_enum); + if (!bv.GetInitialized()) + { + this->var_man->task = VarManager::VAR_TASKS::Info; + ((*this->var_man).*bv.GetFn())(); + } + return bv.GetNbytes(); + } + assert(false); + return 0; +} +double BMIPhreeqcRM::GetCurrentTime() +{ + return this->GetTime(); +} +double BMIPhreeqcRM::GetStartTime() +{ + return this->GetTime(); +} +double BMIPhreeqcRM::GetEndTime() +{ + return this->GetTime() + this->GetTimeStep(); +} +//double BMIPhreeqcRM::GetTimeStep() +//{ +// return this->GetTimeStep(); +//} +void BMIPhreeqcRM::GetValue(const std::string name, void* dest) +{ + RMVARS v_enum = this->var_man->GetEnum(name); + if (v_enum != RMVARS::NotFound) + { + BMIVariant& bv = this->var_man->VariantMap[v_enum]; + //VarManager::VarFunction fn = this->var_man->GetFn(v_enum); + if (!bv.GetInitialized()) + { + this->var_man->task = VarManager::VAR_TASKS::Info; + ((*this->var_man).*bv.GetFn())(); + } + this->var_man->task = VarManager::VAR_TASKS::GetVar; + ((*this->var_man).*bv.GetFn())(); + int Nbytes = this->var_man->VarExchange.GetNbytes(); + int dim = this->var_man->VarExchange.GetDim(); + if (this->var_man->VarExchange.GetCType() == "bool" && dim == 1) + { + memcpy(dest, this->var_man->VarExchange.GetBVarPtr(), Nbytes); + return; + } + if (this->var_man->VarExchange.GetCType() == "int" && dim == 1) + { + memcpy(dest, this->var_man->VarExchange.GetIVarPtr(), Nbytes); + return; + } + if (this->var_man->VarExchange.GetCType() == "double" && dim == 1) + { + memcpy(dest, this->var_man->VarExchange.GetDVarPtr(), Nbytes); + return; + } + if (this->var_man->VarExchange.GetCType() == "std::vector") + { + int itemsize = this->GetVarItemsize(name); + //int nbytes = this->GetVarNbytes(name); + std::stringstream all; + for (size_t i = 0; i < this->var_man->VarExchange.GetStringVectorRef().size(); i++) + { + all << std::left << std::setfill(' ') << std::setw(itemsize) << this->var_man->VarExchange.GetStringVectorRef()[i]; + } + memcpy( dest, all.str().data(), all.str().size()); + return; + } + if (this->var_man->VarExchange.GetCType() == "std::string" && dim == 1) + { + memcpy(dest, this->var_man->VarExchange.GetStringRef().data(), Nbytes); + return; + } + if (this->var_man->VarExchange.GetCType() == "double" && dim > 1) + { + memcpy(dest, this->var_man->VarExchange.GetDoubleVectorPtr(), Nbytes); + return; + } + if (this->var_man->VarExchange.GetCType() == "int" && dim > 1) + { + memcpy(dest, this->var_man->VarExchange.GetIntVectorPtr(), Nbytes); + return; + } + } + std::ostringstream oss; + oss << "BMI GetValue void* failed for variable " << name << std::endl; + this->ErrorMessage(oss.str(), true); + assert(false); + return; +} +void BMIPhreeqcRM::GetValue(const std::string name, bool& dest) +{ + RMVARS v_enum = this->var_man->GetEnum(name); + if (v_enum != RMVARS::NotFound) + { + BMIVariant& bv = this->var_man->VariantMap[v_enum]; + //VarManager::VarFunction fn = this->var_man->GetFn(v_enum); + if (!bv.GetInitialized()) + { + this->var_man->task = VarManager::VAR_TASKS::Info; + ((*this->var_man).*bv.GetFn())(); + } + this->var_man->task = VarManager::VAR_TASKS::GetVar; + ((*this->var_man).*bv.GetFn())(); + assert(this->var_man->VarExchange.GetCType() == "bool"); + dest = this->var_man->VarExchange.GetBVar(); + return; + } + assert(false); + return; +} +void BMIPhreeqcRM::GetValue(const std::string name, bool* dest) +{ + RMVARS v_enum = this->var_man->GetEnum(name); + if (v_enum != RMVARS::NotFound) + { + BMIVariant& bv = this->var_man->VariantMap[v_enum]; + //VarManager::VarFunction fn = this->var_man->GetFn(v_enum); + if (!bv.GetInitialized()) + { + this->var_man->task = VarManager::VAR_TASKS::Info; + ((*this->var_man).*bv.GetFn())(); + } + this->var_man->task = VarManager::VAR_TASKS::GetVar; + ((*this->var_man).*bv.GetFn())(); + assert(this->var_man->VarExchange.GetCType() == "bool"); + int dim = this->var_man->VarExchange.GetDim(); + int nbytes = this->var_man->VarExchange.GetNbytes(); + if (dim == 1) + { + memcpy(dest, this->var_man->VarExchange.GetBVarPtr(), nbytes); + return; + } + } + std::ostringstream oss; + oss << "BMI GetValue bool* failed for variable " << name << std::endl; + this->ErrorMessage(oss.str(), true); + assert(false); + return; +} +void BMIPhreeqcRM::GetValue(const std::string name, double& dest) +{ + RMVARS v_enum = this->var_man->GetEnum(name); + if (v_enum != RMVARS::NotFound) + { + BMIVariant& bv = this->var_man->VariantMap[v_enum]; + //VarManager::VarFunction fn = this->var_man->GetFn(v_enum); + if (!bv.GetInitialized()) + { + this->var_man->task = VarManager::VAR_TASKS::Info; + ((*this->var_man).*bv.GetFn())(); + } + this->var_man->task = VarManager::VAR_TASKS::GetVar; + ((*this->var_man).*bv.GetFn())(); + assert(this->var_man->VarExchange.GetCType() == "double"); + dest = this->var_man->VarExchange.GetDVar(); + return; + } + assert(false); + return; +} +void BMIPhreeqcRM::GetValue(const std::string name, double* dest) +{ + RMVARS v_enum = this->var_man->GetEnum(name); + if (v_enum != RMVARS::NotFound) + { + BMIVariant& bv = this->var_man->VariantMap[v_enum]; + //VarManager::VarFunction fn = this->var_man->GetFn(v_enum); + if (!bv.GetInitialized()) + { + this->var_man->task = VarManager::VAR_TASKS::Info; + ((*this->var_man).*bv.GetFn())(); + } + this->var_man->task = VarManager::VAR_TASKS::GetVar; + ((*this->var_man).*bv.GetFn())(); + assert(this->var_man->VarExchange.GetCType() == "double"); + int dim = this->var_man->VarExchange.GetDim(); + int nbytes = this->var_man->VarExchange.GetNbytes(); + if (dim == 1) + { + memcpy(dest, this->var_man->VarExchange.GetDVarPtr(), nbytes); + return; + } + else if (dim > 1) + { + memcpy(dest, this->var_man->VarExchange.GetDoubleVectorPtr(), nbytes); + return; + } + } + std::ostringstream oss; + oss << "BMI GetValue double* failed for variable " << name << std::endl; + this->ErrorMessage(oss.str(), true); + assert(false); + return; +} +void BMIPhreeqcRM::GetValue(const std::string name, int& dest) +{ + RMVARS v_enum = this->var_man->GetEnum(name); + if (v_enum != RMVARS::NotFound) + { + BMIVariant& bv = this->var_man->VariantMap[v_enum]; + //VarManager::VarFunction fn = this->var_man->GetFn(v_enum); + if (!bv.GetInitialized()) + { + this->var_man->task = VarManager::VAR_TASKS::Info; + ((*this->var_man).*bv.GetFn())(); + } + this->var_man->task = VarManager::VAR_TASKS::GetVar; + ((*this->var_man).*bv.GetFn())(); + dest = this->var_man->VarExchange.GetIVar(); + return; + } + assert(false); + return; +} +void BMIPhreeqcRM::GetValue(const std::string name, int* dest) +{ + RMVARS v_enum = this->var_man->GetEnum(name); + if (v_enum != RMVARS::NotFound) + { + BMIVariant& bv = this->var_man->VariantMap[v_enum]; + //VarManager::VarFunction fn = this->var_man->GetFn(v_enum); + if (!bv.GetInitialized()) + { + this->var_man->task = VarManager::VAR_TASKS::Info; + ((*this->var_man).*bv.GetFn())(); + } + this->var_man->task = VarManager::VAR_TASKS::GetVar; + ((*this->var_man).*bv.GetFn())(); + assert(this->var_man->VarExchange.GetCType() == "int"); + int dim = this->var_man->VarExchange.GetDim(); + int nbytes = this->var_man->VarExchange.GetNbytes(); + if (dim == 1) + { + memcpy(dest, this->var_man->VarExchange.GetIVarPtr(), nbytes); + return; + } + else if (dim > 1) + { + memcpy(dest, this->var_man->VarExchange.GetIntVectorPtr(), nbytes); + return; + } + std::ostringstream oss; + oss << "BMI GetValue int* failed for variable " << name << std::endl; + this->ErrorMessage(oss.str(), true); + return; + } + assert(false); + return; +} +void BMIPhreeqcRM::GetValue(const std::string name, std::string& dest) +{ + RMVARS v_enum = this->var_man->GetEnum(name); + if (v_enum != RMVARS::NotFound) + { + BMIVariant& bv = this->var_man->VariantMap[v_enum]; + //VarManager::VarFunction fn = this->var_man->GetFn(v_enum); + if (!bv.GetInitialized()) + { + this->var_man->task = VarManager::VAR_TASKS::Info; + ((*this->var_man).*bv.GetFn())(); + } + this->var_man->task = VarManager::VAR_TASKS::GetVar; + ((*this->var_man).*bv.GetFn())(); + assert(this->var_man->VarExchange.GetCType() == "std::string"); + dest = this->var_man->VarExchange.GetStringVar(); + return; + } + assert(false); + return; +} +void BMIPhreeqcRM::GetValue(const std::string name, std::vector& dest) +{ + RMVARS v_enum = this->var_man->GetEnum(name); + if (v_enum != RMVARS::NotFound) + { + BMIVariant& bv = this->var_man->VariantMap[v_enum]; + //VarManager::VarFunction fn = this->var_man->GetFn(v_enum); + if (!bv.GetInitialized()) + { + this->var_man->task = VarManager::VAR_TASKS::Info; + ((*this->var_man).*bv.GetFn())(); + } + this->var_man->task = VarManager::VAR_TASKS::GetVar; + ((*this->var_man).*bv.GetFn())(); + assert(this->var_man->VarExchange.GetCType() == "double"); + dest = this->var_man->VarExchange.GetDoubleVectorRef(); + return; + } + assert(false); + return; +} +void BMIPhreeqcRM::GetValue(const std::string name, std::vector& dest) +{ + RMVARS v_enum = this->var_man->GetEnum(name); + if (v_enum != RMVARS::NotFound) + { + BMIVariant& bv = this->var_man->VariantMap[v_enum]; + //VarManager::VarFunction fn = this->var_man->GetFn(v_enum); + if (!bv.GetInitialized()) + { + this->var_man->task = VarManager::VAR_TASKS::Info; + ((*this->var_man).*bv.GetFn())(); + } + this->var_man->task = VarManager::VAR_TASKS::GetVar; + ((*this->var_man).*bv.GetFn())(); + dest = this->var_man->VarExchange.GetIntVectorRef(); + return; + } + assert(false); + return; +} +void BMIPhreeqcRM::GetValue(const std::string name, std::vector& dest) +{ + RMVARS v_enum = this->var_man->GetEnum(name); + if (v_enum != RMVARS::NotFound) + { + BMIVariant& bv = this->var_man->VariantMap[v_enum]; + //VarManager::VarFunction fn = this->var_man->GetFn(v_enum); + if (!bv.GetInitialized()) + { + this->var_man->task = VarManager::VAR_TASKS::Info; + ((*this->var_man).*bv.GetFn())(); + } + this->var_man->task = VarManager::VAR_TASKS::GetVar; + ((*this->var_man).*bv.GetFn())(); + dest = this->var_man->VarExchange.GetStringVectorRef(); + return; + } + assert(false); + return; +} +void* BMIPhreeqcRM::GetValuePtr(const std::string name) +{ + RMVARS v_enum = this->var_man->GetEnum(name); + if (v_enum != RMVARS::NotFound) + { + BMIVariant& bv = this->var_man->VariantMap[v_enum]; + //VarManager::VarFunction fn = this->var_man->GetFn(v_enum); + if (bv.GetVoidPtr() == NULL) + { + this->var_man->task = VarManager::VAR_TASKS::GetPtr; + ((*this->var_man).*bv.GetFn())(); + } + return bv.GetVoidPtr(); + } + assert(false); + return NULL; +} +void BMIPhreeqcRM::SetValue(const std::string name, void* src) +{ + RMVARS v_enum = this->var_man->GetEnum(name); + if (v_enum != RMVARS::NotFound) + { + BMIVariant& bv = this->var_man->VariantMap[v_enum]; + //VarManager::VarFunction fn = this->var_man->GetFn(v_enum); + if (!bv.GetInitialized()) + { + this->var_man->task = VarManager::VAR_TASKS::Info; + ((*this->var_man).*bv.GetFn())(); + } + // Store the variable in var_man->VarExchange + int Nbytes = bv.GetNbytes(); + int itemsize = bv.GetItemsize(); + int dim = Nbytes / itemsize; + if (bv.GetCType() == "bool" && dim == 1) + { + memcpy(this->var_man->VarExchange.GetBVarPtr(), src, Nbytes); + } + else if (bv.GetCType() == "int" && dim == 1) + { + memcpy(this->var_man->VarExchange.GetIVarPtr(), src, Nbytes); + } + else if (bv.GetCType() == "double" && dim == 1) + { + memcpy(this->var_man->VarExchange.GetDVarPtr(), src, Nbytes); + } + else if (bv.GetCType() == "std::string") + { + this->var_man->VarExchange.GetStringRef() = (char*)src; + } + else if (bv.GetCType() == "double" && dim > 1) + { + this->var_man->VarExchange.GetDoubleVectorRef().resize(dim); + memcpy(this->var_man->VarExchange.GetDoubleVectorPtr(), src, Nbytes); + } + else if (bv.GetCType() == "int" && dim > 1) + { + this->var_man->VarExchange.GetIntVectorRef().resize(dim); + memcpy(this->var_man->VarExchange.GetIntVectorPtr(), src, Nbytes); + } + //if (this->var_man->VarExchange.GetType() == "StringVector") + //{ + // // Don't think this is possible + // //int itemsize = this->GetVarItemsize(name); + // //int nbytes = this->GetVarNbytes(name); + // //std::stringstream all; + // //for (size_t i = 0; i < this->var_man->VarExchange.GetStringVectorRef().size(); i++) + // //{ + // // all << std::left << std::setfill(' ') << std::setw(itemsize) << this->var_man->VarExchange.GetStringVectorRef()[i]; + // //} + // //memcpy( src, all.str().size()); + //} + else + { + std::ostringstream oss; + oss << "BMI failed in SetValue void* for variable " << name << std::endl; + this->ErrorMessage(oss.str(), true); + throw PhreeqcRMStop(); + } + // Set the variable + this->var_man->task = VarManager::VAR_TASKS::SetVar; + ((*this->var_man).*bv.GetFn())(); + return; + } + assert(false); + return; +} +void BMIPhreeqcRM::SetValue(const std::string name, bool src) +{ + RMVARS v_enum = this->var_man->GetEnum(name); + if (v_enum != RMVARS::NotFound) + { + BMIVariant& bv = this->var_man->VariantMap[v_enum]; + //VarManager::VarFunction fn = this->var_man->GetFn(v_enum); + if (!bv.GetInitialized()) + { + this->var_man->task = VarManager::VAR_TASKS::Info; + ((*this->var_man).*bv.GetFn())(); + } + // Store in var_man->VarExchange + this->var_man->VarExchange.SetCType("bool"); + this->var_man->VarExchange.SetBVar(src); + // Set the variable + this->var_man->task = VarManager::VAR_TASKS::SetVar; + ((*this->var_man).*bv.GetFn())(); + return; + } + assert(false); + return; +} +void BMIPhreeqcRM::SetValue(const std::string name, char* src) +{ + RMVARS v_enum = this->var_man->GetEnum(name); + if (v_enum != RMVARS::NotFound) + { + BMIVariant& bv = this->var_man->VariantMap[v_enum]; + //VarManager::VarFunction fn = this->var_man->GetFn(v_enum); + if (!bv.GetInitialized()) + { + this->var_man->task = VarManager::VAR_TASKS::Info; + ((*this->var_man).*bv.GetFn())(); + } + // Store in var_man->VarExchange + this->var_man->VarExchange.SetStringVar(src); + // Set the variable + this->var_man->task = VarManager::VAR_TASKS::SetVar; + ((*this->var_man).*bv.GetFn())(); + return; + } + assert(false); + return; +} +void BMIPhreeqcRM::SetValue(const std::string name, double src) +{ + RMVARS v_enum = this->var_man->GetEnum(name); + if (v_enum != RMVARS::NotFound) + { + BMIVariant& bv = this->var_man->VariantMap[v_enum]; + //VarManager::VarFunction fn = this->var_man->GetFn(v_enum); + if (!bv.GetInitialized()) + { + this->var_man->task = VarManager::VAR_TASKS::Info; + ((*this->var_man).*bv.GetFn())(); + } + // Store in var_man->VarExchange + this->var_man->VarExchange.SetDVar(src); + // Set the variable + this->var_man->task = VarManager::VAR_TASKS::SetVar; + ((*this->var_man).*bv.GetFn())(); + return; + } + assert(false); + return; +} +void BMIPhreeqcRM::SetValue(const std::string name, int src) +{ + RMVARS v_enum = this->var_man->GetEnum(name); + if (v_enum != RMVARS::NotFound) + { + BMIVariant& bv = this->var_man->VariantMap[v_enum]; + //VarManager::VarFunction fn = this->var_man->GetFn(v_enum); + if (!bv.GetInitialized()) + { + this->var_man->task = VarManager::VAR_TASKS::Info; + ((*this->var_man).*bv.GetFn())(); + } + // Store in var_man->VarExchange + this->var_man->VarExchange.SetIVar(src); + // Set the variable + this->var_man->task = VarManager::VAR_TASKS::SetVar; + ((*this->var_man).*bv.GetFn())(); + return; + } + assert(false); + return; +} +void BMIPhreeqcRM::SetValue(const std::string name, const std::string src) +{ + RMVARS v_enum = this->var_man->GetEnum(name); + if (v_enum != RMVARS::NotFound) + { + BMIVariant& bv = this->var_man->VariantMap[v_enum]; + //VarManager::VarFunction fn = this->var_man->GetFn(v_enum); + if (!bv.GetInitialized()) + { + this->var_man->task = VarManager::VAR_TASKS::Info; + ((*this->var_man).*bv.GetFn())(); + } + // Store in var_man->VarExchange + this->var_man->VarExchange.SetStringVar(src); + // Set the variable + this->var_man->task = VarManager::VAR_TASKS::SetVar; + ((*this->var_man).*bv.GetFn())(); + return; + } + assert(false); + return; +} +void BMIPhreeqcRM::SetValue(const std::string name, std::vector src) +{ + RMVARS v_enum = this->var_man->GetEnum(name); + if (v_enum != RMVARS::NotFound) + { + BMIVariant& bv = this->var_man->VariantMap[v_enum]; + //VarManager::VarFunction fn = this->var_man->GetFn(v_enum); + if (!bv.GetInitialized()) + { + this->var_man->task = VarManager::VAR_TASKS::Info; + ((*this->var_man).*bv.GetFn())(); + } + // Check dimension + int dim = bv.GetDim(); + if (dim != src.size()) + { + std::ostringstream oss; + oss << "Dimension error in SetValue: " << name; + this->ErrorMessage(oss.str()); + return; + } + // Store in var_man->VarExchange + this->var_man->VarExchange.GetDoubleVectorRef().resize(bv.GetDim()); + this->var_man->VarExchange.SetDoubleVector(src); + // Set the variable + this->var_man->task = VarManager::VAR_TASKS::SetVar; + ((*this->var_man).*bv.GetFn())(); + return; + } + assert(false); + return; +} +void BMIPhreeqcRM::SetValue(const std::string name, std::vector src) +{ + RMVARS v_enum = this->var_man->GetEnum(name); + if (v_enum != RMVARS::NotFound) + { + BMIVariant& bv = this->var_man->VariantMap[v_enum]; + //VarManager::VarFunction fn = this->var_man->GetFn(v_enum); + if (!bv.GetInitialized()) + { + this->var_man->task = VarManager::VAR_TASKS::Info; + ((*this->var_man).*bv.GetFn())(); + } // Store in var_man->VarExchange + this->var_man->VarExchange.GetIntVectorRef().resize(bv.GetDim()); + this->var_man->VarExchange.SetIntVector(src); + // Set the variable + this->var_man->task = VarManager::VAR_TASKS::SetVar; + ((*this->var_man).*bv.GetFn())(); + // Set the variable + this->var_man->task = VarManager::VAR_TASKS::SetVar; + ((*this->var_man).*bv.GetFn())(); + return; + } + assert(false); + return; +} +void BMIPhreeqcRM::SetValue(const std::string name, std::vector src) +{ + RMVARS v_enum = this->var_man->GetEnum(name); + if (v_enum != RMVARS::NotFound) + { + BMIVariant& bv = this->var_man->VariantMap[v_enum]; + //VarManager::VarFunction fn = this->var_man->GetFn(v_enum); + if (!bv.GetInitialized()) + { + this->var_man->task = VarManager::VAR_TASKS::Info; + ((*this->var_man).*bv.GetFn())(); + } + this->var_man->VarExchange.SetCType("std::vector"); + this->var_man->VarExchange.SetStringVector(src); + // Set the variable + this->var_man->task = VarManager::VAR_TASKS::SetVar; + ((*this->var_man).*bv.GetFn())(); + return; + } + assert(false); + return; +} +//BMIPhreeqcRM::VarFunction BMIPhreeqcRM::GetFn(const std::string name) +//{ +// this->var_man->VarExchange.Clear(); +// std::string name_lc = name; +// std::transform(name_lc.begin(), name_lc.end(), name_lc.begin(), tolower); +// auto it = varfn_map.find(name_lc); +// if (it == varfn_map.end()) +// { +// std::ostringstream oss; +// oss << "Unknown variable: " << name; +// this->ErrorMessage(oss.str()); +// return NULL; +// } +// +// VarManager::VAR_TASKS task_save = this->var_man->task; +// this->var_man->task = VarManager::VAR_TASKS::Info; +// it->second(this); +// this->var_man->task = task_save; +// if (this->var_man->VarExchange.GetNotImplementedRef()) +// { +// std::ostringstream oss; +// oss << "Not implemented for variable: " << name; +// this->ErrorMessage(oss.str()); +// return NULL; +// } +// if (this->var_man->task == VarManager::VAR_TASKS::GetVar) +// { +// if (!this->var_man->VarExchange.GetHasGetter() || this->var_man->VarExchange.GetNotImplementedRef()) +// { +// std::ostringstream oss; +// oss << "Cannot get variable: " << name; +// this->ErrorMessage(oss.str()); +// return NULL; +// } +// } +// if (this->var_man->task == VarManager::VAR_TASKS::SetVar) +// { +// if (!this->var_man->VarExchange.GetHasSetter() || this->var_man->VarExchange.GetNotImplementedRef()) +// { +// std::ostringstream oss; +// oss << "Cannot set variable: " << name; +// this->ErrorMessage(oss.str()); +// return NULL; +// } +// } +// if (this->var_man->task == VarManager::VAR_TASKS::GetPtr) +// { +// if (this->var_man->VarExchange.GetNotImplementedRef()) +// { +// std::ostringstream oss; +// oss << "Cannot get a pointer to variable: " << name; +// this->ErrorMessage(oss.str()); +// return NULL; +// } +// } +// return it->second; +//} + +int BMIPhreeqcRM::GetGridRank(const int grid) +{ + if (grid == 0) + { + return 1; + } + return 0; +}; + +int BMIPhreeqcRM::GetGridSize(const int grid) +{ + if (grid == 0) + { + return this->GetGridCellCount(); + } + return 0; +}; + +std::string BMIPhreeqcRM::GetGridType(const int grid) +{ + if (grid == 0) + { + return "points"; + } + return "Undefined grid identifier"; +}; + + +////////////////// + + diff --git a/src/BMIPhreeqcRM.h b/src/BMIPhreeqcRM.h new file mode 100644 index 000000000..f17b28664 --- /dev/null +++ b/src/BMIPhreeqcRM.h @@ -0,0 +1,1090 @@ +#if !defined(BMIPHREEQCRM_H_INCLUDED) +#define BMIPHREEQCRM_H_INCLUDED +#include +#include "PhreeqcRM.h" +#include "BMI_Var.h" +#include "bmi.hxx" +class NotImplemented : public std::logic_error { +public: + NotImplemented() : std::logic_error("Not Implemented") { }; +}; + +class IRM_DLL_EXPORT BMIPhreeqcRM : public bmi::Bmi, public PhreeqcRM +{ +public: + static void CleanupBMIModuleInstances(void); + static int CreateBMIModule(int nxyz, MP_TYPE nthreads); + static IRM_RESULT DestroyBMIModule(int n); + static BMIPhreeqcRM* GetInstance(int n); + /** + Constructor for the BMIPhreeqcRM subclass of PhreeqcRM. A BMIPhreeqcRM + instance has the BMI methods plus all of the PhreeqcRM methods. The + constructor requires two arguments: the number of cells in the user's + model, and either (a) the number of threads for OpenMP parallelization, or + (b) an MPI communicator. + @param ngrid Number of cells in the user's model. A value of zero causes + the program to set nthreads to the number of logical processors of the + computer. + @param nthreads Number of threads for parallelization with OpenMP or + an MPI communicator if PhreeqcRM is compiled with MPI. + @retval A BMIPhreeqcRM instance. + @htmlonly + +
+    int nthreads = 0;
+    std::string yaml_file = "myfile.yaml";
+    int nxyz = GetGridCellCountYAML(yaml_file);
+    BMIPhreeqcRM brm(nxyz, nthreads);
+    brm.Initialize(yaml_file);
+    
+
+ @endhtmlonly + */ + BMIPhreeqcRM(int ngrid, int nthreads); + // Model control functions. + /** + @ref Initialize is used to initialize a PhreeqcRM instance. This method is equivalent to + @ref InitializeYAML. A YAML file used for initialization contains a YAML map of PhreeqcRM + methods and the arguments corresponding to the method. For example, + @htmlonly + +
+    LoadDatabase: phreeqc.dat
+    RunFile:
+      workers: true
+      initial_phreeqc: true
+      utility: true
+      chemistry_name: advect.pqi
+    
+
+ @endhtmlonly + + @ref Initialize will read the YAML file and execute the specified methods with + the specified arguments. Using YAML terminology, the argument(s) for a method + may be a scalar, a sequence, or a map, depending if the argument is + a single item, a single vector, or there are multiple arguments. In the case + of a map, the name associated with each argument (for example "chemistry_name" + above) is arbitrary. The names of the map keys for map arguments are not used + in parsing the YAML file; only the order of the arguments is important. + + The PhreeqcRM methods that can be specified in a YAML file include: + @htmlonly + +
+    @n CloseFiles();
+    @n CreateMapping(std::vector< int >& grid2chem);
+    @n DumpModule();
+    @n FindComponents();
+    @n InitialPhreeqc2Module(std::vector< int > initial_conditions1);
+    @n InitialPhreeqc2Module(std::vector< int > initial_conditions1, 
+    @n     std::vector< int > initial_conditions2, std::vector< double > fraction1);
+    @n InitialPhreeqcCell2Module(int n, std::vector< int > cell_numbers);
+    @n LoadDatabase(std::string database);
+    @n OpenFiles(void);
+    @n OutputMessage(std::string str);
+    @n RunCells(void);
+    @n RunFile(bool workers, bool initial_phreeqc, 
+    @n      bool utility, std::string chemistry_name);
+    @n RunString(bool workers, bool initial_phreeqc, bool utility, std::string input_string);
+    @n ScreenMessage(std::string str);
+    @n SetComponentH2O(bool tf);
+    @n SetConcentrations(std::vector< double > c);
+    @n SetCurrentSelectedOutputUserNumber(int n_user);
+    @n SetDensity(std::vector< double > density);
+    @n SetDumpFileName(std::string dump_name);
+    @n SetErrorHandlerMode(int mode);
+    @n SetErrorOn(bool tf);
+    SetFilePrefix(std::string prefix);
+    @n SetGasCompMoles(std::vector< double > gas_moles);
+    @n SetGasPhaseVolume(std::vector< double > gas_volume);
+    @n SetPartitionUZSolids(bool tf);
+    @n SetPorosity(std::vector< double > por);
+    @n SetPressure(std::vector< double > p);
+    @n SetPrintChemistryMask(std::vector< int > cell_mask);
+    @n SetPrintChemistryOn(bool workers, bool initial_phreeqc, bool utility);
+    @n SetRebalanceByCell(bool tf);
+    @n SetRebalanceFraction(double f);
+    @n SetRepresentativeVolume(std::vector< double > rv);
+    @n SetSaturation(std::vector< double > sat);
+    @n SetScreenOn(bool tf);
+    @n SetSelectedOutputOn(bool tf);
+    @n SetSpeciesSaveOn(bool save_on);
+    @n SetTemperature(std::vector< double > t);
+    @n SetTime(double time);
+    @n SetTimeConversion(double conv_factor);
+    @n SetTimeStep(double time_step);
+    @n SetUnitsExchange(int option);
+    @n SetUnitsGasPhase(int option);
+    @n SetUnitsKinetics(int option);
+    @n SetUnitsPPassemblage(int option);
+    @n SetUnitsSolution(int option);
+    @n SetUnitsSSassemblage(int option);
+    @n SetUnitsSurface(int option);
+    @n SpeciesConcentrations2Module(std::vector< double > species_conc);
+    @n StateSave(int istate);
+    @n StateApply(int istate);
+    @n StateDelete(int istate);
+    @n UseSolutionDensityVolume(bool tf);
+    @n WarningMessage(std::string warnstr);
+    
+
+ @endhtmlonly + @see + @ref Update. + @par C++ Example: + @htmlonly + +
+    int nthreads = 0;
+    std::string yaml_file = "myfile.yaml";
+    int nxyz = GetGridCellCountYAML(yaml_file);
+    BMIPhreeqcRM brm(nxyz, nthreads);
+    brm.Initialize(yaml_file);
+    int ncomps;
+    brm.GetValue("ComponentCount", &ncomps);
+    int ngrid;
+    brm.GetValue("GridCellCount", &ngrid);
+    std::vector< double > c;
+    brm.GetValue("Concentrations", c);
+    brm.SetValue("TimeStep", 86400);
+    for(double time = 0; time < 864000; time+=86400)
+    {
+        // Take a transport time step here and update the vector c.
+        brm.SetValue("Time", time);
+        brm.SetValue("Concentrations", c);
+        brm.Update();
+        brm.GetValue("Concentrations", c);
+    }
+    
+
+ @endhtmlonly + @par MPI: + Called by root, workers must be in the loop of @ref MpiWorker. + */ + void Initialize(std::string config_file) override; + /** + @ref Update runs PhreeqcRM for one time step. This method is equivalent to + @ref RunCells. PhreeqcRM will equilibrate the solutions with all equilibrium + reactants (EQUILIBRIUM_PHASES, EXCHANGE, GAS_PHASE, SOLID_SOLUTIONS, and SURFACE) + and integrate KINETICS reactions for the specified time step (@ref SetTimeStep). + @see + @ref Initialize, + @ref UpdateUntil. + @par C++ Example: + @htmlonly + +
+    BMIPhreeqcRM brm(nxyz, nthreads);
+    brm.Initialize("myfile.yaml");
+    int ncomps;
+    brm.GetValue("ComponentCount", &ncomps);
+    int ngrid;
+    brm.GetValue("GridCellCount", &ngrid);
+    std::vector< double > c;
+    brm.GetValue("Concentrations", c);
+    brm.SetValue("TimeStep", 86400);
+    for(double time = 0; time < 864000; time+=86400)
+    {
+        // Take a transport time step here and update the vector c.
+        brm.SetValue("Time", time);
+        brm.SetValue("Concentrations", c);
+        brm.Update();
+        brm.GetValue("Concentrations", c);
+    }
+    
+
+ @endhtmlonly + @par MPI: + Called by root, workers must be in the loop of @ref MpiWorker. + */ + void Update() override; + + /** + @ref UpdateUntil is the same as @ref Update, except the time step is calculated + from the argument @end_time. The time step is calculated to be @a end_time minus + the current time (@ref GetCurrentTime). + @param end_time Time at the end of the time step. + @see + @ref Initialize, + @ref Update. + @par C++ Example: + @htmlonly + +
+    BMIPhreeqcRM brm(nxyz, nthreads);
+    brm.Initialize("myfile.yaml");
+    int ncomps;
+    brm.GetValue("ComponentCount", &ncomps);
+    int ngrid;
+    brm.GetValue("GridCellCount", &ngrid);
+    std::vector< double > c;
+    brm.GetValue("Concentrations", c);
+    for(double time = 0; time < 864000; time+=86400)
+    {
+        // Take a transport time step here and update the vector c.
+        brm.SetValue("Time", time);
+        brm.SetValue("Concentrations", c);
+        brm.UpdateUntil(time + 86400.0);
+        brm.GetValue("Concentrations", c);
+    }
+    
+
+ @endhtmlonly + @par MPI: + Called by root, workers must be in the loop of @ref MpiWorker. + */ + void UpdateUntil(double end_time) override; + /** + @ref Finalize closes any files open in the BMIPhreeqcRM instance. + @par C++ Example: + @htmlonly + +
+    brm.Finalize();
+     
+
+ @endhtmlonly + @par MPI: + Called by root, workers must be in the loop of @ref MpiWorker. + */ + void Finalize() override; + + // Model information functions. + + /** + @ref GetComponentName returns the component name--"BMI PhreeqcRM". + BMI PhreeqcRM is a partial interface to PhreeqcRM, and provides + the most commonly used methods to implement chemical reactions in a + multicomponent transport model. All of the native PhreeqcRM methods + (non BMI methods) provide are available, which provides a complete + interface to PhreeqcRM. + @retval The string "BMI PhreeqcRM". + @par C++ Example: + @htmlonly + +
+    std::string comp_name = brm.GetComponentName();
+    
+
+ @endhtmlonly + @par MPI: + Called by root. + */ + std::string GetComponentName() override {return "BMI PhreeqcRM";}; + + /** + @ref GetInputVarNames returns the count of input variables that can + be set with @ref SetValue. + @retval Count of input variables that can be set with @ref SetValue. + @see + @ref GetInputVarNames, + @ref GetVarItemsize, + @ref GetVarNbytes, + @ref GetVarType, + @ref GetVarUnits, + @ref SetValue. + @par C++ Example: + @htmlonly + +
+    int count = brm.GetInputItemCount();
+    std::vector< std::string > InputVarNames = brm.GetInputVarNames();
+    oss << "SetValue variables:\n";
+    for (size_t i = 0; i < count; i++)
+    {
+        oss << "  " << i << "  " << InputVarNames[i] << "\n";
+        oss << "     Type:        " << brm.GetVarType(InputVarNames[i]) << "\n";
+        oss << "     Units:       " << brm.GetVarUnits(InputVarNames[i]) << "\n";
+        oss << "     Total bytes: " << brm.GetVarNbytes(InputVarNames[i]) << "\n";
+        oss << "     Item bytes:  " << brm.GetVarItemsize(InputVarNames[i]) << "\n";
+        oss << "     Dim:         " << brm.GetVarNbytes(InputVarNames[i]) /
+               brm.GetVarItemsize(InputVarNames[i]) << "\n";
+    }
+    
+
+ @endhtmlonly + @par MPI: + Called by root. + */ + int GetInputItemCount() override; + + /** + @ref GetOutputItemCount returns the count of output variables that can + be retrieved with @ref GetValue. + @retval Count of output variables that can be retrieved with @ref GetValue. + + @see + @ref GetOutputVarNames, + @ref GetValue, + @ref GetVarItemsize, + @ref GetVarNbytes, + @ref GetVarType, + @ref GetVarUnits. + @par C++ Example: + @htmlonly + +
+    int count = brm.GetOutputItemCount();
+    std::vector< std::string > OutputVarNames = brm.GetOutputVarNames();
+    oss << "GetValue variables:\n";
+    for (size_t i = 0; i < count; i++)
+    {
+        oss << "  " << i << "  " << OutputVarNames[i] << "\n";
+        oss << "     Type:        " << brm.GetVarType(OutputVarNames[i]) << "\n";
+        oss << "     Units:       " << brm.GetVarUnits(OutputVarNames[i]) << "\n";
+        oss << "     Total bytes: " << brm.GetVarNbytes(OutputVarNames[i]) << "\n";
+        oss << "     Item bytes:  " << brm.GetVarItemsize(OutputVarNames[i]) << "\n";
+        oss << "     Dim:         " << brm.GetVarNbytes(OutputVarNames[i]) /
+               brm.GetVarItemsize(OutputVarNames[i]) << "\n";
+    }
+    
+
+ @endhtmlonly + @par MPI: + Called by root. + */ + int GetOutputItemCount() override; + /** + @ref GetPointableItemCount returns the count of output variables for which + pointers can be obtained with @ref GetValuePtr. The pointers point to + current copies of the variables. Setting a value with one of the pointers + will have no effect on the simulation but will corrupt the copy of the variable. + @retval Count of pointers to variables that can be retrieved with + @ref GetValuePtr. + + @see + @ref GetPointableVarNames, + @ref GetValue, + @ref GetVarItemsize, + @ref GetVarNbytes, + @ref GetVarType, + @ref GetVarUnits. + @par C++ Example: + @htmlonly + +
+    int count = brm.GetPointableItemCount();
+    std::vector< std::string > OutputVarNames = brm.GetPointableVarNames();
+    oss << "GetValuePtr variables:\n";
+    for (size_t i = 0; i < count; i++)
+    {
+        oss << "  " << i << "  " << PointableVarNames[i] << "\n";
+        oss << "     Type:        " << brm.GetVarType(PointableVarNames[i]) << "\n";
+        oss << "     Units:       " << brm.GetVarUnits(PointableVarNames[i]) << "\n";
+        oss << "     Total bytes: " << brm.GetVarNbytes(PointableVarNames[i]) << "\n";
+        oss << "     Item bytes:  " << brm.GetVarItemsize(PointableVarNames[i]) << "\n";
+        oss << "     Dim:         " << brm.GetVarNbytes(PointableVarNames[i]) /
+               brm.GetVarItemsize(PointableVarNames[i]) << "\n";
+    }
+    
+
+ @endhtmlonly + @par MPI: + Called by root. + */ + int GetPointableItemCount(); + + /** + @ref GetInputVarNames returns a list of the variable names that can be + set with @ref SetValue. + @retval A std::vector of the names of variables that can be set with + @ref SetValue. + + @see + @ref GetInputItemCount, + @ref GetVarItemsize, + @ref GetVarNbytes, + @ref GetVarType, + @ref GetVarUnits, + @ref SetValue. + @par C++ Example: + @htmlonly + +
+    std::vector< std::string > InputVarNames = brm.GetInputVarNames();
+    int count = brm.GetInputItemCount();
+    oss << "SetValue variables:\n";
+    for (size_t i = 0; i < count; i++)
+    {
+        oss << "  " << i << "  " << InputVarNames[i] << "\n";
+        oss << "     Type:        " << brm.GetVarType(InputVarNames[i]) << "\n";
+        oss << "     Units:       " << brm.GetVarUnits(InputVarNames[i]) << "\n";
+        oss << "     Total bytes: " << brm.GetVarNbytes(InputVarNames[i]) << "\n";
+        oss << "     Item bytes:  " << brm.GetVarItemsize(InputVarNames[i]) << "\n";
+        oss << "     Dim:         " << brm.GetVarNbytes(InputVarNames[i]) /
+               brm.GetVarItemsize(InputVarNames[i]) << "\n";
+    }
+    
+
+ @endhtmlonly + @par MPI: + Called by root. + */ + std::vector GetInputVarNames() override; + + /** + @ref GetOutputVarNames returns a list of the variable names that can + be retrieved with @ref GetValue. + @retval A list of the names of variable that can be retrieved with + @ref GetValue. + + @see + @ref GetOutputItemCount, + @ref GetValue, + @ref GetVarItemsize, + @ref GetVarNbytes, + @ref GetVarType, + @ref GetVarUnits. + @par C++ Example: + @htmlonly + +
+    std::vector< std::string > OutputVarNames = brm.GetOutputVarNames();
+    int count = brm.GetOutputItemCount();
+    oss << "GetValue variables:\n";
+    for (size_t i = 0; i < count; i++)
+    {
+        oss << "  " << i << "  " << OutputVarNames[i] << "\n";
+        oss << "     Type:        " << brm.GetVarType(OutputVarNames[i]) << "\n";
+        oss << "     Units:       " << brm.GetVarUnits(OutputVarNames[i]) << "\n";
+        oss << "     Total bytes: " << brm.GetVarNbytes(OutputVarNames[i]) << "\n";
+        oss << "     Item bytes:  " << brm.GetVarItemsize(OutputVarNames[i]) << "\n";
+        oss << "     Dim:         " << brm.GetVarNbytes(OutputVarNames[i]) /
+               brm.GetVarItemsize(OutputVarNames[i]) << "\n";
+    }
+    
+
+ @endhtmlonly + @par MPI: + Called by root. + */ + std::vector GetOutputVarNames() override; + + /** + @ref GetPointableVarNames returns a list of the names of variables + for which pointers can be retrieved with @ref GetValuePt. + @retval A list of the names of variables for which pointers can + be retieved with @ref GetValuePtr. + + @see + @ref GetPointableItemCount, + @ref GetValue, + @ref GetVarItemsize, + @ref GetVarNbytes, + @ref GetVarType, + @ref GetVarUnits. + @par C++ Example: + @htmlonly + +
+    std::vector< std::string > PointableVarNames = brm.GetPointableVarNames();
+    int count = brm.GetOutputItemCount();
+    oss << "GetValuePtr variables:\n";
+    for (size_t i = 0; i < count; i++)
+    {
+        oss << "  " << i << "  " << PointableVarNames[i] << "\n";
+        oss << "     Type:        " << brm.GetVarType(PointableVarNames[i]) << "\n";
+        oss << "     Units:       " << brm.GetVarUnits(PointableVarNames[i]) << "\n";
+        oss << "     Total bytes: " << brm.GetVarNbytes(PointableVarNames[i]) << "\n";
+        oss << "     Item bytes:  " << brm.GetVarItemsize(PointableVarNames[i]) << "\n";
+        oss << "     Dim:         " << brm.GetVarNbytes(PointableVarNames[i]) /
+               brm.GetVarItemsize(PointableVarNames[i]) << "\n";
+    }
+    
+
+ @endhtmlonly + @par MPI: + Called by root. + */ + std::vector GetPointableVarNames(); + + // Variable information functions + /** + @ref GetVarGrid returns a value of 1, indicating points. + BMIPhreeqcRM does not have a grid of its own. The cells + of BMIPhreeqcRM are associated with the user's model grid, + and all spatial characterists are assigned by the user's + model. + @retval 1 BMIPhreeqcRM cells derive meaning from the user's + model. + */ + int GetVarGrid(const std::string name) override {return 1;} + + /** + Basic Model Interface method that retrieves the type of a variable that + can be set with @ref SetValue or retrieved with @ref GetValue. Types are + "int", "double", "std::string", or "std::vector". + + @param name Name of the variable to retrieve type. + @retval Character string of variable type. + + @see + @ref GetVarNbytes, + @ref GetVarItemsize, + @ref GetVarUnits. + @par C++ Example: + @htmlonly + +
+    std::vector< std::string > OutputVarNames = brm.GetOutputVarNames();
+    int count = brm.GetOutputItemCount();
+    oss << "GetValue variables:\n";
+    for (size_t i = 0; i < count; i++)
+    {
+        oss << "  " << i << "  " << OutputVarNames[i] << "\n";
+        oss << "     Type:        " << brm.GetVarType(OutputVarNames[i]) << "\n";
+        oss << "     Units:       " << brm.GetVarUnits(OutputVarNames[i]) << "\n";
+        oss << "     Total bytes: " << brm.GetVarNbytes(OutputVarNames[i]) << "\n";
+        oss << "     Item bytes:  " << brm.GetVarItemsize(OutputVarNames[i]) << "\n";
+        oss << "     Dim:         " << brm.GetVarNbytes(OutputVarNames[i]) /
+               brm.GetVarItemsize(OutputVarNames[i]) << "\n";
+    }
+    
+
+ @endhtmlonly + @par MPI: + Called by root. + */ + std::string GetVarType(const std::string name) override; + /** + @ref GetVarUnits retrieves the units of a variable + that can be set with @ref SetValue, retrieved with @ref GetValue, + or pointed to by @ref GetValuePtr. + @param name Name of the variable to retrieve type. + @retval Character string of units for variable. + + @see + @ref GetVarNbytes, + @ref GetVarItemsize, + @ref GetVarType. + @par C++ Example: + @htmlonly + +
+    std::vector< std::string > OutputVarNames = brm.GetOutputVarNames();
+    int count = brm.GetOutputItemCount();
+    oss << "GetValue variables:\n";
+    for (size_t i = 0; i < count; i++)
+    {
+        oss << "  " << i << "  " << OutputVarNames[i] << "\n";
+        oss << "     Type:        " << brm.GetVarType(OutputVarNames[i]) << "\n";
+        oss << "     Units:       " << brm.GetVarUnits(OutputVarNames[i]) << "\n";
+        oss << "     Total bytes: " << brm.GetVarNbytes(OutputVarNames[i]) << "\n";
+        oss << "     Item bytes:  " << brm.GetVarItemsize(OutputVarNames[i]) << "\n";
+        oss << "     Dim:         " << brm.GetVarNbytes(OutputVarNames[i]) /
+               brm.GetVarItemsize(OutputVarNames[i]) << "\n";
+    }
+    
+
+ @endhtmlonly + @par MPI: + Called by root. + */ + std::string GetVarUnits(const std::string name) override; + + /** + @ref GetVarItemsize retrieves size of an individual item that + can be set or retrived. Sizes may be sizeof(int), sizeof(double), + or a character length for string variables. + @param name Name of the variable to retrieve size. + @retval Size of one element of the variable. + + @see + @ref GetVarNbytes, + @ref GetVarType, + @ref GetVarUnits. + @par C++ Example: + @htmlonly + +
+    std::vector< std::string > OutputVarNames = brm.GetOutputVarNames();
+    int count = brm.GetOutputItemCount();
+    oss << "GetValue variables:\n";
+    for (size_t i = 0; i < count; i++)
+    {
+        oss << "  " << i << "  " << OutputVarNames[i] << "\n";
+        oss << "     Type:        " << brm.GetVarType(OutputVarNames[i]) << "\n";
+        oss << "     Units:       " << brm.GetVarUnits(OutputVarNames[i]) << "\n";
+        oss << "     Total bytes: " << brm.GetVarNbytes(OutputVarNames[i]) << "\n";
+        oss << "     Item bytes:  " << brm.GetVarItemsize(OutputVarNames[i]) << "\n";
+        oss << "     Dim:         " << brm.GetVarNbytes(OutputVarNames[i]) /
+               brm.GetVarItemsize(OutputVarNames[i]) << "\n";
+    }
+    
+
+ @endhtmlonly + @par MPI: + Called by root. + */ + int GetVarItemsize(const std::string name) override; + + /** + @ref GetVarNbytes retrieves the total number of bytes that are + set for a variable with @ref SetValue or retrieved for a variable with + @ref GetValue. + @param name Name of the variable to retrieve total bytes. + @retval Total number of bytes set or retrieved for variable. + @see + @ref GetVarItemsize, + @ref GetVarType, + @ref GetVarUnits. + . + @par C++ Example: + @htmlonly + +
+        std::vector< std::string > OutputVarNames = brm.GetOutputVarNames();
+    int count = brm.GetOutputItemCount();
+    oss << "GetValue variables:\n";
+    for (size_t i = 0; i < count; i++)
+    {
+        oss << "  " << i << "  " << OutputVarNames[i] << "\n";
+        oss << "     Type:        " << brm.GetVarType(OutputVarNames[i]) << "\n";
+        oss << "     Units:       " << brm.GetVarUnits(OutputVarNames[i]) << "\n";
+        oss << "     Total bytes: " << brm.GetVarNbytes(OutputVarNames[i]) << "\n";
+        oss << "     Item bytes:  " << brm.GetVarItemsize(OutputVarNames[i]) << "\n";
+        oss << "     Dim:         " << brm.GetVarNbytes(OutputVarNames[i]) /
+            brm.GetVarItemsize(OutputVarNames[i]) << "\n";
+    }
+    
+
+ @endhtmlonly + @par MPI : + Called by root. + */ + int GetVarNbytes(const std::string name) override; + + /** + @ref GetVarLocation has no explicit meaning in BMIPhreeqcRM. All + grid-related information derives from the user's model. + @param name Name of the variable to retrieve total bytes. + @retval The string "Unknown" is returned. + */ + std::string GetVarLocation(const std::string name) override { return "Unknown"; } + + // Time functions + + /** + @ref GetCurrentTime returns the current simulation time, in seconds. + (Same as @ref GetTime.) + @retval The current simulation time, in seconds. + @see + @ref GetEndTime, + @ref GetTimeStep, + @ref SetValue, + @ref GetTime, + @ref GetTimeStep, + @ref SetTime, + @ref SetTimeStep. + @par C++ Example: + @htmlonly + +
+    std::cout << "Current time: "
+         << GetCurrentTime()
+         << " seconds\n";
+    
+
+ @endhtmlonly + @par MPI: + Called by root. + */ + double GetCurrentTime() override; + + /** + @ref GetStartTime returns the current simulation time, in seconds. + (Same as @ref GetCurrentTime or @ref GetTime.) + @retval The current simulation time, in seconds. + */ + double GetStartTime() override; + + /** + @ref GetEndTime returns @ref GetCurrentTime plus @ref GetTimeStep, in seconds. + @retval The end of the time step, in seconds. + @see + @ref GetCurrentTime, + @ref GetTimeStep, + @ref SetValue, + @ref GetTime, + @ref GetTimeStep, + @ref SetTime, + @ref SetTimeStep. + @par C++ Example: + @htmlonly + +
+    std::cout << "End of time step "
+         << GetEndTime()
+         << " seconds\n";
+    
+
+ @endhtmlonly + @par MPI: + Called by root. + */ + double GetEndTime() override; + + /** + @ref GetTimeUnits returns the time units of PhreeqcRM. + All time units are seconds. + @retval Returns the string "seconds". + @see + @ref GetCurrentTime, + @ref GetEndTime, + @ref GetTimeStep, + @ref SetValue, + @ref GetTime, + @ref GetTimeStep, + @ref SetTime, + @ref SetTimeStep. + @par C++ Example: + @htmlonly + +
+    std::cout << "BMIPhreeqcRM time units are "
+         << GetTimeUnits() << ".\n";
+    
+
+ @endhtmlonly + @par MPI: + Called by root. + */ + std::string GetTimeUnits() override { return "seconds"; }; + double GetTimeStep() override + { + return PhreeqcRM::GetTimeStep(); + }; + + // Variable getters + /** + @ref GetValue retrieves model variables. Only variables in the list + provided by @ref GetOutputVarNames can be retrieved. + + @param name Name of the variable to retrieve. + @param dest Variable in which to place results. The @a dest variable + can be of different types depending on the variable retrieved. The + following list gives the name in the first argument and the + corresponding data type of the @a dest argument: + + @n "ComponentCount", @a dest: int; + @n "Components", @a dest: std::vector< std::string >; + @n "Concentrations", @a dest: std::vector< double >; + @n "CurrentSelectedOutputUserNumber", @a dest: int; + @n "Density", @a dest: std::vector< double >; + @n "ErrorString", @a dest: std::string; + @n "FilePrefix", @a dest: std::string; + @n "Gfw", @a dest: std::vector< double >; + @n "GridCellCount", @a dest: int; + @n "Porosity", @a dest: std::vector< double >; + @n "Pressure", @a dest: std::vector< double >; + @n "Saturation", @a dest: std::vector< double >; + @n "SelectedOutput", @a dest: std::vector< double >; + @n "SelectedOutputColumnCount", @a dest: int; + @n "SelectedOutputCount", @a dest: int; + @n "SelectedOutputHeadings", @a dest: std::vector< std::string >; + @n "SelectedOutputOn", @a dest: bool; + @n "SelectedOutputRowCount", @a dest: int; + @n "SolutionVolume", @a dest: std::vector< double >; + @n "Temperature", @a dest: std::vector< double >; + @n "Time", @a dest: double; + @n "TimeStep", @a dest: double, + @n "Viscosity", @a dest: std::vector< double >. + + @see + @ref GetOutputVarNames, + @ref GetOutputItemCount, + @ref GetValuePtr; + @ref GetVarItemsize, + @ref GetVarNbytes, + @ref GetVarType, + @ref GetVarUnits. + @par C++ Example: + @htmlonly + +
+        std::vector< double > density;
+        phreeqc_rm.GetValue("Density", density);
+        std::vector< std::string > comps;
+        phreeqc_rm.GetValue("Components", comps);
+    
+
+ @endhtmlonly + @par MPI: + Called by root, workers must be in the loop of @ref MpiWorker. + */ + void GetValue(const std::string name, void* dest) override; + /*! + * \overload void GetValue(std::string name, bool& dest); + */ + void GetValue(const std::string name, bool& dest); + /*! + * \overload void GetValue(std::string name, bool* dest); + */ + void GetValue(const std::string name, bool* dest); + /*! + * \overload void GetValue(std::string name, double& dest); + */ + void GetValue(const std::string name, double& dest); + /*! + * \overload void GetValue(std::string name, double* dest); + */ + void GetValue(const std::string name, double* dest); + /*! + * \overload void GetValue(std::string name, int& dest); + */ + void GetValue(const std::string name, int& dest); + /*! + * \overload void GetValue(std::string name, int* dest); + */ + void GetValue(const std::string name, int* dest); + /*! + * \overload void GetValue(std::string name, std::string& dest); + */ + void GetValue(const std::string name, std::string& dest); + /*! + * \overload void GetValue(std::string name, std::vector& dest); + */ + void GetValue(const std::string name, std::vector& dest); + /*! + * \overload void GetValue(std::string name, std::vector& dest); + */ + void GetValue(const std::string name, std::vector& dest); + /*! + * \overload void GetValue(std::string name, std::vector& dest); + */ + void GetValue(const std::string name, std::vector& dest); + /** + @ref GetValuePtr takes a variable name and returns a + reference to a variable. Unlike the buffer returned from @ref GetValue, + the reference always points to the current values of the variable, + even if the model's state has changed. + @param name Name of the variable to retrieve. + @retval Void pointer to data. + */ + void* GetValuePtr(std::string name) override; + /** + @ref GetValueAtIndices is not implemented + */ + void GetValueAtIndices(std::string name, void* dest, int* inds, int count) override + { + throw NotImplemented(); + }; + + // Variable setters + /** + @ref SetValue sets model variables. Only variables in the list + provided by @ref GetInputVarNames can be set. + @param name Name of the variable to retrieve. + @param src Data used to set the variable. The @a src data type + can vary depending on the variable retrieved. The + following list gives the name in the first argument and the + corresponding data type and size of the @a src argument: + + "Concentrations", std::vector, [GridCellCount*ComponentCount]; + "Density", std::vector, [GridCellCount]; + "FilePrefix", std::string; + "NthSelectedOutput", int; + "Porosity", std::vector, [GridCellCount]; + "Pressure", std::vector, [GridCellCount]; + "Saturation", std::vector, [GridCellCount]; + "SelectedOutputOn", bool; + "Temperature", std::vector, [GridCellCount]; + "Time", double; + "TimeStep", double; + + @see + @ref GetInputVarNames, + @ref GetInputItemCount,, + @ref GetValue, + @ref GetVarItemsize, + @ref GetVarNbytes, + @ref GetVarType, + @ref GetVarUnits. + @par C++ Example: + @htmlonly + +
+    std::vector< double > temperature(ngrid, 28.0);
+    phreeqc_rm.SetValue("Temperature", temperature);
+    
+
+ @endhtmlonly + @par MPI: + Called by root, workers must be in the loop of @ref MpiWorker. + */ + void SetValue(std::string name, void* src) override; + /*! + * \overload void SetValue(std::string name, bool src); + */ + void SetValue(std::string name, bool src); + /*! + * \overload void SetValue(std::string name, char* src); + */ + void SetValue(std::string name, char* src); + /*! + * \overload void SetValue(std::string name, double src); + */ + void SetValue(std::string name, double src); + /*! + * \overload void SetValue(std::string name, int src); + */ + void SetValue(std::string name, int src); + /*! + * \overload void SetValue(std::string name, std::string src); + */ + void SetValue(std::string name, std::string src); + /*! + * \overload void SetValue(std::string name, std::vector src); + */ + void SetValue(std::string name, std::vector src); + /*! + * \overload void SetValue(std::string name, std::vector src); + */ + void SetValue(std::string name, std::vector src); + /*! + * \overload void SetValue(std::string name, std::vector src); + */ + void SetValue(std::string name, std::vector src); + /** + @ref SetValueAtIndices is not implemented. + */ + void SetValueAtIndices(std::string name, int* inds, int count, void* src) override + { + throw NotImplemented(); + }; + // Grid information functions + /** + @ref GetGridRank returns a rank of 1 for grid 0. + BMIPhreeqcRM only has a 1D series of + cells; any grid or spatial information must + be found in the user's model. + @param grid Grid number, only grid 0 is considered. + @retval Rank of 1 is returned for grid 0; 0 for + all other values of @a grid. + */ + int GetGridRank(const int grid) override; + /** + @ref GetGridSize returns the number of cells specified + at creation of the BMIPhreeqcRM instance. + @param grid Grid number, only grid 0 is considered. + @retval Same value as GetGridCellCount is returned for grid 0; + 0 for all other values of @a grid. + */ + int GetGridSize(const int grid) override; + /** + @ref GetGridType is considered to be points. No grid + information is available in BMIPhreeqcRM; all grid + information must be found in the user's model. + @param grid Grid number, only grid 0 is considered. + @retval "Points" is returned for grid 0; + "Undefined grid identifier" is returned for all other + values of @a grid. + */ + std::string GetGridType(const int grid) override; + /** + @ref GetGridShape is not implemented. + */ + void GetGridShape(const int grid, int* shape) override + { + throw NotImplemented(); + } + /** + @ref GetGridSpacing is not implemented. + */ + void GetGridSpacing(const int grid, double* spacing) override + { + throw NotImplemented(); + } + /** + @ref GetGridOrigin is not implemented. + */ + void GetGridOrigin(const int grid, double* origin) override + { + throw NotImplemented(); + } + /** + @ref GetGridX is not implemented. + */ + void GetGridX(const int grid, double* x) override + { + throw NotImplemented(); + } + /** + @ref GetGridY is not implemented. + */ + void GetGridY(const int grid, double* y) override + { + throw NotImplemented(); + } + /** + @ref GetGridZ is not implemented. + */ + void GetGridZ(const int grid, double* z) override + { + throw NotImplemented(); + } + /** + @ref GetGridNodeCount is not implemented. + */ + int GetGridNodeCount(const int grid) override + { + throw NotImplemented(); + } + /** + @ref GetGridEdgeCount is not implemented. + */ + int GetGridEdgeCount(const int grid) override + { + throw NotImplemented(); + } + /** + @ref GetGridFaceCount is not implemented. + */ + int GetGridFaceCount(const int grid) override + { + throw NotImplemented(); + } + /** + @ref GetGridEdgeNodes is not implemented. + */ + void GetGridEdgeNodes(const int grid, int* edge_nodes) override + { + throw NotImplemented(); + } + /** + @ref GetGridFaceEdges is not implemented. + */ + void GetGridFaceEdges(const int grid, int* face_edges) override + { + throw NotImplemented(); + } + /** + @ref GetGridFaceNodes is not implemented. + */ + void GetGridFaceNodes(const int grid, int* face_nodes) override + { + throw NotImplemented(); + } + /** + @ref GetGridNodesPerFace is not implemented. + */ + void GetGridNodesPerFace(const int grid, int* nodes_per_face) override + { + throw NotImplemented(); + } + // data + std::string language; + // typedef void (*VarFunction)(BMIPhreeqcRM* brm_ptr); // function pointer type + // typedef std::map VarFunction_map; + // VarFunction_map varfn_map; + // VarFunction GetFn(const std::string name); + // std::set UpdateMap; + // std::set& GetUpdateMap() { return UpdateMap; } + +private: + //friend class RM_interface; + static std::map Instances; + static size_t InstancesIndex; + void UpdateVariables(); +}; +#endif //BMIPHREEQCRM_H_INCLUDED diff --git a/src/BMI_Var.cpp b/src/BMI_Var.cpp new file mode 100644 index 000000000..307b34e56 --- /dev/null +++ b/src/BMI_Var.cpp @@ -0,0 +1,66 @@ +#include "BMI_Var.h" +BMIVariant::BMIVariant(VarFunction f, std::string name_in) +{ + Initialized = false; + this->name = name_in; + HasSetter = false; + HasGetter = false; + HasPtr = false; + Nbytes = 0; + Itemsize = 0; + dim = 0; + b_var = false; + i_var = 0; + d_var = 0.0; + NotImplemented = false; + VoidPtr = NULL; + fn = f; +} +void BMIVariant::CopyScalars(BMIVariant& bv) +{ + this->Initialized = bv.Initialized; + this->HasSetter = bv.HasSetter; + this->HasGetter = bv.HasGetter; + this->HasPtr = bv.HasPtr; + this->Nbytes = bv.Nbytes; + this->Itemsize = bv.Itemsize; + this->dim = bv.dim; + this->b_var = bv.b_var; + this->i_var = bv.i_var; + this->d_var = bv.d_var; + this->NotImplemented = bv.NotImplemented; + this->VoidPtr = bv.VoidPtr; + this->fn = bv.fn; + this->NotImplemented = bv.NotImplemented; + this->ctype = bv.ctype; + this->ftype = bv.ftype; + this->ptype = bv.ptype; +} +void BMIVariant::Clear() +{ + + Initialized = false; + this->name.clear(); + this->type.clear(); + this->units.clear(); + HasSetter = false; + HasGetter = false; + HasPtr = false; + Nbytes = 0; + Itemsize = 0; + dim = 0; + ctype.clear(); + ftype.clear(); + ptype.clear(); + b_var = false; + i_var = 0; + d_var = 0.0; + string_var.clear(); + IntVector.clear(); + DoubleVector.clear(); + StringVector.clear(); + NotImplemented = false; + VoidPtr = NULL; + fn = NULL; + CharVector.clear(); +} \ No newline at end of file diff --git a/src/BMI_Var.h b/src/BMI_Var.h index 26b55345c..8844f6e46 100644 --- a/src/BMI_Var.h +++ b/src/BMI_Var.h @@ -1,12 +1,157 @@ +#if !defined(BMI_VAR_H_INCLUDED) +#define BMI_VAR_H_INCLUDED #include #include #include +#include +#include +#include +//#include "VarManager.h" #if defined(_WINDLL) #define IRM_DLL_EXPORT __declspec(dllexport) #else #define IRM_DLL_EXPORT #endif +class VarManager; +class PhreeqcRM; +class IRM_DLL_EXPORT BMIVariant +{ + //typedef void (VarManager::*VarFunction)(PhreeqcRM* rm_ptr); // function pointer type + typedef void (VarManager::* VarFunction)(); +private: + bool Initialized; + std::string name; + std::string type; + std::string units; + bool HasSetter; + bool HasGetter; + bool HasPtr; + int Nbytes; + int Itemsize; + int dim; + std::string ctype; + std::string ftype; + std::string ptype; + bool b_var; + int i_var; + double d_var; + std::string string_var; + std::vector IntVector; + std::vector DoubleVector; + std::vector StringVector; + bool NotImplemented; + void* VoidPtr; + std::vector CharVector; + VarFunction fn; +public: + // methods + BMIVariant(VarFunction f, std::string name); + BMIVariant() + { + Initialized = false; + HasSetter = false; + HasGetter = false; + HasPtr = false; + Nbytes = 0; + Itemsize = 0; + dim = 0; + b_var = false; + i_var = 0; + d_var = 0.0; + NotImplemented = false; + VoidPtr = NULL; + fn = NULL; + } + void Clear(); + void SetBasic(std::string units_in, + bool set_in, bool get_in, bool has_ptr_in, int nbytes, int itemsize) + {; + //d_var = 0.0 + //this->name = name_in; + this->units = units_in; + this->HasSetter = set_in; + this->HasGetter = get_in; + this->HasPtr = has_ptr_in; + this->Nbytes = nbytes; + this->Itemsize = itemsize; + if (itemsize != 0) dim = nbytes / itemsize; + //Nbytes = 0; + //Itemsize = 0; + //dim = 0; + //b_var = false; + //i_var = 0; + //NotImplemented = false; + //VoidPtr = NULL; + }; + void SetSizes(int nbytes, int itemsize) + { + this->Nbytes = nbytes; + this->Itemsize = itemsize; + if (itemsize != 0) dim = nbytes / itemsize; + } + void SetTypes(std::string c, std::string f, std::string p) + { + this->ctype = c; this->ftype = f; this->ptype = p; + } + void SetItemsize(int v) { this->Itemsize = v; } + void SetInitialized(bool v) { Initialized = v; } + void SetBVar(bool v) { b_var = v; } + void SetDVar(double v) { d_var = v; } + void SetIVar(int v) { i_var = v; } + void SetStringVar(std::string v) { string_var = v; } + void SetDoubleVector(const std::vector &v) { + assert(v.size() == DoubleVector.size()); + memcpy(DoubleVector.data(), v.data(), v.size() * sizeof(double)); + } + void SetIntVector(const std::vector &v) { + assert(v.size() == IntVector.size()); + memcpy(DoubleVector.data(), v.data(), v.size() * sizeof(int)); + } + void SetCType(std::string v) { this->ctype = v; } + void SetFType(std::string v) { this->ftype = v; } + void SetPType(std::string v) { this->ptype = v; } + void SetName(std::string s) { this->name = s; } + void SetNotImplemented(bool v) { this->NotImplemented = v; } + void SetVoidPtr(void* v) { this->VoidPtr = v; } + void SetCharVector(std::vector v) { this->CharVector = v; } + void SetFn(VarFunction f) { this->fn = f; } // function pointer type + void SetStringVector(const std::vector& v) { this->StringVector = v; } + + std::string GetName() { return this->name; } + std::string GetUnits() { return this->units; } + bool GetHasGetter(void) { return this->HasGetter; } + bool GetHasSetter(void) { return this->HasSetter; } + bool GetHasPtr(void) { return this->HasPtr; } + bool GetInitialized(void) { return this->Initialized; } + bool* GetBVarPtr() { return &this->b_var; } + bool GetBVar() { return this->b_var; } + double* GetDVarPtr() { return &this->d_var; } + double GetDVar() { return this->d_var; } + int* GetIVarPtr() { return &this->i_var; } + int GetIVar() { return this->i_var; } + std::string GetStringVar() { return this->string_var; } + int GetNbytes(void) { return this->Nbytes; } + int GetItemsize(void) { return this->Itemsize; } + std::string& GetCType() { return this->ctype; };; + std::string& GetFType() { return this->ftype; }; + std::string& GetPType() { return this->ptype; }; + double* GetDoubleVectorPtr() { return this->DoubleVector.data(); } + int* GetIntVectorPtr() { return this->IntVector.data(); } + std::vector& GetDoubleVectorRef() { return this->DoubleVector; } + std::vector& GetIntVectorRef() { return this->IntVector; } + std::vector& GetStringVectorRef() { return this->StringVector; } + std::string& GetStringRef() { return this->string_var; } + int GetDim() { return dim; } + void* GetVoidPtr() { return this->VoidPtr; } + std::vector GetCharVector() { return this->CharVector; } + VarFunction GetFn() { + //((VarFunction*)fn)(rm_ptr); + return this->fn; + } + bool& GetNotImplementedRef() { return this->NotImplemented; } + void CopyScalars(BMIVariant& bv); +}; class IRM_DLL_EXPORT BMI_Var { @@ -16,29 +161,73 @@ class IRM_DLL_EXPORT BMI_Var std::string units; bool set; bool get; + bool has_ptr; + int Nbytes; + int Itemsize; + int dim; + std::string ctype; + std::string ftype; + std::string ptype; public: // methods BMI_Var() { this->set = false; this->get = false; + this->has_ptr = false; + this->Nbytes = 0; + this->Itemsize = 0; + this->dim = 0; } - BMI_Var(std::string name_in, std::string type_in, std::string units_in, - bool set_in, bool get_in) + BMI_Var(std::string name_in, std::string units_in, + bool set_in, bool get_in, bool has_ptr_in) + { + this->name = name_in; + this->set = set_in; + this->get = get_in; + this->has_ptr = has_ptr_in; + this->Nbytes = 0; + this->Itemsize = 0; + this->dim = 0; + }; + BMI_Var(std::string name_in, std::string units_in, + bool set_in, bool get_in, bool has_ptr_in, int Nbytes_in, int Itemsize_in) { this->name = name_in; - this->type = type_in; this->units = units_in; this->set = set_in; this->get = get_in; + this->has_ptr = has_ptr_in; + this->Nbytes = Nbytes_in; + this->Itemsize = Itemsize_in; + this->dim = 0; + if (Itemsize != 0) dim = Nbytes / Itemsize; }; - std::string GetName() { return this->name; } - std::string GetType() { return this->type; }; + void SetName(std::string s) { this->name = s; } std::string GetUnits() { return this->units; } - void SetUnits(std::string units_in) { this->units = units_in; }; - bool GetSet(void) { return this->set; }; - void SetSet(bool in_in) { this->set = in_in; }; - bool GetGet(void) { return this->get; }; - void SetGet(bool out_in) { this->get = out_in; }; + void SetUnits(std::string units_in) { this->units = units_in; } + bool GetSet(void) { return this->set; } + void SetSet(bool in_in) { this->set = in_in; } + bool GetGet(void) { return this->get; } + void SetGet(bool out_in) { this->get = out_in; } + bool GetHasPtr(void) { return this->has_ptr; } + void SetHasPtr(bool tf) { this->has_ptr = tf; } + int GetNbytes(void) { return this->Nbytes; } + void SetNbytes(int n) { this->Nbytes = n; } + int GetItemsize(void) { return this->Itemsize; } + void SetItemsize(int n) { this->Itemsize = n; } + std::string GetCType() { return this->ctype; }; + void SetCType(std::string s) { this->ctype = s; }; + std::string GetFType() { return this->ftype; }; + void SetFType(std::string s) { this->ftype = s; }; + std::string GetPType() { return this->ptype; }; + void SetPType(std::string s) { this->ptype = s; }; + void SetTypes(std::string c, std::string f, std::string p) + { + this->ctype = c; this->ftype = f; this->ptype = p; + } + int GetDim() { return dim; } + }; +#endif // BMI_VAR_H_INCLUDED \ No newline at end of file diff --git a/src/BMI_interface.F90 b/src/BMI_interface.F90 new file mode 100644 index 000000000..bbf251ed9 --- /dev/null +++ b/src/BMI_interface.F90 @@ -0,0 +1,2108 @@ + !*MODULE BMIPhreeqcRM PHREEQC Reaction Module for Transport Codes + !> @brief Fortran Documentation for the geochemical reaction module PhreeqcRM. + !> @par "" + !> "USE PhreeqcRM" is included in Fortran source code to define the PhreeqcRM functions. + !> For Windows, define the module by including the file RM_interface.F90 in your project. + !> For Linux, configure, compile, and install the PhreeqcRM library and module file. + !> You will need installed include directory (-I) added to the project) to reference the module file. + !> You will need to link to the library to produce the executable for your code. + !> + MODULE BMIPhreeqcRM + USE PhreeqcRM + IMPLICIT NONE + PRIVATE :: Lower + PRIVATE :: success + + integer, parameter :: BMI_MAX_COMPONENT_NAME = 2048 + integer, parameter :: BMI_MAX_VAR_NAME = 2048 + integer, parameter :: BMI_MAX_TYPE_NAME = 2048 + integer, parameter :: BMI_MAX_UNITS_NAME = 2048 + + integer, parameter :: BMI_FAILURE = 1 + integer, parameter :: BMI_SUCCESS = 0 + + + !> INTERFACE-----Basic Model Interface method that retrieves model variables. Only variables in the list + !> provided by @ref bmif_get_output_var_names can be retrieved. The BMI interface to PhreeqcRM is + !> only partial, and provides only the most basic functions. The native PhreeqcRM methods (those without the the RM_BMI_ + !> prefix) provide a complete interface. + !> @param id The instance @a id returned from @ref RM_Create. + !> @param var Name of the variable to retrieve. + !> @param dest Variable in which to place results. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> + !> Variable names for the second argument (@a name) and variable type of the + !> third argument (@a dest). + !> @n "ComponentCount", @a dest: integer; + !> @n "Components", @a dest: character(len=:), allocatable, dimension(:); + !> @n "Concentrations", @a dest: real(kind=8), allocatable, dimension(:,:); + !> @n "CurrentSelectedOutputUserNumber", @a dest: integer; + !> @n "Density", @a dest: real(kind=8), allocatable, dimension(:); + !> @n "ErrorString", @a dest: character; + !> @n "FilePrefix", @a dest: character; + !> @n "Gfw", @a dest: real(kind=8), allocatable, dimension(:); + !> @n "GridCellCount", @a dest: integer; + !> @n "InputVarNames", @a dest: character(len=:), allocatable, dimension(:); + !> @n "OutputVarNames", @a dest: character(len=:), allocatable, dimension(:); + !> @n "Porosity", @a dest: real(kind=8), allocatable, dimension(:); + !> @n "Pressure", @a dest: real(kind=8), allocatable, dimension(:); + !> @n "Saturation", @a dest: real(kind=8), allocatable, dimension(:); + !> @n "SelectedOutput", @a dest: real(kind=8), allocatable, dimension(:,:); + !> @n "SelectedOutputColumnCount", @a dest: integer; + !> @n "SelectedOutputCount", @a dest: integer; + !> @n "SelectedOutputHeadings", @a dest: character(len=:), allocatable, dimension(:); + !> @n "SelectedOutputOn", @a dest: logical; + !> @n "SelectedOutputRowCount", @a dest: integer; + !> @n "SolutionVolume", @a dest: real(kind=8), allocatable, dimension(:); + !> @n "Temperature", @a dest: real(kind=8), allocatable, dimension(:); + !> @n "Time", @a dest: real(kind=8); + !> @n "TimeStep", @a dest: real(kind=8). + !> + !> @see + !> @ref bmif_get_output_var_names, + !> @ref bmif_get_output_item_count, + !> @ref bmif_get_var_itemsize, + !> @ref bmif_get_var_nbytes, + !> @ref bmif_get_var_type, + !> @ref bmif_get_var_units, + !> @ref bmif_set_value. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> real(kind=8), allocatable, dimension(:) :: bmi_density
+    !> character(len=:), allocatable, dimension(:) :: bmi_comps
+    !> status = bmif_get_value(id, "Density", bmi_density)
+    !> status = bmif_get_value("Components", bmi_comps)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref RM_MpiWorker. + + INTERFACE bmif_get_value + module procedure bmif_get_value_logical + module procedure bmif_get_value_char + module procedure bmif_get_value_char1 + module procedure bmif_get_value_double + module procedure bmif_get_value_double1 + module procedure bmif_get_value_double2 + module procedure bmif_get_value_float ! not implemented + module procedure bmif_get_value_int + module procedure bmif_get_value_int1 + module procedure bmif_get_value_int2 + END INTERFACE bmif_get_value + + INTERFACE get_value_at_indices + module procedure get_value_at_indices_double ! not implemented + module procedure get_value_at_indices_float ! not implemented + module procedure get_value_at_indices_int ! not implemented + END INTERFACE get_value_at_indices + + INTERFACE bmif_set_value + module procedure bmif_set_value_b + module procedure bmif_set_value_c + module procedure bmif_set_value_double + module procedure bmif_set_value_double1 + module procedure bmif_set_value_double2 + module procedure bmif_set_value_float ! not implemented + module procedure bmif_set_value_int + module procedure bmif_set_value_int1 + module procedure bmif_set_value_int2 + END INTERFACE bmif_set_value + + INTERFACE set_value_at_indices + module procedure set_value_at_indices_double ! not implemented + module procedure set_value_at_indices_float ! not implemented + module procedure set_value_at_indices_int ! not implemented + END INTERFACE set_value_at_indices + + INTERFACE bmif_get_value_ptr + module procedure bmif_get_value_ptr_logical + module procedure bmif_get_value_ptr_double + module procedure bmif_get_value_ptr_double1 + module procedure bmif_get_value_ptr_float ! not implemented + module procedure bmif_get_value_ptr_integer + END INTERFACE bmif_get_value_ptr + + CONTAINS + + ! ==================================================== + ! Initialize, run, finalize (IRF) + ! ==================================================== + + !> bmif_create creates a reaction module. If the code is compiled with + !> the preprocessor directive USE_OPENMP, the reaction module is multithreaded. + !> If the code is compiled with the preprocessor directive USE_MPI, the reaction + !> module will use MPI and multiple processes. If neither preprocessor directive is used, + !> the reaction module will be serial (unparallelized). + !> @param nxyz The number of grid cells in the user's model. + !> @param nthreads (or @a comm, MPI) When using OPENMP, the argument (@a nthreads) is the number of worker threads to be used. + !> If @a nthreads <= 0, the number of threads is set equal to the number of processors of the computer. + !> When using MPI, the argument (@a comm) is the MPI communicator to use within the reaction module. + !> @retval Id of the PhreeqcRM instance, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_Destroy. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> nxyz = 40
+    !> #ifdef USE_MPI
+    !>   id = RM_Create(nxyz, MPI_COMM_WORLD)
+    !>   call MPI_Comm_rank(MPI_COMM_WORLD, mpi_myself, status)
+    !>   if (status .ne. MPI_SUCCESS) then
+    !>     stop "Failed to get mpi_myself"
+    !>   endif
+    !>   if (mpi_myself > 0) then
+    !>     status = RM_MpiWorker(id)
+    !>     status = RM_Destroy(id)
+    !>     return
+    !>   endif
+    !> #else
+    !>   nthreads = 3
+    !>   id = RM_Create(nxyz, nthreads)
+    !> #endif
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root and workers. + INTEGER FUNCTION bmif_create(nxyz, nthreads) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION RM_BMI_Create(nxyz, nthreads) & + BIND(C, NAME='RM_BMI_Create') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: nxyz + INTEGER(KIND=C_INT), INTENT(in) :: nthreads + END FUNCTION RM_BMI_Create + END INTERFACE + INTEGER, INTENT(in) :: nxyz + INTEGER, INTENT(in) :: nthreads + bmif_create = RM_BMI_Create(nxyz, nthreads) + return + END FUNCTION bmif_create + + !> bmif_initialize uses a YAML file to initialize an instance of BMIPhreeqcRM. Same as + !> @ref RM_InitializeYAML. + !> @param id The instance @a id returned from @ref RM_Create. + !> @param config_file String containing the YAML file name. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @par + !> The file contains a YAML map of PhreeqcRM methods + !> and the arguments corresponding to the methods. + !> Note that the PhreeqcRM methods do not have the "RM_" prefix + !> and the id argument is not included. + !> For example, + !> @par + !> @htmlonly + !> + !>
+    !> LoadDatabase: phreeqc.dat
+    !> RunFile:
+    !> workers: true
+    !> initial_phreeqc: true
+    !> utility: true
+    !> chemistry_name: advect.pqi
+    !> 
+ !>
+ !> @endhtmlonly + !> @par + !> @ref bmif_initialize will read the YAML file and execute the specified methods with + !> the specified arguments. Using YAML + !> terminology, the argument(s) for a method may be a scalar, a sequence, or a map, + !> depending if the argument is + !> a single item, a single vector, or there are multiple arguments. + !> In the case of a map, the name associated + !> with each argument (for example "chemistry_name" above) is arbitrary. + !> The names of the map keys for map + !> arguments are not used in parsing the YAML file; only the order of + !> the arguments is important. + !> @par + !> The following list gives the PhreeqcRM methods that can be specified in a YAML file + !> and the arguments that are required. The arguments are described with C++ formats, which + !> are sufficient to identify which arguments are YAML scalars (single bool/logical, + !> int, double, string/character argument), + !> sequences (single vector argument), or maps (multiple arguments). + !> @htmlonly + !> + !>
+    !> @n CloseFiles(void);
+    !> @n CreateMapping(std::vector< int >& grid2chem);
+    !> @n DumpModule();
+    !> @n FindComponents();
+    !> @n InitialPhreeqc2Module(std::vector< int > initial_conditions1);
+    !> @n InitialPhreeqc2Module(std::vector< int > initial_conditions1, std::vector< int > initial_conditions2, std::vector< double > fraction1);
+    !> @n InitialPhreeqcCell2Module(int n, std::vector< int > cell_numbers);
+    !> @n LoadDatabase(std::string database);
+    !> @n OpenFiles(void);
+    !> @n OutputMessage(std::string str);
+    !> @n RunCells(void);
+    !> @n RunFile(bool workers, bool initial_phreeqc, bool utility, std::string chemistry_name);
+    !> @n RunString(bool workers, bool initial_phreeqc, bool utility, std::string input_string);
+    !> @n ScreenMessage(std::string str);
+    !> @n SetComponentH2O(bool tf);
+    !> @n SetConcentrations(std::vector< double > c);
+    !> @n SetCurrentSelectedOutputUserNumber(int n_user);
+    !> @n SetDensity(std::vector< double > density);
+    !> @n SetDumpFileName(std::string dump_name);
+    !> @n SetErrorHandlerMode(int mode);
+    !> @n SetErrorOn(bool tf);
+    !> @n SetFilePrefix(std::string prefix);
+    !> @n SetGasCompMoles(std::vector< double > gas_moles);
+    !> @n SetGasPhaseVolume(std::vector< double > gas_volume);
+    !> @n SetPartitionUZSolids(bool tf);
+    !> @n SetPorosity(std::vector< double > por);
+    !> @n SetPressure(std::vector< double > p);
+    !> @n SetPrintChemistryMask(std::vector< int > cell_mask);
+    !> @n SetPrintChemistryOn(bool workers, bool initial_phreeqc, bool utility);
+    !> @n SetRebalanceByCell(bool tf);
+    !> @n SetRebalanceFraction(double f);
+    !> @n SetRepresentativeVolume(std::vector< double > rv);
+    !> @n SetSaturation(std::vector< double > sat);
+    !> @n SetScreenOn(bool tf);
+    !> @n SetSelectedOutputOn(bool tf);
+    !> @n SetSpeciesSaveOn(bool save_on);
+    !> @n SetTemperature(std::vector< double > t);
+    !> @n SetTime(double time);
+    !> @n SetTimeConversion(double conv_factor);
+    !> @n SetTimeStep(double time_step);
+    !> @n SetUnitsExchange(int option);
+    !> @n SetUnitsGasPhase(int option);
+    !> @n SetUnitsKinetics(int option);
+    !> @n SetUnitsPPassemblage(int option);
+    !> @n SetUnitsSolution(int option);
+    !> @n SetUnitsSSassemblage(int option);
+    !> @n SetUnitsSurface(int option);
+    !> @n SpeciesConcentrations2Module(std::vector< double > species_conc);
+    !> @n StateSave(int istate);
+    !> @n StateApply(int istate);
+    !> @n StateDelete(int istate);
+    !> @n UseSolutionDensityVolume(bool tf);
+    !> @n WarningMessage(std::string warnstr);
+    !> 
+ !>
+ !> @endhtmlonly + !> + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> id = RM_Create(nxyz, MPI_COMM_WORLD)
+    !> status = RM_InitializeYAML(id, "myfile.yaml")
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref RM_MpiWorker. +#if defined(USE_YAML) + INTEGER FUNCTION bmif_initialize(id, config_file) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION RMF_BMI_Initialize(id, config_file) & + BIND(C, NAME='RMF_BMI_Initialize') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + CHARACTER(KIND=C_CHAR), INTENT(in) :: config_file(*) + END FUNCTION RMF_BMI_Initialize + END INTERFACE + INTEGER, INTENT(in) :: id + CHARACTER(len=*), INTENT(in) :: config_file + bmif_initialize = success(RMF_BMI_Initialize(id, trim(config_file)//C_NULL_CHAR)) + return + END FUNCTION bmif_initialize +#endif + + !> bmif_update runs a reaction step for all of the cells in the reaction module. + !> Same as @ref RM_RunCells. + !> Normally, tranport concentrations are transferred to the reaction cells + !> (@ref bmif_set_value "Concentrations" before + !> reaction calculations are run. The length of time over which kinetic + !> reactions are integrated is set + !> by @ref bmif_set_value "TimeStep". Other properties that may need to be updated + !> as a result of the transport + !> calculations include porosity (@ref bmif_set_value "Porosity"), + !> pressure (@ref bmif_set_value "Pressure"), + !> saturation (@ref bmif_set_value "Saturation"), + !> temperature (@ref bmif_set_value "Temperature"). + !> @param id The instance @a id returned from @ref RM_Create. + !> @retval IRM_BMI_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref bmif_set_value. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> status = bmif_set_value(id, "Porosity", por)                ! If pore volume changes
+    !> status = bmif_set_value(id, "Saturation", sat)              ! If saturation changes
+    !> status = bmif_set_value(id, "Temperature", temperature)     ! If temperature changes
+    !> status = bmif_set_value(id, "Pressure", pressure)           ! If pressure changes
+    !> status = bmif_set_value(id, "Concentrations", c)            ! Transported concentrations
+    !> status = bmif_set_value(id, "TimeStep", time_step)          ! Time step for kinetic reactions
+    !> status = bmif_update(id)
+    !> status = bmif_get_value(id, "Concentrations", c)            ! Concentrations after reaction
+    !> status = bmif_get_value(id, "Density", density)             ! Density after reaction
+    !> status = bmif_get_value(id, "SolutionVolume", volume)       ! Solution volume after reaction
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref RM_MpiWorker. + INTEGER FUNCTION bmif_update(id) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION RMF_BMI_Update(id) & + BIND(C, NAME='RMF_BMI_Update') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + END FUNCTION RMF_BMI_Update + END INTERFACE + INTEGER, INTENT(in) :: id + bmif_update = success(RMF_BMI_Update(id)) + return + END FUNCTION bmif_update + + !> bmif_update TODOxxxxxxxxxxxxxxxRuns a reaction step for all of the cells in the reaction module. + !> Same as @ref RM_RunCells. + !> Normally, tranport concentrations are transferred to the reaction cells + !> (@ref bmif_set_value "Concentrations" before + !> reaction calculations are run. The length of time over which kinetic + !> reactions are integrated is set + !> by @ref bmif_set_value "TimeStep". Other properties that may need to be updated + !> as a result of the transport + !> calculations include porosity (@ref bmif_set_value "Porosity"), + !> pressure (@ref bmif_set_value "Pressure"), + !> saturation (@ref bmif_set_value "Saturation"), + !> temperature (@ref bmif_set_value "Temperature"). + !> @param id The instance @a id returned from @ref RM_Create. + !> @retval IRM_BMI_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref bmif_set_value. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> status = bmif_set_value(id, "Porosity", por)                ! If pore volume changes
+    !> status = bmif_set_value(id, "Saturation", sat)              ! If saturation changes
+    !> status = bmif_set_value(id, "Temperature", temperature)     ! If temperature changes
+    !> status = bmif_set_value(id, "Pressure", pressure)           ! If pressure changes
+    !> status = bmif_set_value(id, "Concentrations", c)            ! Transported concentrations
+    !> status = bmif_set_value(id, "TimeStep", time_step)          ! Time step for kinetic reactions
+    !> status = bmif_update(id)
+    !> status = bmif_get_value(id, "Concentrations", c)            ! Concentrations after reaction
+    !> status = bmif_get_value(id, "Density", density)             ! Density after reaction
+    !> status = bmif_get_value(id, "SolutionVolume", volume)       ! Solution volume after reaction
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref RM_MpiWorker. + INTEGER FUNCTION bmif_update_until(id, time) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION RMF_BMI_UpdateUntil(id, time) & + BIND(C, NAME='RMF_BMI_UpdateUntil') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + real(kind=C_DOUBLE), INTENT(in) :: time + END FUNCTION RMF_BMI_UpdateUntil + END INTERFACE + INTEGER, INTENT(in) :: id + real(kind=8), INTENT(in) :: time + bmif_update_until = success(RMF_BMI_UpdateUntil(id, time)) + return + END FUNCTION bmif_update_until + + !> bmif_finalize destroys a reaction module, same as @ref RM_Destroy. + !> @param id The instance @a id returned from @ref RM_Create. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_Create. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> status = bmif_finalize(id)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root and workers. + INTEGER FUNCTION bmif_finalize(id) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION RM_Destroy(id) & + BIND(C, NAME='RM_Destroy') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + END FUNCTION RM_Destroy + END INTERFACE + INTEGER, INTENT(in) :: id + bmif_finalize = success(RM_Destroy(id)) + return + END FUNCTION bmif_finalize + + ! ==================================================== + ! Exchange items + ! ==================================================== + + !> bmif_get_component_name returns the component name--BMIPhreeqcRM. The BMI interface to PhreeqcRM is + !> only partial, and provides only the most basic functions. The native PhreeqcRM methods (those without the the BMI_ + !> prefix) provide a complete interface, and it is expected that the native methods will be used in preference to the BMI_ + !> methods. + !> + !> @param id The instance @a id returned from @ref RM_Create. + !> @param component_name is filled with "PhreeqcRM", the name of the component. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> status = bmif_get_component_name(id, component_name)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root. + INTEGER FUNCTION bmif_get_component_name(id, component_name) + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER, INTENT(in) :: id + CHARACTER(len=*), INTENT(inout) :: component_name + component_name = "BMI_PhreeqcRM" + bmif_get_component_name = BMI_SUCCESS + return + END FUNCTION bmif_get_component_name + + + !> Basic Model Interface method that returns count of input variables that + !> can be set with @ref bmif_set_value. + !> @retval Count of input variables that can be set with @ref bmif_set_value. + !> @param id The instance @a id returned from @ref RM_Create. + !> + !> @see + !> @ref bmif_get_input_var_names, + !> @ref bmif_get_var_itemsize, + !> @ref bmif_get_var_nbytes, + !> @ref bmif_get_var_type, + !> @ref bmif_get_var_units, + !> @ref bmif_set_value. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> integer inputvarcount
+    !> inputvarcount = bmif_get_input_item_count(id);
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root. + !> + INTEGER FUNCTION bmif_get_input_item_count(id, count) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION RMF_BMI_GetInputItemCount(id) & + BIND(C, NAME='RMF_BMI_GetInputItemCount') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + END FUNCTION RMF_BMI_GetInputItemCount + END INTERFACE + INTEGER, INTENT(in) :: id + INTEGER, INTENT(inout) :: count + INTEGER :: status + count = RMF_BMI_GetInputItemCount(id) + bmif_get_input_item_count = success(count) + END FUNCTION bmif_get_input_item_count + + !> bmif_get_output_item_count returns count of output variables that can be + !> retrieved with @ref bmif_get_value. + !> @param id The instance @a id returned from @ref RM_Create. + !> @retval Count of output variables that can be retrieved with @ref bmif_get_value. + !> + !> @see + !> @ref bmif_get_output_var_names, + !> @ref bmif_get_value, + !> @ref bmif_get_var_itemsize, + !> @ref bmif_get_var_nbytes, + !> @ref bmif_get_var_type, + !> @ref bmif_get_var_units. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> integer outputvarcount
+    !> outputvarcount = bmif_get_output_item_count(id);
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root. + INTEGER FUNCTION bmif_get_output_item_count(id, count) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION RMF_BMI_GetOutputItemCount(id) & + BIND(C, NAME='RMF_BMI_GetOutputItemCount') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + END FUNCTION RMF_BMI_GetOutputItemCount + END INTERFACE + INTEGER, INTENT(in) :: id + INTEGER, INTENT(inout) :: count + INTEGER :: status + count = RMF_BMI_GetOutputItemCount(id) + bmif_get_output_item_count = success(count) + END FUNCTION bmif_get_output_item_count + + !> Basic Model Interface method that returns count of variables for which + !> pointers can be retrieved with @ref bmif_get_ptr. + !> @retval Count of input variables that can be set with @ref bmif_set_value. + !> @param id The instance @a id returned from @ref RM_Create. + !> + !> @see + !> @ref bmif_get_input_var_names, + !> @ref bmif_get_var_itemsize, + !> @ref bmif_get_var_nbytes, + !> @ref bmif_get_var_type, + !> @ref bmif_get_var_units, + !> @ref bmif_set_value. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> integer inputvarcount
+    !> inputvarcount = bmif_get_input_item_count(id);
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root. + !> + INTEGER FUNCTION bmif_get_pointable_item_count(id, count) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION RMF_BMI_GetPointableItemCount(id) & + BIND(C, NAME='RMF_BMI_GetPointableItemCount') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + END FUNCTION RMF_BMI_GetPointableItemCount + END INTERFACE + INTEGER, INTENT(in) :: id + INTEGER, INTENT(inout) :: count + INTEGER :: status + count = RMF_BMI_GetPointableItemCount(id) + bmif_get_pointable_item_count = success(count) + END FUNCTION bmif_get_pointable_item_count + + !> Basic Model Interface method that returns a list of the variable names that can be set + !> with @ref bmif_set_value. + !> @param id The instance @a id returned from @ref RM_Create. + !> @param var_names Deferred length, allocatable, 1D character vector. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> + !> @see + !> @ref bmif_get_input_item_count, + !> @ref bmif_get_value, + !> @ref bmif_get_var_itemsize, + !> @ref bmif_get_var_nbytes, + !> @ref bmif_get_var_type, + !> @ref bmif_get_var_units, + !> @ref bmif_set_value. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> character(len=:), dimension(:), allocatable          :: inputvars
+    !> status = bmif_get_input_var_names(id, inputvars)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root. + INTEGER FUNCTION bmif_get_input_var_names(id, dest) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION RMF_BMI_GetNames(id, type, dest) & + BIND(C, NAME='RMF_BMI_GetNames') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + CHARACTER(KIND=C_CHAR), INTENT(in) :: type + CHARACTER(KIND=C_CHAR), INTENT(inout) :: dest + END FUNCTION RMF_BMI_GetNames + END INTERFACE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION RMF_BMI_GetNamesSize(id, type, dest) & + BIND(C, NAME='RMF_BMI_GetNamesSize') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + CHARACTER(KIND=C_CHAR), INTENT(in) :: type + INTEGER(KIND=C_INT), INTENT(inout) :: dest + END FUNCTION RMF_BMI_GetNamesSize + END INTERFACE + INTEGER, INTENT(in) :: id + CHARACTER(len=:), allocatable, dimension(:), INTENT(inout) :: dest + character(100) :: vartype + integer :: nbytes, status, dim, itemsize + vartype = "inputvarnames" + status = RMF_BMI_GetNamesSize(id, trim(vartype)//C_NULL_CHAR, itemsize) + status = bmif_get_input_item_count(id, dim) + nbytes = dim * itemsize + dim = nbytes / itemsize + if(allocated(dest)) deallocate(dest) + allocate(character(len=itemsize) :: dest(dim)) + bmif_get_input_var_names = RMF_BMI_GetNames(id, trim(vartype)//C_NULL_CHAR, dest(1)) + return + END FUNCTION bmif_get_input_var_names + + !> bmif_get_output_var_names returns a list of the variable names that can be + !> retrieved with @ref bmif_get_value. + !> @param id The instance @a id returned from @ref RM_Create. + !> @param var_names Deferred length, allocatable, 1D character vector. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> + !> @see + !> @ref bmif_get_output_item_count, + !> @ref bmif_get_value, + !> @ref bmif_get_var_itemsize, + !> @ref bmif_get_var_nbytes, + !> @ref bmif_get_var_type, + !> @ref bmif_get_var_units. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> character(len=:), allocatable, dimension(:) :: var_names
+    !> var_names = bmif_get_output_var_names(id);
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root. + INTEGER FUNCTION bmif_get_output_var_names(id, dest) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION RMF_BMI_GetNames(id, type, dest) & + BIND(C, NAME='RMF_BMI_GetNames') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + CHARACTER(KIND=C_CHAR), INTENT(in) :: type + CHARACTER(KIND=C_CHAR), INTENT(inout) :: dest + END FUNCTION RMF_BMI_GetNames + END INTERFACE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION RMF_BMI_GetNamesSize(id, type, dest) & + BIND(C, NAME='RMF_BMI_GetNamesSize') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + CHARACTER(KIND=C_CHAR), INTENT(in) :: type + INTEGER(KIND=C_INT), INTENT(inout) :: dest + END FUNCTION RMF_BMI_GetNamesSize + END INTERFACE + INTEGER, INTENT(in) :: id + CHARACTER(len=:), allocatable, dimension(:), INTENT(inout) :: dest + character(100) :: vartype + integer :: nbytes, status, dim, itemsize + vartype = "outputvarnames" + status = RMF_BMI_GetNamesSize(id, trim(vartype)//C_NULL_CHAR, itemsize) + status = bmif_get_output_item_count(id, dim) + nbytes = dim * itemsize + if(allocated(dest)) deallocate(dest) + allocate(character(len=itemsize) :: dest(dim)) + bmif_get_output_var_names = RMF_BMI_GetNames(id, trim(vartype)//C_NULL_CHAR, dest(1)) + return + END FUNCTION bmif_get_output_var_names + + !> bmif_get_pointable_var_names returns a list of the variable names that can be + !> retrieved with @ref bmif_get_value. + !> @param id The instance @a id returned from @ref RM_Create. + !> @param var_names Deferred length, allocatable, 1D character vector. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> + !> @see + !> @ref bmif_get_pointable_item_count, + !> @ref bmif_get_value, + !> @ref bmif_get_var_itemsize, + !> @ref bmif_get_var_nbytes, + !> @ref bmif_get_var_type, + !> @ref bmif_get_var_units. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> character(len=:), allocatable, dimension(:) :: var_names
+    !> var_names = bmif_get_output_var_names(id);
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root. + INTEGER FUNCTION bmif_get_pointable_var_names(id, dest) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION RMF_BMI_GetNames(id, type, dest) & + BIND(C, NAME='RMF_BMI_GetNames') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + CHARACTER(KIND=C_CHAR), INTENT(in) :: type + CHARACTER(KIND=C_CHAR), INTENT(inout) :: dest + END FUNCTION RMF_BMI_GetNames + END INTERFACE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION RMF_BMI_GetNamesSize(id, type, dest) & + BIND(C, NAME='RMF_BMI_GetNamesSize') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + CHARACTER(KIND=C_CHAR), INTENT(in) :: type + INTEGER(KIND=C_INT), INTENT(inout) :: dest + END FUNCTION RMF_BMI_GetNamesSize + END INTERFACE + INTEGER, INTENT(in) :: id + CHARACTER(len=:), allocatable, dimension(:), INTENT(inout) :: dest + character(100) :: vartype + integer :: nbytes, status, dim, itemsize + vartype = "pointablevarnames" + status = RMF_BMI_GetNamesSize(id, trim(vartype)//C_NULL_CHAR, itemsize) + status = bmif_get_pointable_item_count(id, dim) + nbytes = dim * itemsize + dim = nbytes / itemsize + if(allocated(dest)) deallocate(dest) + allocate(character(len=itemsize) :: dest(dim)) + bmif_get_pointable_var_names = RMF_BMI_GetNames(id, trim(vartype)//C_NULL_CHAR, dest(1)) + return + END FUNCTION bmif_get_pointable_var_names ! ==================================================== + ! Variable information + ! ==================================================== + + integer FUNCTION bmif_get_var_grid(id, var, grid) + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER, INTENT(in) :: id + CHARACTER(len=*), INTENT(in) :: var + INTEGER, INTENT(out) :: grid + grid = 1 + bmif_get_var_grid = BMI_SUCCESS + END FUNCTION bmif_get_var_grid + + !> bmif_get_var_type retrieves the type of a variable that can be set with + !> @ref bmif_set_value or retrieved with @ref bmif_get_value. Types are "character", + !> "real(kind=8)","integer", or "logical", + !> or an allocatable array of these types. + !> Only variables in the list + !> provided by @ref bmif_get_input_var_names can be set. + !> Only variables in the list + !> provided by @ref bmif_get_output_var_names can be retrieved. + !> @param id The instance @a id returned from @ref RM_Create. + !> @param var Name of the variable to retrieve total bytes. + !> @param vtype Type of the variable. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref bmif_get_input_var_names, + !> @ref bmif_get_input_item_count, + !> @ref bmif_get_output_var_names, + !> @ref bmif_get_output_item_count, + !> @ref bmif_get_var_units. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> do i = 1, size(inputvars)
+    !>     write(*,"(1x, I4, A40)") i, trim(inputvars(i))
+    !>     status = bmif_get_var_units(id, inputvars(i), string)
+    !>     write(*,"(5x, A15)") trim(string)
+    !>     status = bmif_get_var_type(id, inputvars(i), string)
+    !>     write(*,"(5x, A15)") trim(string)
+    !>     write(*, "(5x, I15)") bmif_get_var_itemsize(id, inputvars(i))
+    !>     write(*, "(5x, I15)") bmif_get_var_nbytes(id, inputvars(i))
+    !> enddo
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root. + INTEGER FUNCTION bmif_get_var_type(id, var, vtype) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION RMF_BMI_GetVarType(id, var, vtype, l) & + BIND(C, NAME='RMF_BMI_GetVarType') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id, l + CHARACTER(KIND=C_CHAR), INTENT(in) :: var(*) + CHARACTER(KIND=C_CHAR), INTENT(inout) :: vtype(*) + END FUNCTION RMF_BMI_GetVarType + END INTERFACE + INTEGER, INTENT(in) :: id + CHARACTER(len=*), INTENT(in) :: var + CHARACTER(len=*), INTENT(inout) :: vtype + bmif_get_var_type = success(RMF_BMI_GetVarType(id, trim(var)//C_NULL_CHAR, vtype, len(vtype))) + return + END FUNCTION bmif_get_var_type + + !> bmif_get_var_units retrieves the units of a + !> variable that can be set with + !> @ref bmif_set_value or retrieved with @ref bmif_get_value. + !> Only variables in the list + !> provided by @ref bmif_get_input_var_names can be set. + !> Only variables in the list + !> provided by @ref bmif_get_output_var_names can be retrieved. + !> @param id The instance @a id returned from @ref RM_Create. + !> @param var Name of the variable to retrieve total bytes. + !> @param units Units of the variable. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref bmif_get_input_var_names, + !> @ref bmif_get_input_item_count, + !> @ref bmif_get_output_var_names, + !> @ref bmif_get_output_item_count, + !> @ref bmif_get_var_type. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> do i = 1, size(inputvars)
+    !>     write(*,"(1x, I4, A40)") i, trim(inputvars(i))
+    !>     status = bmif_get_var_units(id, inputvars(i), string)
+    !>     write(*,"(5x, A15)") trim(string)
+    !>     status = bmif_get_var_type(id, inputvars(i), string)
+    !>     write(*,"(5x, A15)") trim(string)
+    !>     write(*, "(5x, I15)") bmif_get_var_itemsize(id, inputvars(i))
+    !>     write(*, "(5x, I15)") bmif_get_var_nbytes(id, inputvars(i))
+    !> enddo
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root. + INTEGER FUNCTION bmif_get_var_units(id, var, units) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION RMF_BMI_GetVarUnits(id, var, units, l) & + BIND(C, NAME='RMF_BMI_GetVarUnits') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id, l + CHARACTER(KIND=C_CHAR), INTENT(in) :: var(*) + CHARACTER(KIND=C_CHAR), INTENT(inout) :: units(*) + END FUNCTION RMF_BMI_GetVarUnits + END INTERFACE + INTEGER, INTENT(in) :: id + CHARACTER(len=*), INTENT(in) :: var + CHARACTER(len=*), INTENT(inout) :: units + bmif_get_var_units = success(RMF_BMI_GetVarUnits(id, trim(var)//C_NULL_CHAR, units, len(units))) + return + END FUNCTION bmif_get_var_units + + !> bmif_get_var_itemsize retrieves the size of an + !> individual item that can be set or retrived. + !> Sizes may be sizeof(int), sizeof(double), + !> or a character length for string variables. Only variables in the list + !> provided by @ref bmif_get_input_var_names can be set. + !> Only variables in the list + !> provided by @ref bmif_get_output_var_names can be retrieved. + !> @param id The instance @a id returned from @ref RM_Create. + !> @param var Name of the variable to retrieve. + !> @retval Size of one element of the variable. + !> + !> @see + !> @ref bmif_get_input_var_names, + !> @ref bmif_get_input_item_count, + !> @ref bmif_get_output_var_names, + !> @ref bmif_get_output_item_count, + !> @ref bmif_get_value, + !> @ref bmif_get_var_nbytes, + !> @ref bmif_set_value. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> integer nbytes, item_size, dim
+    !> real(kind=8), allocatable, dimension(:) :: bmi_temperature
+    !> nbytes = bmif_get_var_nbytes(id, "Temperature")
+    !> item_size = bmif_get_var_itemsize(id, "Temperature");
+    !> int dim = nbytes/item_size;
+    !> allocate(bmi_temperature(dim))
+    !> bmi_temperature = 25.0
+    !> status = bmif_set_value("Temperature", bmi_temperature);
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root. + INTEGER FUNCTION bmif_get_var_itemsize(id, var, itemsize) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION RMF_BMI_GetVarItemsize(id, var) & + BIND(C, NAME='RMF_BMI_GetVarItemsize') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + CHARACTER(KIND=C_CHAR), INTENT(in) :: var(*) + END FUNCTION RMF_BMI_GetVarItemsize + END INTERFACE + INTEGER, INTENT(in) :: id + CHARACTER(len=*), INTENT(in) :: var + INTEGER, INTENT(out) :: itemsize + itemsize = RMF_BMI_GetVarItemsize(id, trim(var)//C_NULL_CHAR) + bmif_get_var_itemsize = success(bmif_get_var_itemsize) + END FUNCTION bmif_get_var_itemsize + + !> bmif_get_var_nbytes retrieves the size of an + !> individual item that can be set or retrived. + !> Sizes may be sizeof(int), sizeof(double), + !> or a character length for string variables. Only variables in the list + !> provided by @ref bmif_get_input_var_names can be set. + !> Only variables in the list + !> provided by @ref bmif_get_output_var_names can be retrieved. + !> @param id The instance @a id returned from @ref RM_Create. + !> @param var Name of the variable to retrieve size. + !> @retval Size of one element of the variable. + !> + !> @see + !> @ref bmif_get_input_var_names, + !> @ref bmif_get_input_item_count, + !> @ref bmif_get_output_var_names, + !> @ref bmif_get_output_item_count, + !> @ref bmif_get_value, + !> @ref bmif_get_var_nbytes, + !> @ref bmif_set_value. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> integer nbytes, item_size, dim
+    !>  real(kind=8), allocatable, dimension(:) :: bmi_temperature
+    !> nbytes = bmif_get_var_nbytes(id, "Temperature")
+    !> item_size = bmif_get_var_itemsize(id, "Temperature");
+    !> int dim = nbytes/item_size;
+    !> allocate(bmi_temperature(dim))
+    !>  bmi_temperature = 25.0
+    !> status = bmif_set_value("Temperature", bmi_temperature);
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root. + INTEGER FUNCTION bmif_get_var_nbytes(id, var, nbytes) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION RMF_BMI_GetVarNbytes(id, var) & + BIND(C, NAME='RMF_BMI_GetVarNbytes') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + CHARACTER(KIND=C_CHAR), INTENT(in) :: var(*) + END FUNCTION RMF_BMI_GetVarNbytes + END INTERFACE + INTEGER, INTENT(in) :: id + CHARACTER(len=*), INTENT(in) :: var + INTEGER, INTENT(out) :: nbytes + nbytes = RMF_BMI_GetVarNbytes(id, trim(var)//C_NULL_CHAR) + bmif_get_var_nbytes = success(nbytes) + END FUNCTION bmif_get_var_nbytes + + ! ==================================================== + ! Time information + ! ==================================================== + + !> bmif_get_current_time returns the current simulation time, in seconds. (Same as @ref RM_GetTime.) + !> The reaction module does not change the time value, so the + !> returned value is equal to the default (0.0) or the last time set by + !> @ref bmif_set_value("Time", time) or @ref RM_SetTime. + !> @param id The instance @a id returned from @ref RM_Create. + !> @retval The current simulation time, in seconds. + !> @see + !> @ref bmif_get_end_time, + !> @ref bmif_get_time_step, + !> @ref bmif_set_value, + !> @ref RM_GetTime, + !> @ref RM_GetTimeStep, + !> @ref RM_SetTime, + !> @ref RM_SetTimeStep. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> time = bmif_get_current_time(id)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root. + INTEGER FUNCTION bmif_get_current_time(id, time) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + REAL(KIND=C_DOUBLE) FUNCTION RMF_BMI_GetCurrentTime(id) & + BIND(C, NAME='RMF_BMI_GetCurrentTime') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + END FUNCTION RMF_BMI_GetCurrentTime + END INTERFACE + INTEGER, INTENT(in) :: id + real(kind=8), intent(inout) :: time + time = RMF_BMI_GetCurrentTime(id) + bmif_get_current_time = BMI_SUCCESS + END FUNCTION bmif_get_current_time + + INTEGER FUNCTION bmif_get_start_time(id, start_time) + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER, INTENT(in) :: id + real(kind=8), INTENT(inout) :: start_time + bmif_get_start_time = bmif_get_current_time(id, start_time) + END FUNCTION bmif_get_start_time + + !> bmif_get_end_time returns @ref bmif_get_current_time plus + !> @ref bmif_get_time_step, in seconds. + !> @param id The instance @a id returned from @ref RM_Create. + !> @retval The end of the time step, in seconds. + !> @see + !> @ref bmif_get_current_time, + !> @ref bmif_get_time_step, + !> @ref bmif_set_value, + !> @ref RM_GetTime, + !> @ref RM_GetTimeStep, + !> @ref RM_SetTime, + !> @ref RM_SetTimeStep. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> time = bmif_get_end_time(id)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root. + INTEGER FUNCTION bmif_get_end_time(id, end_time) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + REAL(KIND=C_DOUBLE) FUNCTION RMF_BMI_GetEndTime(id) & + BIND(C, NAME='RMF_BMI_GetEndTime') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + END FUNCTION RMF_BMI_GetEndTime + END INTERFACE + INTEGER, INTENT(in) :: id + real(kind=8), intent(inout) :: end_time + end_time = RMF_BMI_GetEndTime(id) + bmif_get_end_time = BMI_SUCCESS + END FUNCTION bmif_get_end_time + + !> bmif_get_time_units returns the time units of PhreeqcRM. + !> All time units are seconds for PhreeqcRM. + !> @param id The instance @a id returned from @ref RM_Create. + !> @param time_units The instance @a id returned from @ref RM_Create. + !> @retval Returns the string "seconds". + !> @see + !> @ref bmif_get_current_time, + !> @ref bmif_get_end_time, + !> @ref bmif_get_time_step, + !> @ref bmif_set_value, + !> @ref RM_GetTime, + !> @ref RM_GetTimeStep, + !> @ref RM_SetTime, + !> @ref RM_SetTimeStep, + !> @ref bmif_set_value. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> character(20) time_units
+    !> status = bmif_get_time_units(id, time_units) << ".\n";
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root. + INTEGER FUNCTION bmif_get_time_units(id, time_units) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION RMF_BMI_GetTimeUnits(id, time_units, l) & + BIND(C, NAME='RMF_BMI_GetTimeUnits') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id, l + CHARACTER(KIND=C_CHAR), INTENT(inout) :: time_units(*) + END FUNCTION RMF_BMI_GetTimeUnits + END INTERFACE + INTEGER, INTENT(in) :: id + CHARACTER(len=*), INTENT(inout) :: time_units + bmif_get_time_units = success(RMF_BMI_GetTimeUnits(id, time_units, len(time_units))) + return + END FUNCTION bmif_get_time_units + + + !> bmif_get_time_step returns the current simulation time step, + !> in seconds. (Same as @ref RM_GetTimeStep.) + !> The reaction module does not change the time-step value, so the + !> returned value is equal to the last time step set by + !> @ref bmif_set_value("TimeStep", time_step) or @ref RM_SetTimeStep. + !> @param id The instance @a id returned from @ref RM_Create. + !> @retval The current simulation time step, in seconds. + !> @see + !> @ref bmif_get_current_time, + !> @ref bmif_get_end_time, + !> @ref bmif_set_value, + !> @ref RM_GetTime, + !> @ref RM_GetTimeStep, + !> @ref RM_SetTime, + !> @ref RM_SetTimeStep. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> time_step = bmif_get_time_step(id)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root. + INTEGER FUNCTION bmif_get_time_step(id, time_step) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + REAL(KIND=C_DOUBLE) FUNCTION RMF_BMI_GetTimeStep(id) & + BIND(C, NAME='RMF_BMI_GetTimeStep') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + END FUNCTION RMF_BMI_GetTimeStep + END INTERFACE + INTEGER, INTENT(in) :: id + real(kind=8), intent(inout) :: time_step + time_step = RMF_BMI_GetTimeStep(id) + bmif_get_time_step = BMI_SUCCESS + END FUNCTION bmif_get_time_step + + ! ==================================================== + ! Getters, by type + ! ==================================================== + + !> Basic Model Interface method that retrieves model variables. Only variables in the list + !> provided by @ref bmif_get_output_var_names can be retrieved. The BMI interface to PhreeqcRM is + !> only partial, and provides only the most basic functions. The native PhreeqcRM methods (those without the the RM_BMI_ + !> prefix) provide a complete interface. + !> @param id The instance @a id returned from @ref RM_Create. + !> @param var Name of the variable to retrieve. + !> @param dest Variable in which to place results. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> + !> Variable names for the second argument (@a name) and variable type of the + !> third argument (@a dest). + !> @n "ComponentCount", @a dest: integer; + !> @n "Components", @a dest: character(len=:), allocatable, dimension(:); + !> @n "Concentrations", @a dest: real(kind=8), allocatable, dimension(:,:); + !> @n "CurrentSelectedOutputUserNumber", @a dest: integer; + !> @n "Density", @a dest: real(kind=8), allocatable, dimension(:); + !> @n "ErrorString", @a dest: character; + !> @n "FilePrefix", @a dest: character; + !> @n "Gfw", @a dest: real(kind=8), allocatable, dimension(:); + !> @n "GridCellCount", @a dest: integer; + !> @n "InputVarNames", @a dest: character(len=:), allocatable, dimension(:); + !> @n "OutputVarNames", @a dest: character(len=:), allocatable, dimension(:); + !> @n "Porosity", @a dest: real(kind=8), allocatable, dimension(:); + !> @n "Pressure", @a dest: real(kind=8), allocatable, dimension(:); + !> @n "Saturation", @a dest: real(kind=8), allocatable, dimension(:); + !> @n "SelectedOutput", @a dest: real(kind=8), allocatable, dimension(:,:); + !> @n "SelectedOutputColumnCount", @a dest: integer; + !> @n "SelectedOutputCount", @a dest: integer; + !> @n "SelectedOutputHeadings", @a dest: character(len=:), allocatable, dimension(:); + !> @n "SelectedOutputOn", @a dest: logical; + !> @n "SelectedOutputRowCount", @a dest: integer; + !> @n "SolutionVolume", @a dest: real(kind=8), allocatable, dimension(:); + !> @n "Temperature", @a dest: real(kind=8), allocatable, dimension(:); + !> @n "Time", @a dest: real(kind=8); + !> @n "TimeStep", @a dest: real(kind=8). + !> + !> @see + !> @ref bmif_get_output_var_names, + !> @ref bmif_get_output_item_count, + !> @ref bmif_get_var_itemsize, + !> @ref bmif_get_var_nbytes, + !> @ref bmif_get_var_type, + !> @ref bmif_get_var_units, + !> @ref bmif_set_value. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> real(kind=8), allocatable, dimension(:) :: bmi_density
+    !> character(len=:), allocatable, dimension(:) :: bmi_comps
+    !> status = bmif_get_value(id, "Density", bmi_density)
+    !> status = bmif_get_value("Components", bmi_comps)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref RM_MpiWorker. + + !> \overload + INTEGER FUNCTION bmif_get_value_logical(id, var, dest) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION RMF_BMI_GetValue(id, var, dest) & + BIND(C, NAME='RMF_BMI_GetValue') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + CHARACTER(KIND=C_CHAR), INTENT(in) :: var(*) + LOGICAL(KIND=C_INT), INTENT(inout) :: dest + END FUNCTION RMF_BMI_GetValue + END INTERFACE + INTEGER, INTENT(in) :: id + CHARACTER(len=*), INTENT(in) :: var + LOGICAL(KIND=4), INTENT(inout) :: dest + character(100) :: vartype + integer :: status + status = bmif_get_var_type(id, var, vartype) + if (vartype .ne. "logical") then + stop "Variable type error." + endif + bmif_get_value_logical = RMF_BMI_GetValue(id, trim(var)//C_NULL_CHAR, dest) + return + END FUNCTION bmif_get_value_logical + + !> \overload + INTEGER FUNCTION bmif_get_value_char(id, var, dest) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION RMF_BMI_GetValue(id, var, dest) & + BIND(C, NAME='RMF_BMI_GetValue') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + CHARACTER(KIND=C_CHAR), INTENT(in) :: var(*) + CHARACTER(KIND=C_CHAR), INTENT(inout) :: dest + END FUNCTION RMF_BMI_GetValue + END INTERFACE + INTEGER, INTENT(in) :: id + CHARACTER(len=*), INTENT(in) :: var + CHARACTER(len=*), INTENT(inout) :: dest + character(BMI_MAX_TYPE_NAME) :: vartype + integer :: itemsize, status + CHARACTER(len=:), allocatable :: temp + status = bmif_get_var_type(id, var, vartype) + if (vartype .ne. "character") then + stop "Variable type error." + endif + status = bmif_get_var_itemsize(id, var, itemsize) + allocate(character(len=itemsize) :: temp) + status = RMF_BMI_GetValue(id, trim(var)//C_NULL_CHAR, temp) + if (len(dest) .gt. 0) then + dest = temp + else + status = RM_ErrorMessage(id, "Variable length is zero") + status = -1 + endif + bmif_get_value_char = success(status) + return + END FUNCTION bmif_get_value_char + + !> \overload + INTEGER FUNCTION bmif_get_value_char_alloc(id, var, dest) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION RMF_BMI_GetValue(id, var, dest) & + BIND(C, NAME='RMF_BMI_GetValue') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + CHARACTER(KIND=C_CHAR), INTENT(in) :: var(*) + CHARACTER(KIND=C_CHAR), INTENT(inout) :: dest + END FUNCTION RMF_BMI_GetValue + END INTERFACE + INTEGER, INTENT(in) :: id + CHARACTER(len=*), INTENT(in) :: var + CHARACTER(len=:), allocatable, INTENT(inout) :: dest + character(BMI_MAX_TYPE_NAME) :: vartype + integer :: itemsize, status + CHARACTER(len=:), allocatable :: temp + status = bmif_get_var_type(id, var, vartype) + if (vartype .ne. "character") then + stop "Variable type error." + endif + status = bmif_get_var_itemsize(id, var, itemsize) + allocate(character(len=itemsize) :: temp) + status = RMF_BMI_GetValue(id, trim(var)//C_NULL_CHAR, temp) + dest = temp + bmif_get_value_char_alloc = success(status) + return + END FUNCTION bmif_get_value_char_alloc + + !> \overload + INTEGER FUNCTION bmif_get_value_char1(id, var, dest) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION RMF_BMI_GetValue(id, var, dest) & + BIND(C, NAME='RMF_BMI_GetValue') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + CHARACTER(KIND=C_CHAR), INTENT(in) :: var(*) + CHARACTER(KIND=C_CHAR), INTENT(inout) :: dest + END FUNCTION RMF_BMI_GetValue + END INTERFACE + INTEGER, INTENT(in) :: id + CHARACTER(len=*), INTENT(in) :: var + CHARACTER(len=:), allocatable, dimension(:), INTENT(inout) :: dest + character(100) :: vartype + integer :: nbytes, status, dim, itemsize + integer :: dim1, dim2 + dim1 = 0 + dim2 = 0 + status = bmif_get_var_type(id, var, vartype) + if (vartype .ne. "character(len=:),allocatable,dimension(:)") then + stop "Variable type error." + endif + status = bmif_get_var_itemsize(id, var, itemsize) + status = bmif_get_var_nbytes(id, var, nbytes) + dim = nbytes / itemsize + if (allocated(dest)) then + dim2 = size(dest) + if (dim2 > 0) then + dim1 = len(dest(1)) + endif + endif + if (dim1 .ne. itemsize .or. dim2 .ne. dim) then + if(allocated(dest)) deallocate(dest) + allocate(character(len=itemsize) :: dest(dim)) + endif + bmif_get_value_char1 = RMF_BMI_GetValue(id, trim(var)//C_NULL_CHAR, dest(1)) + return + END FUNCTION bmif_get_value_char1 + + !> \overload + INTEGER FUNCTION bmif_get_value_double(id, var, dest) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION RMF_BMI_GetValue(id, var, dest) & + BIND(C, NAME='RMF_BMI_GetValue') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + CHARACTER(KIND=C_CHAR), INTENT(in) :: var(*) + REAL(KIND=C_DOUBLE), INTENT(inout) :: dest + END FUNCTION RMF_BMI_GetValue + END INTERFACE + INTEGER, INTENT(in) :: id + CHARACTER(len=*), INTENT(in) :: var + real(kind=8), INTENT(inout) :: dest + character(100) :: vartype + integer :: bytes, nbytes, status, dim, itemsize + integer :: dim1, dim2 + dim1 = 0 + dim2 = 0 + status = bmif_get_var_type(id, var, vartype) + if (vartype .ne. "real(kind=8)") then + stop "Variable type error." + endif + bmif_get_value_double = RMF_BMI_GetValue(id, trim(var)//C_NULL_CHAR, dest) + return + END FUNCTION bmif_get_value_double + + !> \overload + INTEGER FUNCTION bmif_get_value_double1(id, var, dest) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION RMF_BMI_GetValue(id, var, dest) & + BIND(C, NAME='RMF_BMI_GetValue') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + CHARACTER(KIND=C_CHAR), INTENT(in) :: var(*) + REAL(KIND=C_DOUBLE), INTENT(inout) :: dest + END FUNCTION RMF_BMI_GetValue + END INTERFACE + INTEGER, INTENT(in) :: id + CHARACTER(len=*), INTENT(in) :: var + real(kind=8), allocatable, dimension(:), INTENT(inout) :: dest + character(100) :: vartype + integer :: nbytes, status, dim, itemsize + integer :: dim1, dim2 + dim1 = 0 + dim2 = 0 + status = bmif_get_var_type(id, var, vartype) + if (vartype .ne. "real(kind=8)") then + stop "Variable type error." + endif + status = bmif_get_var_itemsize(id, var, itemsize) + status = bmif_get_var_nbytes(id, var, nbytes) + dim = nbytes / itemsize + if (allocated(dest)) then + dim2 = size(dest) + endif + if (dim2 .ne. dim) then + if(allocated(dest)) deallocate(dest) + allocate(dest(dim)) + endif + bmif_get_value_double1 = RMF_BMI_GetValue(id, trim(var)//C_NULL_CHAR, dest(1)) + return + END FUNCTION bmif_get_value_double1 + + !> \overload + INTEGER FUNCTION bmif_get_value_double2(id, var, dest) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION RMF_BMI_GetValue(id, var, dest) & + BIND(C, NAME='RMF_BMI_GetValue') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + CHARACTER(KIND=C_CHAR), INTENT(in) :: var(*) + REAL(KIND=C_DOUBLE), INTENT(inout) :: dest + END FUNCTION RMF_BMI_GetValue + END INTERFACE + INTEGER, INTENT(in) :: id + CHARACTER(len=*), INTENT(in) :: var + real(kind=8), allocatable, INTENT(inout) :: dest(:,:) + character(100) :: vartype + character(40) :: varname + integer :: status + integer :: dim1, dim2 + logical :: need_alloc + status = bmif_get_var_type(id, var, vartype) + if (vartype .ne. "real(kind=8)") then + stop "Variable type error." + endif + varname = Lower(var) + need_alloc = .true. + if (varname .eq. "concentrations") then + dim1 = RM_GetGridCellCount(id) + dim2 = RM_GetComponentCount(id) + else if (varname .eq. "selectedoutput") then + dim1 = RM_GetSelectedOutputRowCount(id) + dim2 = RM_GetSelectedOutputColumnCount(id) + else + stop "Unknown 2d variable" + endif + if (allocated(dest)) then + if ((size(dest,1) .eq. dim1) .and. & + (size(dest,2) .eq. dim2)) then + need_alloc = .false. + else + deallocate(dest) + endif + endif + if (need_alloc) then + allocate(dest(dim1, dim2)) + endif + bmif_get_value_double2 = RMF_BMI_GetValue(id, trim(var)//C_NULL_CHAR, dest(1,1)) + return + END FUNCTION bmif_get_value_double2 + + !> \overload + INTEGER FUNCTION bmif_get_value_int(id, var, dest) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION RMF_BMI_GetValue(id, var, dest) & + BIND(C, NAME='RMF_BMI_GetValue') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + CHARACTER(KIND=C_CHAR), INTENT(in) :: var(*) + INTEGER(KIND=C_INT), INTENT(inout) :: dest + END FUNCTION RMF_BMI_GetValue + END INTERFACE + INTEGER, INTENT(in) :: id + CHARACTER(len=*), INTENT(in) :: var + integer, INTENT(inout) :: dest + character(100) :: vartype + integer :: bytes, nbytes, status, dim, itemsize + integer :: dim1, dim2 + dim1 = 0 + dim2 = 0 + status = bmif_get_var_type(id, var, vartype) + if (vartype .ne. "integer") then + stop "Variable type error." + endif + bmif_get_value_int = RMF_BMI_GetValue(id, trim(var)//C_NULL_CHAR, dest) + return + END FUNCTION bmif_get_value_int + + !> \overload + INTEGER FUNCTION bmif_get_value_int1(id, var, dest) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION RMF_BMI_GetValue(id, var, dest) & + BIND(C, NAME='RMF_BMI_GetValue') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + CHARACTER(KIND=C_CHAR), INTENT(in) :: var(*) + INTEGER(KIND=C_INT), INTENT(inout) :: dest + END FUNCTION RMF_BMI_GetValue + END INTERFACE + INTEGER, INTENT(in) :: id + CHARACTER(len=*), INTENT(in) :: var + integer, allocatable, INTENT(inout) :: dest(:) + character(100) :: vartype + integer :: nbytes, status, dim, itemsize + integer :: dim1, dim2 + dim1 = 0 + dim2 = 0 + status = bmif_get_var_type(id, var, vartype) + if (vartype .ne. "integer,allocatable,dimension(:)") then + stop "Variable type error." + endif + status = bmif_get_var_itemsize(id, var, itemsize) + status = bmif_get_var_nbytes(id, var, nbytes) + dim = nbytes / itemsize + if (allocated(dest)) then + dim2 = size(dest) + endif + if (dim2 .ne. dim) then + if(allocated(dest)) deallocate(dest) + allocate(dest(dim)) + endif + bmif_get_value_int1 = RMF_BMI_GetValue(id, trim(var)//C_NULL_CHAR, dest(1)) + return + END FUNCTION bmif_get_value_int1 + + !> \overload + INTEGER FUNCTION bmif_get_value_int2(id, var, dest) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION RMF_BMI_GetValue(id, var, dest) & + BIND(C, NAME='RMF_BMI_GetValue') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + CHARACTER(KIND=C_CHAR), INTENT(in) :: var(*) + INTEGER(KIND=C_INT), INTENT(inout) :: dest + END FUNCTION RMF_BMI_GetValue + END INTERFACE + INTEGER, INTENT(in) :: id + CHARACTER(len=*), INTENT(in) :: var + integer, allocatable, INTENT(inout) :: dest(:,:) + character(100) :: vartype + character(40) :: varname + integer :: status + integer :: dim1, dim2 + logical :: need_alloc + status = bmif_get_var_type(id, var, vartype) + if (vartype .ne. "real(kind=8)") then + stop "Variable type error." + endif + varname = Lower(varname) + need_alloc = .true. + stop "Unknown 2d variable" + bmif_get_value_int2 = RMF_BMI_GetValue(id, trim(var)//C_NULL_CHAR, dest(1,1)) + return + END FUNCTION bmif_get_value_int2 + + !> \overload + INTEGER FUNCTION bmif_get_value_ptr_double(id, var, dest) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION RMF_BMI_GetValuePtr(id, var, src) & + BIND(C, NAME='RMF_BMI_GetValuePtr') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + CHARACTER(KIND=C_CHAR), INTENT(in) :: var(*) + type (c_ptr), INTENT(inout) :: src + END FUNCTION RMF_BMI_GetValuePtr + END INTERFACE + INTEGER, INTENT(in) :: id + CHARACTER(len=*), INTENT(in) :: var + real(kind=c_double), pointer, INTENT(inout) :: dest + type (c_ptr) :: src + integer :: status + status = RMF_BMI_GetValuePtr(id, trim(var)//C_NULL_CHAR, src) + call C_F_POINTER(src, dest) + bmif_get_value_ptr_double = success(status) + return + END FUNCTION bmif_get_value_ptr_double + + !> \overload + INTEGER FUNCTION bmif_get_value_ptr_double1(id, var, dest) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION RMF_BMI_GetValuePtr(id, var, src) & + BIND(C, NAME='RMF_BMI_GetValuePtr') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + CHARACTER(KIND=C_CHAR), INTENT(in) :: var(*) + type (c_ptr), INTENT(inout) :: src + END FUNCTION RMF_BMI_GetValuePtr + END INTERFACE + INTEGER, INTENT(in) :: id + CHARACTER(len=*), INTENT(in) :: var + real(kind=c_double), pointer, INTENT(inout) :: dest(:) + type (c_ptr) :: src + integer nbytes, itemsize, dim, status + status = bmif_get_var_nbytes(id, var, nbytes) + status = bmif_get_var_itemsize(id, var, itemsize) + dim = nbytes/itemsize + status = RMF_BMI_GetValuePtr(id, trim(var)//C_NULL_CHAR, src) + call c_f_pointer(src, dest, [dim]); + bmif_get_value_ptr_double1 = success(status) + return + END FUNCTION bmif_get_value_ptr_double1 + + !> \overload + INTEGER FUNCTION bmif_get_value_ptr_integer(id, var, dest) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION RMF_BMI_GetValuePtr(id, var, src) & + BIND(C, NAME='RMF_BMI_GetValuePtr') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + CHARACTER(KIND=C_CHAR), INTENT(in) :: var(*) + type (c_ptr), INTENT(inout) :: src + END FUNCTION RMF_BMI_GetValuePtr + END INTERFACE + INTEGER, INTENT(in) :: id + CHARACTER(len=*), INTENT(in) :: var + integer, pointer, INTENT(inout) :: dest + type (c_ptr) :: src + integer status + status = RMF_BMI_GetValuePtr(id, trim(var)//C_NULL_CHAR, src) + call c_f_pointer(src, dest) + bmif_get_value_ptr_integer = success(status) + return + END FUNCTION bmif_get_value_ptr_integer + + !> \overload + INTEGER FUNCTION bmif_get_value_ptr_logical(id, var, dest) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION RMF_BMI_GetValuePtr(id, var, src) & + BIND(C, NAME='RMF_BMI_GetValuePtr') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + CHARACTER(KIND=C_CHAR), INTENT(in) :: var(*) + type (c_ptr), INTENT(inout) :: src + END FUNCTION RMF_BMI_GetValuePtr + END INTERFACE + INTEGER, INTENT(in) :: id + CHARACTER(len=*), INTENT(in) :: var + logical, pointer, INTENT(inout) :: dest + type (c_ptr) :: src + integer status + status = RMF_BMI_GetValuePtr(id, trim(var)//C_NULL_CHAR, src) + call c_f_pointer(src, dest) + bmif_get_value_ptr_logical = success(status) + return + END FUNCTION bmif_get_value_ptr_logical + + ! ==================================================== + ! Setters, by type + ! ==================================================== + + !> Basic Model Interface method that sets model variables. Only variables in the list + !> provided by @ref bmif_get_input_var_names can be set. The BMI interface to PhreeqcRM is + !> only partial, and provides only the most basic functions. The native PhreeqcRM methods + !> (those without the the RM_BMI_ + !> prefix) provide a complete interface. + !> @param id The instance id returned from @ref RM_Create. + !> @param var String defining variable to set. + !> @param src Data to use to set the variable in PhreeqcRM. + !> @retval IRM_RESULT Zero indicates success, negative indicates failure. + !> + !> Variable names for the second argument (@a var) + !> and required variable type for the third argument (@a src): + !> @n "Concentrations", real(kind=8), allocatable, dimension(:,:); + !> @n "Density", real(kind=8), allocatable, dimension(:); + !> @n "FilePrefix", character; + !> @n "NthSelectedOutput", integer; + !> @n "Porosity", real(kind=8), allocatable, dimension(:); + !> @n "Pressure", real(kind=8), allocatable, dimension(:); + !> @n "Saturation", real(kind=8), allocatable, dimension(:); + !> @n "SelectedOutputOn", logical; + !> @n "Temperature", real(kind=8), allocatable, dimension(:); + !> @n "Time", real(kind=8); + !> @n "TimeStep", real(kind=8). + !> + !> @see + !> @ref bmif_get_input_var_names, + !> @ref bmif_get_input_item_count,, + !> @ref bmif_get_value, + !> @ref bmif_get_var_itemsize, + !> @ref bmif_get_var_nbytes, + !> @ref bmif_get_var_type, + !> @ref bmif_get_var_units. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> real(kind=8), allocatable, dimension(:) :: tc
+    !> allocate(tc(nxyz))
+    !> tc = 28.0d0
+    !> status = bmif_set_value(id, "Temperature", tc);
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref MpiWorker. + !> \overload + INTEGER FUNCTION bmif_set_value_b(id, var, src) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION RMF_BMI_SetValue(id, var, src) & + BIND(C, NAME='RMF_BMI_SetValue') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + CHARACTER(KIND=C_CHAR), INTENT(in) :: var(*) + LOGICAL(KIND=C_INT), INTENT(in) :: src + END FUNCTION RMF_BMI_SetValue + END INTERFACE + INTEGER, INTENT(in) :: id + CHARACTER(len=*), INTENT(in) :: var + LOGICAL(kind=4), INTENT(in) :: src + character(100) :: vartype + integer :: bytes, nbytes, status, dim + status = bmif_get_var_type(id, var, vartype) + if (vartype .ne. "logical") then + stop "Variable type error." + endif + bmif_set_value_b = RMF_BMI_SetValue(id, trim(var)//C_NULL_CHAR, src) + return + END FUNCTION bmif_set_value_b + + !> \overload + INTEGER FUNCTION bmif_set_value_c(id, var, src) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION RMF_BMI_SetValue(id, var, src) & + BIND(C, NAME='RMF_BMI_SetValue') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + CHARACTER(KIND=C_CHAR), INTENT(in) :: var(*) + CHARACTER(KIND=C_CHAR), INTENT(in) :: src + END FUNCTION RMF_BMI_SetValue + END INTERFACE + INTEGER, INTENT(in) :: id + CHARACTER(len=*), INTENT(in) :: var + CHARACTER(len=*), INTENT(in) :: src + character(100) :: vartype + integer :: bytes, nbytes, status, dim + status = bmif_get_var_type(id, var, vartype) + if (vartype .ne. "character") then + stop "Variable type error." + endif + bmif_set_value_c = RMF_BMI_SetValue(id, trim(var)//C_NULL_CHAR, trim(src)//C_NULL_CHAR) + return + END FUNCTION bmif_set_value_c + + !> \overload + INTEGER FUNCTION bmif_set_value_int(id, var, src) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION RMF_BMI_SetValue(id, var, src) & + BIND(C, NAME='RMF_BMI_SetValue') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + CHARACTER(KIND=C_CHAR), INTENT(in) :: var(*) + INTEGER(KIND=C_INT), INTENT(inout) :: src + END FUNCTION RMF_BMI_SetValue + END INTERFACE + INTEGER, INTENT(in) :: id + CHARACTER(len=*), INTENT(in) :: var + integer, INTENT(inout) :: src + character(100) :: vartype + integer :: bytes, nbytes, status, dim + status = bmif_get_var_type(id, var, vartype) + if (vartype .ne. "integer") then + stop "Variable type error." + endif + if (var .eq. "NthSelectedOutput") src = src - 1 + bmif_set_value_int = RMF_BMI_SetValue(id, trim(var)//C_NULL_CHAR, src) + if (var .eq. "NthSelectedOutput") src = src + 1 + return + END FUNCTION bmif_set_value_int + + !> \overload + INTEGER FUNCTION bmif_set_value_int1(id, var, src) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION RMF_BMI_SetValue(id, var, src) & + BIND(C, NAME='RMF_BMI_SetValue') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + CHARACTER(KIND=C_CHAR), INTENT(in) :: var(*) + INTEGER(KIND=C_INT), INTENT(inout) :: src + END FUNCTION RMF_BMI_SetValue + END INTERFACE + INTEGER, INTENT(in) :: id + CHARACTER(len=*), INTENT(in) :: var + integer, INTENT(inout) :: src(:) + character(100) :: vartype + integer :: nbytes, status, dim, itemsize + status = bmif_get_var_type(id, var, vartype) + if (vartype .ne. "integer,allocatable,dimension(:)") then + stop "Variable type error." + endif + status = bmif_get_var_nbytes(id, var, nbytes) + status = bmif_get_var_itemsize(id, var, itemsize) + dim = nbytes / itemsize + if (dim .ne. size(src)) then + stop "Variable dimension error" + endif + bmif_set_value_int1 = RMF_BMI_SetValue(id, trim(var)//C_NULL_CHAR, src(1)) + return + END FUNCTION bmif_set_value_int1 + + !> \overload + INTEGER FUNCTION bmif_set_value_int2(id, var, src) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION RMF_BMI_SetValue(id, var, src) & + BIND(C, NAME='RMF_BMI_SetValue') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + CHARACTER(KIND=C_CHAR), INTENT(in) :: var(*) + INTEGER(KIND=C_INT), INTENT(inout) :: src + END FUNCTION RMF_BMI_SetValue + END INTERFACE + integer, INTENT(in) :: id + CHARACTER(len=*), INTENT(in) :: var + integer, INTENT(inout) :: src(:,:) + character(100) :: vartype + integer :: nbytes, status, dim, itemsize + status = bmif_get_var_type(id, var, vartype) + if (vartype .ne. "integer,allocatable,dimension(:,:)") then + stop "Variable type error." + endif + status = bmif_get_var_nbytes(id, var, nbytes) + status = bmif_get_var_itemsize(id, var, itemsize) + dim = nbytes / itemsize + if (dim .ne. size(src,1)*size(src,2)) then + stop "Variable dimension error" + endif + bmif_set_value_int2 = RMF_BMI_SetValue(id, trim(var)//C_NULL_CHAR, src(1,1)) + return + END FUNCTION bmif_set_value_int2 + + !> \overload + INTEGER FUNCTION bmif_set_value_double(id, var, src) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION RMF_BMI_SetValue(id, var, src) & + BIND(C, NAME='RMF_BMI_SetValue') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + CHARACTER(KIND=C_CHAR), INTENT(in) :: var(*) + REAL(KIND=C_DOUBLE), INTENT(inout) :: src + END FUNCTION RMF_BMI_SetValue + END INTERFACE + INTEGER, INTENT(in) :: id + CHARACTER(len=*), INTENT(in) :: var + real(kind=8), INTENT(inout) :: src + character(100) :: vartype + integer :: bytes, nbytes, status, dim + status = bmif_get_var_type(id, var, vartype) + if (vartype .ne. "real(kind=8)") then + stop "Variable type error." + endif + bmif_set_value_double = RMF_BMI_SetValue(id, trim(var)//C_NULL_CHAR, src) + return + END FUNCTION bmif_set_value_double + + !> \overload + INTEGER FUNCTION bmif_set_value_double1(id, var, src) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION RMF_BMI_SetValue(id, var, src) & + BIND(C, NAME='RMF_BMI_SetValue') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + CHARACTER(KIND=C_CHAR), INTENT(in) :: var(*) + REAL(KIND=C_DOUBLE), INTENT(inout) :: src + END FUNCTION RMF_BMI_SetValue + END INTERFACE + INTEGER, INTENT(in) :: id + CHARACTER(len=*), INTENT(in) :: var + real(kind=8), INTENT(inout) :: src(:) + character(100) :: vartype + integer :: nbytes, status, dim, itemsize + status = bmif_get_var_type(id, var, vartype) + if (vartype .ne. "real(kind=8)") then + stop "Variable type error." + endif + status = bmif_get_var_nbytes(id, var, nbytes) + status = bmif_get_var_itemsize(id, var, itemsize) + dim = nbytes / itemsize + if (dim .ne. size(src)) then + stop "Variable dimension error" + endif + bmif_set_value_double1 = RMF_BMI_SetValue(id, trim(var)//C_NULL_CHAR, src(1)) + return + END FUNCTION bmif_set_value_double1 + + !> \overload + INTEGER FUNCTION bmif_set_value_double2(id, var, src) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION RMF_BMI_SetValue(id, var, src) & + BIND(C, NAME='RMF_BMI_SetValue') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + CHARACTER(KIND=C_CHAR), INTENT(in) :: var(*) + REAL(KIND=C_DOUBLE), INTENT(inout) :: src + END FUNCTION RMF_BMI_SetValue + END INTERFACE + integer, INTENT(in) :: id + CHARACTER(len=*), INTENT(in) :: var + real(kind=8), INTENT(inout) :: src(:,:) + character(100) :: vartype + integer :: nbytes, status, dim, itemsize + status = bmif_get_var_type(id, var, vartype) + if (vartype .ne. "real(kind=8)") then + stop "Variable type error." + endif + status = bmif_get_var_nbytes(id, var, nbytes) + status = bmif_get_var_itemsize(id, var, itemsize) + dim = nbytes / itemsize + if (dim .ne. size(src,1)*size(src,2)) then + stop "Variable dimension error" + endif + bmif_set_value_double2 = RMF_BMI_SetValue(id, trim(var)//C_NULL_CHAR, src(1,1)) + return + END FUNCTION bmif_set_value_double2 + + ! ==================================================== + ! Grid information + ! ==================================================== + + INTEGER FUNCTION bmif_grid_rank(id, grid, rank) + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER, INTENT(in) :: id, grid + INTEGER, INTENT(inout) :: rank + if (grid .eq. 0) then + rank = 1 + bmif_grid_rank = BMI_SUCCESS + else + rank = 0 + bmif_grid_rank = BMI_FAILURE + endif + END FUNCTION bmif_grid_rank + + INTEGER FUNCTION bmif_grid_size(id, grid, ngrid) + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER, INTENT(in) :: id, grid + INTEGER, INTENT(inout) :: ngrid + if (grid .eq. 0) then + bmif_grid_size = success(bmif_get_value(id, "GridCellCount", ngrid)) + else + ngrid = 0 + bmif_grid_size = BMI_FAILURE + endif + END FUNCTION bmif_grid_size + + INTEGER FUNCTION bmif_grid_type(id, grid, str) + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER, INTENT(in) :: id, grid + CHARACTER(len=*), INTENT(inout) :: str + if (grid .eq. 1) then + str = "points" + bmif_grid_type = BMI_SUCCESS + else + str = "" + bmif_grid_type = BMI_FAILURE + endif + END FUNCTION bmif_grid_type + + ! ==================================================== + ! Functions not implemented + ! ==================================================== + + INCLUDE "BMI_not_implemented.inc" + + ! ==================================================== + ! Utility functions + ! ==================================================== + + FUNCTION Lower(s1) RESULT (s2) + CHARACTER(*) :: s1 + CHARACTER(LEN(s1)) :: s2 + CHARACTER :: ch + INTEGER,PARAMETER :: DUC = ICHAR('A') - ICHAR('a') + INTEGER :: i + + DO i = 1,LEN(s1) + ch = s1(i:i) + IF (ch >= 'A'.AND.ch <= 'Z') ch = CHAR(ICHAR(ch)-DUC) + s2(i:i) = ch + END DO + END FUNCTION Lower + + INTEGER FUNCTION SUCCESS(i) + implicit none + integer, intent(in) :: i + success = BMI_FAILURE + if (i .ge. 0) success = BMI_SUCCESS + END FUNCTION SUCCESS + + END MODULE BMIPhreeqcRM diff --git a/src/BMI_interface_F.cpp b/src/BMI_interface_F.cpp new file mode 100644 index 000000000..4f4ca71d0 --- /dev/null +++ b/src/BMI_interface_F.cpp @@ -0,0 +1,429 @@ +#ifdef USE_MPI +#include "mpi.h" +#endif +#include "BMI_Var.h" +#include "BMIPhreeqcRM.h" +//#include "RM_interface_F.h" +#include "BMI_interface_F.h" +#include "IPhreeqcPhastLib.h" +#include "Phreeqc.h" +#include "PHRQ_io.h" +#include "BMI_Var.h" +#include +#include +#include +#include +static void +rmpadfstring(char* dest, const char* src, unsigned int len) +{ + size_t sofar; + + for (sofar = 0; (sofar < len) && (*src != '\0'); ++sofar) + *dest++ = *src++; + + while (sofar++ < len) + *dest++ = ' '; +} +#ifdef USE_MPI +/* ---------------------------------------------------------------------- */ +int +RM_BMI_Create(int* nxyz, int* nthreads) +/* ---------------------------------------------------------------------- */ +{ + // + // Creates reaction module, called by root and MPI workers + // + return BMIPhreeqcRM::CreateBMIModule(*nxyz, MPI_Comm_f2c(*nthreads)); +} +#else +/* ---------------------------------------------------------------------- */ +int +RM_BMI_Create(int* nxyz, int* nthreads) +/* ---------------------------------------------------------------------- */ +{ + // + // Creates reaction module, called by root and MPI workers + // + return BMIPhreeqcRM::CreateBMIModule(*nxyz, *nthreads); +} +#endif +/* ---------------------------------------------------------------------- */ +IRM_RESULT +RMF_BMI_GetComponentName(int* id, char* chem_name, int* l1) +/* ---------------------------------------------------------------------- */ +{ + // Returns "PhreeqcRM" + BMIPhreeqcRM* bmirm_ptr = BMIPhreeqcRM::GetInstance(*id); + if (bmirm_ptr) + { + if (chem_name != NULL) + { + if (*l1 > 0) + { + rmpadfstring(chem_name, bmirm_ptr->GetComponentName().c_str(), (unsigned int)*l1); + return IRM_OK; + } + } + return IRM_INVALIDARG; + } + return IRM_BADINSTANCE; +} +/* ---------------------------------------------------------------------- */ +double +RMF_BMI_GetCurrentTime(int* id) +/* ---------------------------------------------------------------------- */ +{ + // Retrieves current simulation time, in seconds + BMIPhreeqcRM* bmirm_ptr = BMIPhreeqcRM::GetInstance(*id); + if (bmirm_ptr) + { + return bmirm_ptr->GetTime(); + } + return IRM_BADINSTANCE; +} +/* ---------------------------------------------------------------------- */ +double +RMF_BMI_GetEndTime(int* id) +/* ---------------------------------------------------------------------- */ +{ + // Retrieves current simulation time, in seconds + BMIPhreeqcRM* bmirm_ptr = BMIPhreeqcRM::GetInstance(*id); + if (bmirm_ptr) + { + return bmirm_ptr->GetEndTime(); + } + return IRM_BADINSTANCE; +} +/* ---------------------------------------------------------------------- */ +int +RMF_BMI_GetInputItemCount(int* id) +/* ---------------------------------------------------------------------- */ +{ + // Retrieves number of variables that can be set + BMIPhreeqcRM* bmirm_ptr = BMIPhreeqcRM::GetInstance(*id); + if (bmirm_ptr) + { + return bmirm_ptr->GetInputItemCount(); + } + return IRM_BADINSTANCE; +} + +/* ---------------------------------------------------------------------- */ +int +RMF_BMI_GetOutputItemCount(int* id) +/* ---------------------------------------------------------------------- */ +{ + // Retrieves number of variables that can be retrieved + BMIPhreeqcRM* bmirm_ptr = BMIPhreeqcRM::GetInstance(*id); + if (bmirm_ptr) + { + return bmirm_ptr->GetOutputItemCount(); + } + return IRM_BADINSTANCE; +} +/* ---------------------------------------------------------------------- */ +int +RMF_BMI_GetPointableItemCount(int* id) +/* ---------------------------------------------------------------------- */ +{ + // Retrieves number of variables that can be retrieved + BMIPhreeqcRM* bmirm_ptr = BMIPhreeqcRM::GetInstance(*id); + if (bmirm_ptr) + { + return bmirm_ptr->GetPointableItemCount(); + } + return IRM_BADINSTANCE; +} +/* ---------------------------------------------------------------------- */ +int +RMF_BMI_GetNamesSize(int* id, const char* type, int* dest) +/* ---------------------------------------------------------------------- */ +{ + // Retrieves number of variables that can be retrieved + BMIPhreeqcRM* bmirm_ptr = BMIPhreeqcRM::GetInstance(*id); + if (bmirm_ptr) + { + std::vector v; + std::string stype = type; + if (stype == "inputvarnames") + { + v = bmirm_ptr->GetInputVarNames(); + } + if (stype == "outputvarnames") + { + v = bmirm_ptr->GetOutputVarNames(); + } + if (stype == "pointablevarnames") + { + v = bmirm_ptr->GetPointableVarNames(); + } + int size = 0; + for (size_t i = 0; i < v.size(); i++) + { + if (v[i].size() > size) size = v[i].size(); + } + memcpy(dest, &size, sizeof(int)); + return IRM_OK; + } + return IRM_BADINSTANCE; +} +/* ---------------------------------------------------------------------- */ +int +RMF_BMI_GetNames(int* id, const char* type, char* dest) +/* ---------------------------------------------------------------------- */ +{ + // Retrieves number of variables that can be retrieved + BMIPhreeqcRM* bmirm_ptr = BMIPhreeqcRM::GetInstance(*id); + std::string stype = type; + if (bmirm_ptr) + { + std::vector v; + if (stype == "inputvarnames") + { + v = bmirm_ptr->GetInputVarNames(); + } + if (stype == "outputvarnames") + { + v = bmirm_ptr->GetOutputVarNames(); + } + if (stype == "pointablevarnames") + { + v = bmirm_ptr->GetPointableVarNames(); + } + int size = 0; + for (size_t i = 0; i < v.size(); i++) + { + if (v[i].size() > size) size = v[i].size(); + } + int itemsize = size; + std::stringstream all; + for (size_t i = 0; i < v.size(); i++) + { + all << std::left << std::setfill(' ') << std::setw(itemsize) << v[i]; + } + memcpy( dest, all.str().data(), all.str().size()); + return IRM_OK; + } + return IRM_BADINSTANCE; +} +/* ---------------------------------------------------------------------- */ +double +RMF_BMI_GetTimeStep(int* id) +/* ---------------------------------------------------------------------- */ +{ + // Retrieves current time step, in seconds + BMIPhreeqcRM* bmirm_ptr = BMIPhreeqcRM::GetInstance(*id); + if (bmirm_ptr) + { + return bmirm_ptr->GetTimeStep(); + } + return IRM_BADINSTANCE; +} +/* ---------------------------------------------------------------------- */ +IRM_RESULT +RMF_BMI_GetTimeUnits(int* id, char* units, int* l1) +/* ---------------------------------------------------------------------- */ +{ + // Returns time units + BMIPhreeqcRM* bmirm_ptr = BMIPhreeqcRM::GetInstance(*id); + if (bmirm_ptr) + { + if (units != NULL) + { + if (*l1 > 0) + { + rmpadfstring(units, bmirm_ptr->GetTimeUnits().c_str(), (unsigned int)*l1); + return IRM_OK; + } + } + return IRM_INVALIDARG; + } + return IRM_BADINSTANCE; +} +/* ---------------------------------------------------------------------- */ +IRM_RESULT +RMF_BMI_GetValue(int* id, char* var, void* dest) +/* ---------------------------------------------------------------------- */ +{ + // Returns value(s) for var + BMIPhreeqcRM* bmirm_ptr = BMIPhreeqcRM::GetInstance(*id); + if (bmirm_ptr) + { + if (var != NULL) + { + std::string str_var = var; + size_t end = str_var.find_last_not_of(' '); + str_var = (end == std::string::npos) ? "" : str_var.substr(0, end + 1); + std::string type = bmirm_ptr->GetVarType(var); + bmirm_ptr->GetValue(str_var, dest); + return IRM_OK; + } + return IRM_INVALIDARG; + } + return IRM_BADINSTANCE; +} +/* ---------------------------------------------------------------------- */ +IRM_RESULT +RMF_BMI_GetValuePtr(int* id, char* var, void*& dest) +/* ---------------------------------------------------------------------- */ +{ + // Returns value(s) for var + BMIPhreeqcRM* bmirm_ptr = BMIPhreeqcRM::GetInstance(*id); + if (bmirm_ptr) + { + if (var != NULL) + { + std::string str_var = var; + size_t end = str_var.find_last_not_of(' '); + str_var = (end == std::string::npos) ? "" : str_var.substr(0, end + 1); + std::string type = bmirm_ptr->GetVarType(var); + dest = bmirm_ptr->GetValuePtr(str_var); + return IRM_OK; + } + return IRM_INVALIDARG; + } + return IRM_BADINSTANCE; +} +/* ---------------------------------------------------------------------- */ +int +RMF_BMI_GetVarItemsize(int* id, char* var) +/* ---------------------------------------------------------------------- */ +{ + // Retrieves number of bytes needed for one item + BMIPhreeqcRM* bmirm_ptr = BMIPhreeqcRM::GetInstance(*id); + if (bmirm_ptr) + { + std::string str_var = var; + size_t end = str_var.find_last_not_of(' '); + str_var = (end == std::string::npos) ? "" : str_var.substr(0, end + 1); + return bmirm_ptr->GetVarItemsize(str_var); + } + return IRM_BADINSTANCE; +} +/* ---------------------------------------------------------------------- */ +int +RMF_BMI_GetVarNbytes(int* id, char* var) +/* ---------------------------------------------------------------------- */ +{ + // Retrieves number total number of bytes needed for the buffer + BMIPhreeqcRM* bmirm_ptr = BMIPhreeqcRM::GetInstance(*id); + if (bmirm_ptr) + { + std::string str_var = var; + size_t end = str_var.find_last_not_of(' '); + str_var = (end == std::string::npos) ? "" : str_var.substr(0, end + 1); + return bmirm_ptr->GetVarNbytes(str_var); + } + return IRM_BADINSTANCE; +} +/* ---------------------------------------------------------------------- */ +IRM_RESULT +RMF_BMI_GetVarType(int* id, char* var, char* vtype, int* l1) +/* ---------------------------------------------------------------------- */ +{ + // Returns type of variable var + BMIPhreeqcRM* bmirm_ptr = BMIPhreeqcRM::GetInstance(*id); + if (bmirm_ptr) + { + std::string str_var = var; + size_t end = str_var.find_last_not_of(' '); + str_var = (end == std::string::npos) ? "" : str_var.substr(0, end + 1); + std::string type_cpp = bmirm_ptr->GetVarType(str_var); + if (*l1 > 0) + { + rmpadfstring(vtype, type_cpp.c_str(), (unsigned int)*l1); + return IRM_OK; + } + return IRM_INVALIDARG; + } + return IRM_BADINSTANCE; +} + +/* ---------------------------------------------------------------------- */ +IRM_RESULT +RMF_BMI_GetVarUnits(int* id, char* var, char* units, int* l1) +/* ---------------------------------------------------------------------- */ +{ + // Returns units of variable var + BMIPhreeqcRM* bmirm_ptr = BMIPhreeqcRM::GetInstance(*id); + if (bmirm_ptr) + { + std::string str_var = var; + size_t end = str_var.find_last_not_of(' '); + str_var = (end == std::string::npos) ? "" : str_var.substr(0, end + 1); + std::string units_cpp = bmirm_ptr->GetVarUnits(str_var); + if (*l1 > 0) + { + rmpadfstring(units, units_cpp.c_str(), (unsigned int)*l1); + return IRM_OK; + } + return IRM_INVALIDARG; + } + return IRM_BADINSTANCE; +} +#ifdef USE_YAML +/* ---------------------------------------------------------------------- */ +IRM_RESULT +RMF_BMI_Initialize(int* id, char* config_file) +/* ---------------------------------------------------------------------- */ +{ + // Returns units of variable var + BMIPhreeqcRM* bmirm_ptr = BMIPhreeqcRM::GetInstance(*id); + if (bmirm_ptr) + { + bmirm_ptr->Initialize(config_file); + return IRM_OK; + } + return IRM_BADINSTANCE; +} +#endif +/* ---------------------------------------------------------------------- */ +IRM_RESULT +RMF_BMI_SetValue(int* id, char* var, void* src) +/* ---------------------------------------------------------------------- */ +{ + // Returns value(s) for var + BMIPhreeqcRM* bmirm_ptr = BMIPhreeqcRM::GetInstance(*id); + if (bmirm_ptr) + { + if (var != NULL) + { + std::string str_var = var; + size_t end = str_var.find_last_not_of(' '); + str_var = (end == std::string::npos) ? "" : str_var.substr(0, end + 1); + bmirm_ptr->SetValue(str_var, src); + return IRM_OK; + } + return IRM_INVALIDARG; + } + return IRM_BADINSTANCE; +} +// IRM_RESULT RMF_BMI_Update(int* id); +/* ---------------------------------------------------------------------- */ +IRM_RESULT +RMF_BMI_Update(int* id) +/* ---------------------------------------------------------------------- */ +{ + // Returns units of variable var + BMIPhreeqcRM* bmirm_ptr = BMIPhreeqcRM::GetInstance(*id); + if (bmirm_ptr) + { + bmirm_ptr->Update(); + return IRM_OK; + } + return IRM_BADINSTANCE; +} +/* ---------------------------------------------------------------------- */ +IRM_RESULT +RMF_BMI_UpdateUntil(int* id, double* time) +/* ---------------------------------------------------------------------- */ +{ + // Returns units of variable var + BMIPhreeqcRM* bmirm_ptr = BMIPhreeqcRM::GetInstance(*id); + if (bmirm_ptr) + { + bmirm_ptr->UpdateUntil(*time); + return IRM_OK; + } + return IRM_BADINSTANCE; +} \ No newline at end of file diff --git a/src/BMI_interface_F.h b/src/BMI_interface_F.h new file mode 100644 index 000000000..77e67913a --- /dev/null +++ b/src/BMI_interface_F.h @@ -0,0 +1,42 @@ +///*! @file BMI_interface_F.h +// @brief C/Fortran Documentation +//*/ +#if !defined(BMI_INTERFACE_F_H_INCLUDED) +#define BMI_INTERFACE_F_H_INCLUDED +#include "IrmResult.h" +#if defined(_WINDLL) +#define IRM_DLL_EXPORT __declspec(dllexport) +#else +#define IRM_DLL_EXPORT +#endif + +#if defined(__cplusplus) +extern "C" { +#endif + IRM_DLL_EXPORT int RM_BMI_Create(int* nxyz, int* nthreads = NULL); + IRM_DLL_EXPORT IRM_RESULT RMF_BMI_GetComponentName(int* id, char* chem_name, int* l1); + IRM_DLL_EXPORT double RMF_BMI_GetCurrentTime(int* id); + IRM_DLL_EXPORT double RMF_BMI_GetEndTime(int* id); + IRM_DLL_EXPORT int RMF_BMI_GetInputItemCount(int* id); + IRM_DLL_EXPORT int RMF_BMI_GetNames(int* id, const char* type, char* dest); + IRM_DLL_EXPORT int RMF_BMI_GetNamesSize(int* id, const char* type, int* dest); + IRM_DLL_EXPORT int RMF_BMI_GetOutputItemCount(int* id); + IRM_DLL_EXPORT int RMF_BMI_GetPointableItemCount(int* id); + IRM_DLL_EXPORT double RMF_BMI_GetTimeStep(int* id); + IRM_DLL_EXPORT IRM_RESULT RMF_BMI_GetTimeUnits(int* id, char* units, int* l1); + IRM_DLL_EXPORT IRM_RESULT RMF_BMI_GetValue(int* id, char* name, void* dest); + IRM_DLL_EXPORT IRM_RESULT RMF_BMI_GetValuePtr(int* id, char* var, void*& dest); + IRM_DLL_EXPORT int RMF_BMI_GetVarItemsize(int* id, char* name); + IRM_DLL_EXPORT int RMF_BMI_GetVarNbytes(int* id, char* name); + IRM_DLL_EXPORT IRM_RESULT RMF_BMI_GetVarType(int* id, char* name, char* vtype, int* l1); + IRM_DLL_EXPORT IRM_RESULT RMF_BMI_GetVarUnits(int* id, char* name, char* units, int* l1); + IRM_DLL_EXPORT IRM_RESULT RMF_BMI_Initialize(int* id, char* config_file); + IRM_DLL_EXPORT IRM_RESULT RMF_BMI_SetValue(int* id, char* name, void* src); + IRM_DLL_EXPORT IRM_RESULT RMF_BMI_Update(int* id); + IRM_DLL_EXPORT IRM_RESULT RMF_BMI_UpdateUntil(int* id, double* time); + +#if defined(__cplusplus) +} +#endif + +#endif // BMI_INTERFACE_F_H_INCLUDED diff --git a/src/BMI_methods.cpp b/src/BMI_methods.cpp index ca89a90e0..60ad0466d 100644 --- a/src/BMI_methods.cpp +++ b/src/BMI_methods.cpp @@ -14,12 +14,15 @@ #ifdef USE_YAML #include "yaml-cpp/yaml.h" #endif + void PhreeqcRM::BMI_SetValue(std::string name, void* src) { - std::map < std::string, BMI_Var >::iterator it = this->bmi_var_map.find(name); + std::string name_lc = name; + std::transform(name_lc.begin(), name_lc.end(), name_lc.begin(), tolower); + std::map < std::string, BMI_Var >::iterator it = this->bmi_var_map.find(name_lc); if (it != bmi_var_map.end()) { - if (it->first == "Concentrations") + if (it->first == "concentrations") { int ngrid = this->GetGridCellCount(); int ncomps = this->GetComponentCount(); @@ -28,7 +31,7 @@ void PhreeqcRM::BMI_SetValue(std::string name, void* src) this->SetConcentrations(conc); return; } - if (it->first == "Density") + if (it->first == "density") { int ngrid = this->GetGridCellCount(); std::vector density(ngrid, INACTIVE_CELL_VALUE); @@ -36,15 +39,21 @@ void PhreeqcRM::BMI_SetValue(std::string name, void* src) this->SetDensity(density); return; } - if (it->first == "NthSelectedOutput") + if (it->first == "fileprefix") + { + std::string file = (char*)src; + this->SetFilePrefix(file); + return; + } + if (it->first == "nthselectedoutput") { int nth_so; memcpy(&nth_so, src, sizeof(int)); - int nuser = this->GetNthSelectedOutputUserNumber(nth_so); + int nuser = this->GetNthSelectedOutputUserNumber(nth_so - 1); this->SetCurrentSelectedOutputUserNumber(nuser); return; } - if (it->first == "Porosity") + if (it->first == "porosity") { int ngrid = this->GetGridCellCount(); std::vector porosity(ngrid, INACTIVE_CELL_VALUE); @@ -52,7 +61,15 @@ void PhreeqcRM::BMI_SetValue(std::string name, void* src) this->SetPorosity(porosity); return; } - if (it->first == "Pressure") + if (it->first == "porosity") + { + int ngrid = this->GetGridCellCount(); + std::vector porosity(ngrid, INACTIVE_CELL_VALUE); + memcpy(porosity.data(), src, ngrid * sizeof(double)); + this->SetPorosity(porosity); + return; + } + if (it->first == "pressure") { int ngrid = this->GetGridCellCount(); std::vector pressure(ngrid, INACTIVE_CELL_VALUE); @@ -60,7 +77,7 @@ void PhreeqcRM::BMI_SetValue(std::string name, void* src) this->SetPressure(pressure); return; } - if (it->first == "Saturation") + if (it->first == "saturation") { int ngrid = this->GetGridCellCount(); std::vector sat(ngrid, INACTIVE_CELL_VALUE); @@ -68,7 +85,7 @@ void PhreeqcRM::BMI_SetValue(std::string name, void* src) this->SetSaturation(sat); return; } - if (it->first == "SelectedOutputOn") + if (it->first == "selectedoutputon") { int so_on; memcpy(&so_on, src, sizeof(int)); @@ -76,7 +93,7 @@ void PhreeqcRM::BMI_SetValue(std::string name, void* src) this->SetSelectedOutputOn(so_on_bool); return; } - if (it->first == "Temperature") + if (it->first == "temperature") { int ngrid = this->GetGridCellCount(); std::vector temp(ngrid, INACTIVE_CELL_VALUE); @@ -84,37 +101,409 @@ void PhreeqcRM::BMI_SetValue(std::string name, void* src) this->SetTemperature(temp); return; } - if (it->first == "Time") + if (it->first == "time") { double time; memcpy(&time, src, sizeof(double)); this->SetTime(time); return; } - if (it->first == "TimeStep") + if (it->first == "timestep") { - double timestep=0; + double timestep = 0; memcpy(×tep, src, sizeof(double)); this->SetTimeStep(timestep); return; } } - //throw LetItThrow("Item not found"); ErrorMessage("Item not found"); throw PhreeqcRMStop(); } + +void PhreeqcRM::BMI_SetValue(std::string name, bool& src) +{ + std::string name_lc = name; + std::transform(name_lc.begin(), name_lc.end(), name_lc.begin(), tolower); + std::map < std::string, BMI_Var >::iterator it = this->bmi_var_map.find(name_lc); + if (it != bmi_var_map.end()) + { + + if (it->first == "selectedoutputon") + { + this->SetSelectedOutputOn(src); + return; + } + } + ErrorMessage("Item not found for BMI_SetValue with bool argument."); + throw PhreeqcRMStop(); +} +void PhreeqcRM::BMI_SetValue(std::string name, double& src) +{ + std::string name_lc = name; + std::transform(name_lc.begin(), name_lc.end(), name_lc.begin(), tolower); + std::map < std::string, BMI_Var >::iterator it = this->bmi_var_map.find(name_lc); + if (it != bmi_var_map.end()) + { + + if (it->first == "time") + { + this->SetTime(src); + return; + } + if (it->first == "timestep") + { + this->SetTimeStep(src); + return; + } + } + ErrorMessage("Item not found for BMI_SetValue with double argument."); + throw PhreeqcRMStop(); +} +void PhreeqcRM::BMI_SetValue(const std::string name, int& src) +{ + std::string name_lc = name; + std::transform(name_lc.begin(), name_lc.end(), name_lc.begin(), tolower); + std::map < std::string, BMI_Var >::iterator it = this->bmi_var_map.find(name_lc); + if (it != bmi_var_map.end()) + { + if (it->first == "nthselectedoutput") + { + this->SetNthSelectedOutput(src); + return; + } + } + ErrorMessage("Item not found for BMI_SetValue with int argument."); + throw PhreeqcRMStop(); +} + +void PhreeqcRM::BMI_SetValue(std::string name, const std::string& src) +{ + std::string name_lc = name; + std::transform(name_lc.begin(), name_lc.end(), name_lc.begin(), tolower); + std::map < std::string, BMI_Var >::iterator it = this->bmi_var_map.find(name_lc); + if (it != bmi_var_map.end()) + { + if (it->first == "fileprefix") + { + this->SetFilePrefix(src); + return; + } + } + ErrorMessage("Item not found for BMI_SetValue with std::string argument."); + throw PhreeqcRMStop(); +} +void PhreeqcRM::BMI_SetValue(std::string name, std::vector< double >& src) +{ + std::string name_lc = name; + std::transform(name_lc.begin(), name_lc.end(), name_lc.begin(), tolower); + std::map < std::string, BMI_Var >::iterator it = this->bmi_var_map.find(name_lc); + if (it != bmi_var_map.end()) + { + if (it->first == "concentrations") + { + int ngrid = this->GetGridCellCount(); + int ncomps = this->GetComponentCount(); + if ((int)src.size() != ngrid * ncomps) + { + ErrorMessage("Dimension error for concentration vector."); + } + this->SetConcentrations(src); + return; + } + if (it->first == "density") + { + int ngrid = this->GetGridCellCount(); + if ((int)src.size() != ngrid ) + { + ErrorMessage("Dimension error for density vector."); + } + this->SetDensity(src); + return; + } + + if (it->first == "porosity") + { + int ngrid = this->GetGridCellCount(); + if ((int)src.size() != ngrid) + { + ErrorMessage("Dimension error for porosity vector."); + } + this->SetPorosity(src); + return; + } + if (it->first == "pressure") + { + int ngrid = this->GetGridCellCount(); + if ((int)src.size() != ngrid) + { + ErrorMessage("Dimension error for pressure vector."); + } + this->SetPressure(src); + return; + } + if (it->first == "saturation") + { + int ngrid = this->GetGridCellCount(); + if ((int)src.size() != ngrid) + { + ErrorMessage("Dimension error for saturation vector."); + } + this->SetSaturation(src); + return; + } + if (it->first == "temperature") + { + int ngrid = this->GetGridCellCount(); + if ((int)src.size() != ngrid) + { + ErrorMessage("Dimension error for temperature vector."); + } + this->SetTemperature(src); + return; + } + } + ErrorMessage("Item not found for BMI_SetValue with std::vector < double > argument."); + throw PhreeqcRMStop(); +} + +void PhreeqcRM::BMI_SetValue(std::string name, std::vector< int>& src) +{ + std::string name_lc = name; + std::transform(name_lc.begin(), name_lc.end(), name_lc.begin(), tolower); + std::map < std::string, BMI_Var >::iterator it = this->bmi_var_map.find(name_lc); + if (it != bmi_var_map.end()) + { + } + ErrorMessage("Item not found for BMI_SetValue with std::vector < int > argument."); + throw PhreeqcRMStop(); +} + +void PhreeqcRM::BMI_SetValue(std::string name, std::vector& src) +{ + std::string name_lc = name; + std::transform(name_lc.begin(), name_lc.end(), name_lc.begin(), tolower); + std::map < std::string, BMI_Var >::iterator it = this->bmi_var_map.find(name_lc); + if (it != bmi_var_map.end()) + { + } + ErrorMessage("Item not found for BMI_SetValue with std::vector < std::string > argument."); + throw PhreeqcRMStop(); +} + +void PhreeqcRM::BMI_GetValue(std::string name, bool& dest) +{ + std::string name_lc = name; + std::transform(name_lc.begin(), name_lc.end(), name_lc.begin(), tolower); + std::map < std::string, BMI_Var >::iterator it = this->bmi_var_map.find(name_lc); + if (it != bmi_var_map.end()) + { + + if (it->first == "selectedoutputon") + { + dest = this->GetSelectedOutputOn(); + return; + } + } + ErrorMessage("Item not found for BMI_GetValue with bool argument."); + throw PhreeqcRMStop(); +} +void PhreeqcRM::BMI_GetValue(std::string name, double& dest) +{ + std::string name_lc = name; + std::transform(name_lc.begin(), name_lc.end(), name_lc.begin(), tolower); + std::map < std::string, BMI_Var >::iterator it = this->bmi_var_map.find(name_lc); + if (it != bmi_var_map.end()) + { + if (it->first == "time") + { + dest = this->GetTime(); + return; + } + if (it->first == "timestep") + { + dest = this->GetTimeStep(); + return; + } + } + //throw LetItThrow("Item not found"); + ErrorMessage("Item not found for BMI_GetValue with double argument."); + throw PhreeqcRMStop(); +} + +void PhreeqcRM::BMI_GetValue(std::string name, int& dest) +{ + std::string name_lc = name; + std::transform(name_lc.begin(), name_lc.end(), name_lc.begin(), tolower); + std::map < std::string, BMI_Var >::iterator it = this->bmi_var_map.find(name_lc); + if (it != bmi_var_map.end()) + { + if (it->first == "componentcount") + { + dest = this->GetComponentCount(); + return; + } + if (it->first == "currentselectedoutputusernumber") + { + dest = this->GetIPhreeqcPointer(0)->GetCurrentSelectedOutputUserNumber(); + return; + } + if (it->first == "gridcellcount") + { + dest = this->GetGridCellCount(); + return; + } + if (it->first == "selectedoutputcolumncount") + { + dest = this->GetSelectedOutputColumnCount(); + return; + } + if (it->first == "selectedoutputcount") + { + dest = this->GetSelectedOutputCount(); + return; + } + if (it->first == "selectedoutputrowcount") + { + dest = this->GetSelectedOutputRowCount(); + return; + } + } + ErrorMessage("Item not found for BMI_GetValue with double argument."); + throw PhreeqcRMStop(); +} + +void PhreeqcRM::BMI_GetValue(std::string name, std::string& dest) +{ + std::string name_lc = name; + std::transform(name_lc.begin(), name_lc.end(), name_lc.begin(), tolower); + std::map < std::string, BMI_Var >::iterator it = this->bmi_var_map.find(name_lc); + if (it != bmi_var_map.end()) + { + if (it->first == "fileprefix") + { + dest = this->GetFilePrefix(); + return; + } + if (it->first == "errorstring") + { + dest = this->GetErrorString(); + return; + } + } + ErrorMessage("Item not found for BMI_GetValue with std::string argument."); + throw PhreeqcRMStop(); +} +void PhreeqcRM::BMI_GetValue(std::string name, std::vector < double >& dest) +{ + std::string name_lc = name; + std::transform(name_lc.begin(), name_lc.end(), name_lc.begin(), tolower); + std::map < std::string, BMI_Var >::iterator it = this->bmi_var_map.find(name_lc); + if (it != bmi_var_map.end()) + { + if (it->first == "concentrations") + { + this->GetConcentrations(dest); + return; + } + if (it->first == "density") + { + this->GetDensity(dest); + return; + } + if (it->first == "gfw") + { + dest = this->GetGfw(); + return; + } + if (it->first == "porosity") + { + dest = this->GetPorosity(); + return; + } + if (it->first == "pressure") + { + dest = this->GetPressure(); + return; + } + if (it->first == "saturation") + { + this->GetSaturation(dest); + return; + } + if (it->first == "selectedoutput") + { + IRM_RESULT status = this->GetSelectedOutput(dest); + return; + } + if (it->first == "solutionvolume") + { + dest = this->GetSolutionVolume(); + return; + } + if (it->first == "temperature") + { + dest = this->GetTemperature(); + return; + } + + } + ErrorMessage("Item not found for BMI_GetValue with std::vector < double > argument."); + throw PhreeqcRMStop(); +} +void PhreeqcRM::BMI_GetValue(std::string name, std::vector < std::string >& dest) +{ + std::string name_lc = name; + std::transform(name_lc.begin(), name_lc.end(), name_lc.begin(), tolower); + std::map < std::string, BMI_Var >::iterator it = this->bmi_var_map.find(name_lc); + if (it != bmi_var_map.end()) + { + if (it->first == "components") + { + dest = this->GetComponents(); + return; + } + + if (it->first == "inputvarnames") + { + dest = this->BMI_GetInputVarNames(); + return; + } + + if (it->first == "outputvarnames") + { + dest = this->BMI_GetOutputVarNames(); + return; + } + if (it->first == "selectedoutputheadings") + { + int count = this->GetSelectedOutputColumnCount(); + dest.clear(); + for (int i = 0; i < count; i++) + { + std::string heading; + IRM_RESULT status = this->GetSelectedOutputHeading(i, heading); + dest.push_back(heading); + } + return; + } + } + ErrorMessage("Item not found for BMI_GetValue with std::vector < std::string > argument."); + throw PhreeqcRMStop(); +} void PhreeqcRM::BMI_GetValue(std::string name, void* dest) { - std::map < std::string, BMI_Var >::iterator it = this->bmi_var_map.find(name); + std::string name_lc = name; + std::transform(name_lc.begin(), name_lc.end(), name_lc.begin(), tolower); + std::map < std::string, BMI_Var >::iterator it = this->bmi_var_map.find(name_lc); if (it != bmi_var_map.end()) { - if (it->first == "ComponentCount") + if (it->first == "componentcount") { int count = this->GetComponentCount(); memcpy(dest, &count, sizeof(int)); return; } - if (it->first == "Components") + if (it->first == "components") { int string_length = this->BMI_GetVarItemsize("Components"); std::vector comps = this->GetComponents(); @@ -126,83 +515,119 @@ void PhreeqcRM::BMI_GetValue(std::string name, void* dest) memcpy(dest, all_comps.str().c_str(), all_comps.str().size()); return; } - if (it->first == "Concentrations") + if (it->first == "concentrations") { std::vector rm_conc; this->GetConcentrations(rm_conc); - memcpy(dest, rm_conc.data(), rm_conc.size()*sizeof(double)); + memcpy(dest, rm_conc.data(), rm_conc.size() * sizeof(double)); return; } - if (it->first == "CurrentSelectedOutputUserNumber") + if (it->first == "currentselectedoutputusernumber") { int count = this->GetIPhreeqcPointer(0)->GetCurrentSelectedOutputUserNumber(); memcpy(dest, &count, sizeof(int)); return; } - if (it->first == "Density") + if (it->first == "density") { std::vector density; this->GetDensity(density); - memcpy(dest, density.data(), density.size()*sizeof(double)); + memcpy(dest, density.data(), density.size() * sizeof(double)); return; } - if (it->first == "ErrorString") + if (it->first == "fileprefix") + { + std::string filep = this->GetFilePrefix(); + memcpy(dest, filep.c_str(), filep.size()); + return; + } + if (it->first == "errorstring") { std::string err = this->GetErrorString(); memcpy(dest, err.c_str(), err.size()); return; } - if (it->first == "Gfw") + if (it->first == "gfw") { const std::vector gfw = this->GetGfw(); memcpy(dest, gfw.data(), gfw.size() * sizeof(double)); return; } - if (it->first == "GridCellCount") + if (it->first == "gridcellcount") { int count = this->GetGridCellCount(); memcpy(dest, &count, sizeof(int)); return; } + if (it->first == "inputvarnames") + { + int string_length = this->BMI_GetVarItemsize("inputvarnames"); + std::vector < std::string > varnames = this->BMI_GetInputVarNames(); + std::stringstream all_varnames; + for (size_t i = 0; i < varnames.size(); i++) + { + all_varnames << std::left << std::setfill(' ') << std::setw(string_length) << varnames[i]; + } + memcpy(dest, all_varnames.str().c_str(), all_varnames.str().size()); + return; + } //if (it->first == "NthSelectedOutputUserNumber") //{ // int num = this->GetNthSelectedOutputUserNumber(); // memcpy(dest, &num, sizeof(int)); // return; //} - if (it->first == "Pressure") + if (it->first == "outputvarnames") + { + int string_length = this->BMI_GetVarItemsize("outputvarnames"); + std::vector < std::string > varnames = this->BMI_GetOutputVarNames(); + std::stringstream all_varnames; + for (size_t i = 0; i < varnames.size(); i++) + { + all_varnames << std::left << std::setfill(' ') << std::setw(string_length) << varnames[i]; + } + memcpy(dest, all_varnames.str().c_str(), all_varnames.str().size()); + return; + } + if (it->first == "porosity") + { + const std::vector& porosity = this->GetPorosity(); + memcpy(dest, porosity.data(), porosity.size() * sizeof(double)); + return; + } + if (it->first == "pressure") { - const std::vector &pressure = this->GetPressure(); + const std::vector& pressure = this->GetPressure(); memcpy(dest, pressure.data(), pressure.size() * sizeof(double)); return; } - if (it->first == "Saturation") + if (it->first == "saturation") { std::vector saturation; this->GetSaturation(saturation); memcpy(dest, saturation.data(), saturation.size() * sizeof(double)); return; } - if (it->first == "SelectedOutput") + if (it->first == "selectedoutput") { std::vector so; IRM_RESULT status = this->GetSelectedOutput(so); memcpy(dest, so.data(), so.size() * sizeof(double)); return; } - if (it->first == "SelectedOutputColumnCount") + if (it->first == "selectedoutputcolumncount") { int count = this->GetSelectedOutputColumnCount(); memcpy(dest, &count, sizeof(int)); return; } - if (it->first == "SelectedOutputCount") + if (it->first == "selectedoutputcount") { int count = this->GetSelectedOutputCount(); memcpy(dest, &count, sizeof(int)); return; } - if (it->first == "SelectedOutputHeadings") + if (it->first == "selectedoutputheadings") { int string_length = this->BMI_GetVarItemsize("SelectedOutputHeadings"); int count = this->GetSelectedOutputColumnCount(); @@ -216,113 +641,167 @@ void PhreeqcRM::BMI_GetValue(std::string name, void* dest) memcpy(dest, all_headings.str().c_str(), all_headings.str().size()); return; } - if (it->first == "SelectedOutputOn") + if (it->first == "selectedoutputon") { - int flag = (int)this->GetSelectedOutputOn(); - memcpy(dest, &flag, sizeof(int)); + int tf = (int)this->GetSelectedOutputOn(); + memcpy(dest, &tf, sizeof(int)); return; } - if (it->first == "SelectedOutputRowCount") + if (it->first == "selectedoutputon") + { + int tf = (int)this->GetSelectedOutputOn(); + memcpy(dest, &tf, sizeof(bool)); + return; + } + if (it->first == "selectedoutputrowcount") { int count = this->GetSelectedOutputRowCount(); memcpy(dest, &count, sizeof(int)); return; } - if (it->first == "Temperature") + if (it->first == "solutionvolume") + { + const std::vector& vol = this->GetSolutionVolume(); + memcpy(dest, vol.data(), vol.size() * sizeof(double)); + return; + } + if (it->first == "temperature") { - const std::vector &temperature = this->GetTemperature(); + const std::vector& temperature = this->GetTemperature(); memcpy(dest, temperature.data(), temperature.size() * sizeof(double)); return; } + if (it->first == "time") + { + double time = this->GetTime(); + memcpy(dest, &time, sizeof(double)); + return; + } + if (it->first == "timestep") + { + double timestep = this->GetTimeStep(); + memcpy(dest, ×tep, sizeof(double)); + return; + } } - //throw LetItThrow("Item not found"); ErrorMessage("Item not found"); throw PhreeqcRMStop(); } int PhreeqcRM::BMI_GetVarNbytes(std::string name) { - std::map < std::string, BMI_Var >::iterator it = this->bmi_var_map.find(name); + std::string name_lc = name; + std::transform(name_lc.begin(), name_lc.end(), name_lc.begin(), tolower); + std::map < std::string, BMI_Var >::iterator it = this->bmi_var_map.find(name_lc); if (it != bmi_var_map.end()) { - if (it->first == "ComponentCount") + if (it->first == "componentcount") { return this->GetComponentCount(); } - if (it->first == "Components") + if (it->first == "components") { - int string_size = this->BMI_GetVarItemsize("Components"); + int string_size = this->BMI_GetVarItemsize("components"); int dim = this->GetComponentCount(); return string_size * dim * (int)sizeof(char); } - if (it->first == "Concentrations") + if (it->first == "concentrations") { return (int)sizeof(double) * this->GetGridCellCount() * this->GetComponentCount(); } - if (it->first == "CurrentSelectedOutputUserNumber") + if (it->first == "currentselectedoutputusernumber") { return (int)sizeof(int); } - if (it->first == "Density") + if (it->first == "density") { return (int)sizeof(double) * this->GetGridCellCount(); } - if (it->first == "ErrorString") + + if (it->first == "fileprefix") + { + return (int)this->GetFilePrefix().size(); + } + if (it->first == "errorstring") { return (int)this->GetErrorString().size(); } - if (it->first == "Gfw") + if (it->first == "gfw") { return (int)sizeof(double) * this->GetComponentCount(); } - if (it->first == "GridCellCount") + if (it->first == "gridcellcount") { return (int)sizeof(int); } - if (it->first == "NthSelectedOutput") + if (it->first == "inputvarnames") + { + int string_length = this->BMI_GetVarItemsize("inputvarnames"); + std::vector < std::string > varnames = this->BMI_GetInputVarNames(); + return string_length * (int)(varnames.size() * sizeof(char)); + } + if (it->first == "nthselectedoutput") { return (int)sizeof(int); } - if (it->first == "Porosity") + if (it->first == "outputvarnames") + { + int string_length = this->BMI_GetVarItemsize("outputvarnames"); + std::vector < std::string > varnames = this->BMI_GetOutputVarNames(); + return string_length * (int)(varnames.size() * sizeof(char)); + } + if (it->first == "porosity") { return (int)sizeof(double) * this->GetGridCellCount(); } - if (it->first == "Pressure") + if (it->first == "pressure") { return (int)sizeof(double) * this->GetGridCellCount(); } - if (it->first == "Saturation") + if (it->first == "saturation") { return (int)sizeof(double) * this->GetGridCellCount(); } - if (it->first == "SelectedOutput") + if (it->first == "selectedoutput") { return (int)sizeof(double) * this->GetSelectedOutputColumnCount() * this->GetSelectedOutputRowCount(); } - if (it->first == "SelectedOutputColumnCount") + if (it->first == "selectedoutputcolumncount") { return (int)sizeof(int); } - if (it->first == "SelectedOutputCount") + if (it->first == "selectedoutputcount") { return (int)sizeof(int); } - if (it->first == "SelectedOutputHeadings") + if (it->first == "selectedoutputheadings") { - int string_size = this->BMI_GetVarItemsize("SelectedOutputHeadings"); + int string_size = this->BMI_GetVarItemsize("selectedoutputheadings"); return string_size * this->GetSelectedOutputColumnCount() * (int)sizeof(char); } - if (it->first == "SelectedOutputOn") + if (it->first == "selectedoutputon") { return (int)sizeof(int); } - if (it->first == "SelectedOutputRowCount") + if (it->first == "selectedoutputrowcount") { return (int)sizeof(int); } - if (it->first == "Temperature") + if (it->first == "solutionvolume") + { + return (int)sizeof(double) * this->GetGridCellCount(); + } + if (it->first == "temperature") { return (int)sizeof(double) * this->GetGridCellCount(); } + if (it->first == "time") + { + return (int)sizeof(double); + } + if (it->first == "timestep") + { + return (int)sizeof(double); + } } //throw LetItThrow("Item not found"); ErrorMessage("Item not found"); @@ -330,10 +809,12 @@ int PhreeqcRM::BMI_GetVarNbytes(std::string name) } std::string PhreeqcRM::BMI_GetVarUnits(std::string name) { - std::map < std::string, BMI_Var >::iterator it = this->bmi_var_map.find(name); + std::string name_lc = name; + std::transform(name_lc.begin(), name_lc.end(), name_lc.begin(), tolower); + std::map < std::string, BMI_Var >::iterator it = this->bmi_var_map.find(name_lc); if (it != bmi_var_map.end()) { - if (it->first == "Concentrations") + if (it->first == "concentrations") { int units = this->GetUnitsSolution(); switch (units) @@ -362,16 +843,17 @@ std::string PhreeqcRM::BMI_GetVarUnits(std::string name) } int PhreeqcRM::BMI_GetVarItemsize(std::string name) { - std::map < std::string, BMI_Var >::iterator it = this->bmi_var_map.find(name); + std::string name_lc = name; + std::transform(name_lc.begin(), name_lc.end(), name_lc.begin(), tolower); + std::map < std::string, BMI_Var >::iterator it = this->bmi_var_map.find(name_lc); if (it != bmi_var_map.end()) { - if (it->first == "ComponentCount") + if (it->first == "componentcount") { return (int)sizeof(int); } - if (it->first == "Components") + if (it->first == "components") { - const std::vector< std::string >& ref = this->GetComponents(); size_t max = 0; for (size_t i = 0; i < this->GetComponents().size(); i++) { @@ -379,59 +861,83 @@ int PhreeqcRM::BMI_GetVarItemsize(std::string name) } return (int)max; } - if (it->first == "Concentrations") + if (it->first == "concentrations") { return (int)sizeof(double); } - if (it->first == "CurrentSelectedOutputUserNumber") + if (it->first == "currentselectedoutputusernumber") { return (int)sizeof(int); } - if (it->first == "Density") + if (it->first == "density") { return (int)sizeof(double); } - if (it->first == "ErrorString") + if (it->first == "fileprefix") + { + return (int)this->GetFilePrefix().size(); + } + if (it->first == "errorstring") { return (int)this->GetErrorString().size(); } - if (it->first == "Gfw") + if (it->first == "gfw") { return (int)sizeof(double); } - if (it->first == "GridCellCount") + if (it->first == "gridcellcount") { return (int)sizeof(int); } - if (it->first == "NthSelectedOutput") + if (it->first == "inputvarnames") + { + std::vector < std::string > varnames = this->BMI_GetInputVarNames(); + size_t max = 0; + for (size_t i = 0; i < varnames.size(); i++) + { + if (varnames[i].size() > max) max = varnames[i].size(); + } + return (int)max; + } + if (it->first == "nthselectedoutput") { return (int)sizeof(int); } - if (it->first == "Porosity") + if (it->first == "outputvarnames") + { + std::vector < std::string > varnames = this->BMI_GetOutputVarNames(); + size_t max = 0; + for (size_t i = 0; i < varnames.size(); i++) + { + if (varnames[i].size() > max) max = varnames[i].size(); + } + return (int)max; + } + if (it->first == "porosity") { return (int)sizeof(double); } - if (it->first == "Pressure") + if (it->first == "pressure") { return (int)sizeof(double); } - if (it->first == "Saturation") + if (it->first == "saturation") { return (int)sizeof(double); } - if (it->first == "SelectedOutput") + if (it->first == "selectedoutput") { return (int)sizeof(double); } - if (it->first == "SelectedOutputColumnCount") + if (it->first == "selectedoutputcolumncount") { return (int)sizeof(int); } - if (it->first == "SelectedOutputCount") + if (it->first == "selectedoutputcount") { return (int)sizeof(int); } - if (it->first == "SelectedOutputHeadings") + if (it->first == "selectedoutputheadings") { int nhead = this->GetSelectedOutputColumnCount(); size_t max = 0; @@ -443,15 +949,27 @@ int PhreeqcRM::BMI_GetVarItemsize(std::string name) } return (int)max; } - if (it->first == "SelectedOutputOn") + if (it->first == "selectedoutputon") { return (int)sizeof(int); } - if (it->first == "SelectedOutputRowCount") + if (it->first == "selectedoutputrowcount") { return (int)sizeof(int); } - if (it->first == "Temperature") + if (it->first == "solutionvolume") + { + return (int)sizeof(double); + } + if (it->first == "temperature") + { + return (int)sizeof(double); + } + if (it->first == "time") + { + return (int)sizeof(double); + } + if (it->first == "timestep") { return (int)sizeof(double); } @@ -466,7 +984,9 @@ int PhreeqcRM::BMI_GetVarItemsize(std::string name) } std::string PhreeqcRM::BMI_GetVarType(std::string name) { - std::map < std::string, BMI_Var >::iterator it = this->bmi_var_map.find(name); + std::string name_lc = name; + std::transform(name_lc.begin(), name_lc.end(), name_lc.begin(), tolower); + std::map < std::string, BMI_Var >::iterator it = this->bmi_var_map.find(name_lc); if (it != bmi_var_map.end()) { return it->second.GetType(); @@ -492,37 +1012,37 @@ void PhreeqcRM::BMI_MakeVarMap() //var_map["BackwardMapping"] = Var_BMI("BackwardMapping", "int", "mapping", sizeof(int)); //var_map["CreateMapping"] = Var_BMI("CreateMapping", "int", "mapping", sizeof(int)); //var_map["ChemistryCellCount"] = Var_BMI("ChemistryCellCount", "int", "count", sizeof(int)); - bmi_var_map["Components"] = BMI_Var("Components", "string", "names", false, true); - bmi_var_map["ComponentCount"] = BMI_Var("ComponentCount", "int", "names", false, true); - bmi_var_map["Concentrations"] = BMI_Var("Concentrations", "double", "mol L-1", true, true); - bmi_var_map["Density"] = BMI_Var("Density", "double", "kg L-1", true, true); + bmi_var_map["components"] = BMI_Var("Components", "character,1d", "names", false, true); + bmi_var_map["componentcount"] = BMI_Var("ComponentCount", "integer", "names", false, true); + bmi_var_map["concentrations"] = BMI_Var("Concentrations", "double,2d", "mol L-1", true, true); + bmi_var_map["density"] = BMI_Var("Density", "double,1d", "kg L-1", true, true); //var_map["EndCell"] = Var_BMI("EndCell", "int", "cell numbers", sizeof(int)); //var_map["EquilibriumPhasesNames"] = Var_BMI("EquilibriumPhasesNames", "string", "names", sizeof(char)); - bmi_var_map["ErrorString"] = BMI_Var("ErrorString", "string", "error", false, true); + bmi_var_map["errorstring"] = BMI_Var("ErrorString", "character", "error", false, true); //var_map["ExchangeNames"] = Var_BMI("ExchangeNames", "string", "names", sizeof(char)); //var_map["ExchangeSpeciesNames"] = Var_BMI("ExchangeSpeciesNames", "string", "names", sizeof(char)); - //var_map["FilePrefix"] = Var_BMI("FilePrefix", "string", "name", sizeof(char)); + bmi_var_map["fileprefix"] = BMI_Var("FilePrefix", "character", "name", true, true); //!var_map["GasComponentNames"] = Var_BMI("GasComponentsNames", "string", "names", sizeof(char)); //!var_map["GasCompMoles"] = Var_BMI("GasCompMoles", "double", "mol", sizeof(double)); //!var_map["GasCompPressures"] = Var_BMI("GasCompPressures", "double", "atm", sizeof(double)); //!var_map["GasCompPhi"] = Var_BMI("GasCompPhi", "double", "atm-1", sizeof(double)); //!var_map["GasPhaseVolume"] = Var_BMI("GasPhaseVolume", "double", "L", sizeof(double)); - bmi_var_map["Gfw"] = BMI_Var("Gfw", "double", "g mol-1", false, true); - bmi_var_map["GridCellCount"] = BMI_Var("GridCellCount", "int", "count", false, true); + bmi_var_map["gfw"] = BMI_Var("Gfw", "double,1d", "g mol-1", false, true); + bmi_var_map["gridcellcount"] = BMI_Var("GridCellCount", "integer", "count", false, true); //var_map["KineticReactions"] = Var_BMI("KineticReactions", "string", "names", sizeof(char)); //var_map["MpiMyself"] = Var_BMI("MpiMyself", "int", "id", sizeof(int)); //var_map["MpiTasks"] = Var_BMI("MpiTasks", "int", "count", sizeof(int)); - bmi_var_map["NthSelectedOutput"] = BMI_Var("NthSelectedOutput", "int", "id", true, false); - bmi_var_map["Saturation"] = BMI_Var("Saturation", "double", "unitless", true, true); - bmi_var_map["SelectedOutput"] = BMI_Var("SelectedOutput", "double", "user", false, true); - bmi_var_map["SelectedOutputColumnCount"] = BMI_Var("SelectedOutputColumnCount", "int", "count", false, true); - bmi_var_map["SelectedOutputCount"] = BMI_Var("SelectedOutputCount", "int", "count", false, true); - bmi_var_map["SelectedOutputHeadings"] = BMI_Var("SelectedOutputHeadings", "string", "names", false, true); - bmi_var_map["SelectedOutputRowCount"] = BMI_Var("SelectedOutputRowCount", "int", "count", false, true); + bmi_var_map["nthselectedoutput"] = BMI_Var("NthSelectedOutput", "integer", "id", true, false); + bmi_var_map["saturation"] = BMI_Var("Saturation", "double,1d", "unitless", true, true); + bmi_var_map["selectedoutput"] = BMI_Var("SelectedOutput", "double,2d", "user", false, true); + bmi_var_map["selectedoutputcolumncount"] = BMI_Var("SelectedOutputColumnCount", "integer", "count", false, true); + bmi_var_map["selectedoutputcount"] = BMI_Var("SelectedOutputCount", "integer", "count", false, true); + bmi_var_map["selectedoutputheadings"] = BMI_Var("SelectedOutputHeadings", "character,1d", "names", false, true); + bmi_var_map["selectedoutputrowcount"] = BMI_Var("SelectedOutputRowCount", "integer", "count", false, true); //var_map["SINames"] = Var_BMI("SINames", "string", "names", 0); //var_map["SolidSolutionComponentsNames"] = Var_BMI("SolidSolutionComponentsNames", "string", "names", sizeof(char)); //var_map["SolidSolutionNames"] = Var_BMI("SolidSolutionNames", "string", "names", sizeof(char)); - //var_map["SolutionVolume"] = Var_BMI("SolutionVolume", "double", "L", sizeof(double)); + bmi_var_map["solutionvolume"] = BMI_Var("SolutionVolume", "double,1d", "L", false, true); //!var_map["SpeciesConcentrations"] = Var_BMI("SpeciesConcentrations", "double", "mg L-1", sizeof(double)); //!var_map["SpeciesD25"] = Var_BMI("SpeciesD25", "double", "cm2 s-1", sizeof(double)); //!var_map["SpeciesLog10Gammas"] = Var_BMI("SpeciesLog10Gammas", "double", "log L mol-1", sizeof(double)); @@ -535,19 +1055,19 @@ void PhreeqcRM::BMI_MakeVarMap() //var_map["SurfaceSpeciesNames"] = Var_BMI("SurfaceSpeciesNames", "string", "names", sizeof(char)); //var_map["SurfaceTypes"] = Var_BMI("SurfaceTypes", "string", "names", sizeof(char)); //var_map["ThreadCount"] = Var_BMI("ThreadCount", "int", "count", sizeof(int)); - bmi_var_map["Time"] = BMI_Var("Time", "double", "s", true, false); + bmi_var_map["time"] = BMI_Var("Time", "double", "s", true, true); //var_map["TimeConversion"] = Var_BMI("TimeConversion", "double", "unitless", sizeof(double)); - bmi_var_map["TimeStep"] = BMI_Var("TimeStep", "double", "s", true, false); + bmi_var_map["timestep"] = BMI_Var("TimeStep", "double", "s", true, true); //var_map["MpiWorker"] = Var_BMI("MpiWorker", "int", "id", sizeof(int)); //var_map["ComponentH2O"] = Var_BMI("ComponentH2O", "int", "flag", sizeof(int)); - bmi_var_map["CurrentSelectedOutputUserNumber"] = BMI_Var("CurrentSelectedOutputUserNumber", "int", "id", false, true); + bmi_var_map["currentselectedoutputusernumber"] = BMI_Var("CurrentSelectedOutputUserNumber", "integer", "id", false, true); //var_map["DumpFileName"] = Var_BMI("DumpFileName", "string", "name", sizeof(char)); //var_map["ErrorHandlerMode"] = Var_BMI("ErrorHandlerMode", "int", "flag", sizeof(int)); //var_map["ErrorOn"] = Var_BMI("ErrorOn", "int", "flag", sizeof(int)); //var_map["PartitionUZSolids"] = Var_BMI("PartitionUZSolids", "int", "flag", sizeof(int)); - bmi_var_map["Porosity"] = BMI_Var("Porosity", "double", "unitless", true, false); + bmi_var_map["porosity"] = BMI_Var("Porosity", "double,1d", "unitless", true, true); //var_map["PartitionUZSolids"] = Var_BMI("PartitionUZSolids", "int", "flag", sizeof(int)); - bmi_var_map["Pressure"] = BMI_Var("Pressure", "double", "atm", true, true); + bmi_var_map["pressure"] = BMI_Var("Pressure", "double,1d", "atm", true, true); //var_map["PrintChemistryMask"] = Var_BMI("PrintChemistryMask", "int", "flags", sizeof(int)); //var_map["PrintChemistryOn"] = Var_BMI("PrintChemistryOn", "int", "flag", sizeof(int)); //var_map["RebalanceByCell"] = Var_BMI("RebalanceByCell", "int", "flag", sizeof(int)); @@ -555,8 +1075,8 @@ void PhreeqcRM::BMI_MakeVarMap() //var_map["RepresentativeVolume"] = Var_BMI("RepresentativeVolume", "double", "L", sizeof(double)); //var_map["RebalanceByCell"] = Var_BMI("RebalanceByCell", "int", "flag", sizeof(int)); //var_map["ScreenOn"] = Var_BMI("ScreenOn", "int", "flag", sizeof(int)); - bmi_var_map["SelectedOutputOn"] = BMI_Var("SelectedOutputOn", "int", "flag", true, false); - bmi_var_map["Temperature"] = BMI_Var("Temperature", "double", "C", true, true); + bmi_var_map["selectedoutputon"] = BMI_Var("SelectedOutputOn", "logical", "flag", true, true); + bmi_var_map["temperature"] = BMI_Var("Temperature", "double,1d", "C", true, true); //var_map["UnitsExchange"] = Var_BMI("UnitsExchange", "int", "flag", sizeof(int)); //var_map["UnitsGasPhase"] = Var_BMI("UnitsExchange", "int", "flag", sizeof(int)); //var_map["UnitsKinetics"] = Var_BMI("UnitsExchange", "int", "flag", sizeof(int)); @@ -565,7 +1085,8 @@ void PhreeqcRM::BMI_MakeVarMap() //var_map["UnitsSSassemblage"] = Var_BMI("UnitsExchange", "int", "flag", sizeof(int)); //var_map["UnitsSurface"] = Var_BMI("UnitsExchange", "int", "flag", sizeof(int)); //var_map["UseSolutionDensityVolume"] = Var_BMI("UseSolutionDensityVolume", "int", "flag", sizeof(int)); - + bmi_var_map["inputvarnames"] = BMI_Var("InputVarNames", "character,1d", "string", false, true); + bmi_var_map["outputvarnames"] = BMI_Var("OutputVarNames", "character,1d", "string", false, true); } this->bmi_input_vars.clear(); this->bmi_output_vars.clear(); @@ -574,442 +1095,15 @@ void PhreeqcRM::BMI_MakeVarMap() { if (it->second.GetSet()) { - bmi_input_vars.push_back(it->first); + bmi_input_vars.push_back(it->second.GetName()); } if (it->second.GetGet()) { - bmi_output_vars.push_back(it->first); + bmi_output_vars.push_back(it->second.GetName()); } } } -#ifdef USE_YAML -IRM_RESULT PhreeqcRM::InitializeYAML(std::string config) -{ - YAML::Node yaml = YAML::LoadFile(config); - std::string keyword; - YAML::Node node; - for (YAML::Node::const_iterator it = yaml.begin();it != yaml.end();++it) - { - keyword = it->first.as(); - YAML::Node node = it->second; - bool is_defined = node.IsDefined(); - bool is_map = node.IsMap(); - bool is_null = node.IsNull(); - bool is_scalar = node.IsScalar(); - bool is_sequence = node.IsSequence(); - size_t node_size = node.size(); - - if (keyword == "CloseFiles") - { - this->CloseFiles(); - continue; - } - if (keyword == "CreateMapping") - { - assert(node.IsSequence()); - std::vector grid2chem = it->second.as>(); - this->CreateMapping(grid2chem); - continue; - } - if (keyword == "DumpModule") - { - assert(node.IsMap()); - assert(node.size() == 2); - YAML::const_iterator it1 = node.begin(); - bool dump_on = it1++->second.as(); - bool append = it1++->second.as(); - this->DumpModule(dump_on, append); - continue; - } - if (keyword == "FindComponents") - { - this->FindComponents(); - continue; - } - if (keyword == "InitialPhreeqc2Module") - { - if (node.IsSequence()) - { - std::vector< int > ic = node.as< std::vector< int > >(); - this->InitialPhreeqc2Module(ic); - continue; - } - else if (node.IsMap()) - { - assert(node.IsMap()); - assert(node.size() == 3); - YAML::const_iterator it1 = node.begin(); - std::vector < int > ic1 = it1++->second.as< std::vector < int > >(); - std::vector < int > ic2 = it1++->second.as< std::vector < int > >(); - std::vector < double > f1 = it1->second.as< std::vector < double > >(); - this->InitialPhreeqc2Module(ic1, ic2, f1); - continue; - } - //throw LetItThrow("YAML argument mismatch InitialPhreeqc2Module"); - ErrorMessage("YAML argument mismatch InitialPhreeqc2Module"); - throw PhreeqcRMStop(); - } - if (keyword == "InitialPhreeqcCell2Module") - { - assert(node.IsMap()); - assert(node.size() == 2); - YAML::const_iterator it1 = node.begin(); - int n = it1++->second.as(); - std::vector< int > cell_numbers = it1->second.as< std::vector >(); - this->InitialPhreeqcCell2Module(n, cell_numbers); - continue; - } - if (keyword == "LoadDatabase") - { - std::string file = node.as< std::string >(); - this->LoadDatabase(file); - continue; - } - if (keyword == "OpenFiles") - { - this->OpenFiles(); - continue; - } - if (keyword == "OutputMessage") - { - assert(node.IsScalar()); - std::string str = node.as< std::string >(); - this->OutputMessage(str); - continue; - } - if (keyword == "RunCells") - { - this->RunCells(); - continue; - } - if (keyword == "RunFile") - { - assert(node.IsMap()); - assert(node.size() == 4); - YAML::const_iterator it1 = node.begin(); - bool workers = it1++->second.as(); - bool initial = it1++->second.as(); - bool utility = it1++->second.as(); - std::string file = it1->second.as< std::string >(); - this->RunFile(workers, initial, utility, file); - continue; - } - if (keyword == "RunString") - { - assert(node.IsMap()); - assert(node.size() == 4); - YAML::const_iterator it1 = node.begin(); - bool workers = it1++->second.as(); - bool initial = it1++->second.as(); - bool utility = it1++->second.as(); - std::string string = it1->second.as(); - this->RunString(workers, initial, utility, string); - continue; - } - if (keyword == "ScreenMessage") - { - assert(node.IsScalar()); - std::string str = node.as< std::string >(); - this->ScreenMessage(str); - continue; - } - if (keyword == "SetComponentH2O") - { - assert(node.IsScalar()); - bool tf = node.as< bool >(); - this->SetComponentH2O(tf); - continue; - } - if (keyword == "SetConcentrations") { - assert(node.IsSequence()); - std::vector< double > c = node.as< std::vector< double > >(); - this->SetConcentrations(c); - continue; - } - if (keyword == "SetCurrentSelectedOutputUserNumber") - { - assert(node.IsScalar()); - int n = node.as< int >(); - this->SetCurrentSelectedOutputUserNumber(n); - continue; - } - if (keyword == "SetDensity") - { - assert(node.IsSequence()); - std::vector< double > den = node.as< std::vector< double > >(); - this->SetDensity(den); - continue; - } - if (keyword == "SetDumpFileName") - { - assert(node.IsScalar()); - std::string str = node.as< std::string >(); - this->SetDumpFileName(str); - continue; - } - if (keyword == "SetErrorHandlerMode") - { - assert(node.IsScalar()); - int mode = node.as< int >(); - this->SetErrorHandlerMode(mode); - continue; - } - if (keyword == "SetErrorOn") { - assert(node.IsScalar()); - bool tf = node.as< bool >(); - this->SetErrorOn(tf); - continue; - } - if (keyword == "SetFilePrefix") - { - assert(node.IsScalar()); - std::string prefix = node.as< std::string >(); - this->SetFilePrefix(prefix); - continue; - } - if (keyword == "SetGasCompMoles") { - assert(node.IsSequence()); - std::vector mol = node.as< std::vector < double > >(); - this->SetGasCompMoles(mol); - continue; - } - if (keyword == "SetGasPhaseVolume") { - assert(node.IsSequence()); - std::vector vol = node.as< std::vector < double > >(); - this->SetGasPhaseVolume(vol); - continue; - } - if (keyword == "SetGridCellCount") { - this->WarningMessage("SetGridCellCount has no effect after the PhreeqcRM instance is created."); - continue; - } - if (keyword == "SetPartitionUZSolids") - { - assert(node.IsScalar()); - bool tf = node.as< bool >(); - this->SetPartitionUZSolids(tf); - continue; - } - if (keyword == "SetPorosity") - { - assert(node.IsSequence()); - std::vector por = node.as< std::vector< double > >(); - this->SetPorosity(por); - continue; - } - if (keyword == "SetPressure") - { - assert(node.IsSequence()); - std::vector pressure = node.as< std::vector< double > >(); - this->SetPressure(pressure); - continue; - } - if (keyword == "SetPrintChemistryMask") - { - assert(node.IsSequence()); - std::vector mask = node.as< std::vector< int > >(); - this->SetPrintChemistryMask(mask); - continue; - } - if (keyword == "SetPrintChemistryOn") - { - assert(node.IsMap()); - assert(node.size() == 3); - YAML::const_iterator it1 = node.begin(); - bool workers = it1++->second.as< bool >(); - bool initial = it1++->second.as< bool >(); - bool utility = it1->second.as< bool >(); - this->SetPrintChemistryOn(workers, initial, utility); - continue; - } - if (keyword == "SetRebalanceByCell") - { - assert(node.IsScalar()); - bool tf = node.as< bool >(); - this->SetRebalanceByCell(tf); - continue; - } - if (keyword == "SetRebalanceFraction") - { - assert(node.IsScalar()); - double f = node.as(); - this->SetRebalanceFraction(f); - continue; - } - if (keyword == "SetRepresentativeVolume") - { - assert(node.IsSequence()); - std::vector rv = it->second.as< std::vector >(); - this->SetRepresentativeVolume(rv); - continue; - } - if (keyword == "SetSaturation") - { - assert(node.IsSequence()); - std::vector< double > sat = node.as< std::vector< double> >(); - this->SetSaturation(sat); - continue; - } - if (keyword == "SetScreenOn") { - assert(node.IsScalar()); - bool tf = node.as< bool >(); - this->SetScreenOn(tf); - continue; - } - if (keyword == "SetSelectedOutputOn") - { - assert(node.IsScalar()); - bool tf = node.as< bool >(); - this->SetSelectedOutputOn(tf); - continue; - } - if (keyword == "SetSpeciesSaveOn") - { - assert(node.IsScalar()); - bool tf = node.as< bool >(); - this->SetSpeciesSaveOn(tf); - continue; - } - if (keyword == "SetTemperature") - { - assert(node.IsSequence()); - std::vector temp = node.as>(); - this->SetTemperature(temp); - continue; - } - if (keyword == "SetTime") - { - assert(node.IsScalar()); - double time = node.as(); - this->SetTime(time); - continue; - } - if (keyword == "SetTimeConversion") - { - assert(node.IsScalar()); - double time_conv = node.as(); - this->SetTimeConversion(time_conv); - continue; - } - if (keyword == "SetTimeStep") - { - assert(node.IsScalar()); - double time_step = node.as(); - this->SetTimeStep(time_step); - continue; - } - if (keyword == "SetUnitsExchange") - { - assert(node.IsScalar()); - int units = node.as(); - this->SetUnitsExchange(units); - continue; - } - if (keyword == "SetUnitsGasPhase") - { - assert(node.IsScalar()); - int units = node.as< int >(); - this->SetUnitsGasPhase(units); - continue; - } - if (keyword == "SetUnitsKinetics") - { - assert(node.IsScalar()); - int units = node.as< int >(); - this->SetUnitsKinetics(units); - continue; - } - if (keyword == "SetUnitsPPassemblage") - { - assert(node.IsScalar()); - int units = node.as< int >(); - this->SetUnitsPPassemblage(units); - continue; - } - if (keyword == "SetUnitsSolution") - { - assert(node.IsScalar()); - int units = node.as< int >(); - this->SetUnitsSolution(units); - continue; - } - if (keyword == "SetUnitsSSassemblage") - { - assert(node.IsScalar()); - int units = node.as< int >(); - this->SetUnitsSSassemblage(units); - continue; - } - if (keyword == "SetUnitsSurface") - { - assert(node.IsScalar()); - int units = node.as< int >(); - this->SetUnitsSurface(units); - continue; - } - if (keyword == "SpeciesConcentrations2Module") - { - assert(node.IsSequence()); - std::vector < double > scond = node.as< std::vector < double > >(); - this->SpeciesConcentrations2Module(scond); - continue; - } - if (keyword == "StateSave") - { - assert(node.IsScalar()); - int n = node.as< int >(); - this->StateSave(n); - continue; - } - if (keyword == "StateApply") - { - assert(node.IsScalar()); - int n = node.as< int >(); - this->StateApply(n); - continue; - } - if (keyword == "StateDelete") - { - assert(node.IsScalar()); - int n = node.as< int >(); - this->StateDelete(n); - continue; - } - if (keyword == "UseSolutionDensityVolume") - { - assert(node.IsScalar()); - bool tf = node.as< bool >(); - this->UseSolutionDensityVolume(tf); - continue; - } - if (keyword == "WarningMessage") - { - assert(node.IsScalar()); - std::string str = node.as< std::string >(); - this->WarningMessage(str); - continue; - } - //throw LetItThrow("YAML keyword not found"); - ErrorMessage("YAML keyword not found"); - throw PhreeqcRMStop(); - } - return IRM_RESULT::IRM_OK; -} -// Global method -int -GetGridCellCountYAML(std::string YAML_file) -{ - YAML::Node yaml = YAML::LoadFile(YAML_file); - std::string keyword; - YAML::Node node; - if (yaml["SetGridCellCount"].IsDefined()) - { - return yaml["SetGridCellCount"].as(); - } - return 0; -} -#endif diff --git a/src/BMI_methods.h b/src/BMI_methods.h new file mode 100644 index 000000000..8021680ec --- /dev/null +++ b/src/BMI_methods.h @@ -0,0 +1,896 @@ +// BMI data and methods +private: + std::map bmi_var_map; + std::vector< std::string > bmi_input_vars; + std::vector< std::string > bmi_output_vars; +public: + + //void BMI_Finalize(); +/** +Basic Model Interface method that returns the component name--PhreeqcRM. The BMI interface to PhreeqcRM is +only partial, and provides only the most basic functions. The native PhreeqcRM methods (those without the the BMI_ +prefix) provide a complete interface, and it is expected that the native methods will be used in preference to the BMI_ +methods. + +@retval The string "PhreeqcRM". +@par C++ Example: +@htmlonly + +
+std::string comp_name = phreeqc_rm.BMI_GetComponentName();
+
+
+@endhtmlonly +@par MPI: +Called by root. +*/ + std::string BMI_GetComponentName() { return "PhreeqcRM"; } + + //-------------------------- + + /** + Basic Model Interface method that returns the current simulation time, in seconds. (Same as @ref GetTime.) + The reaction module does not change the time value, so the + returned value is equal to the default (0.0) or the last time set by + @ref BMI_SetValue("Time", time) or @ref SetTime. + @retval The current simulation time, in seconds. + @see + @ref BMI_GetEndTime, + @ref BMI_GetTimeStep, + @ref BMI_SetValue, + @ref GetTime, + @ref GetTimeStep, + @ref SetTime, + @ref SetTimeStep. + @par C++ Example: + @htmlonly + +
+	std::cout << "Current time: "
+		 << BMI_GetCurrentTime()
+		 << " seconds\n";
+	
+
+ @endhtmlonly + @par MPI: + Called by root. + */ + double BMI_GetCurrentTime() { return this->GetTime(); } + + //-------------------------- + + /** + Basic Model Interface method that returns @ref BMI_GetCurrentTime plus @ref BMI_GetTimeStep, in seconds. + @retval The end of the time step, in seconds. + @see + @ref BMI_GetCurrentTime, + @ref BMI_GetTimeStep, + @ref BMI_SetValue, + @ref GetTime, + @ref GetTimeStep, + @ref SetTime, + @ref SetTimeStep. + @par C++ Example: + @htmlonly + +
+	std::cout << "End of time step "
+		 << BMI_GetEndTime()
+		 << " seconds\n";
+	
+
+ @endhtmlonly + @par MPI: + Called by root. + */ + double BMI_GetEndTime() { return this->GetTime() + this->GetTimeStep(); } + + //-------------------------- + + /** + Basic Model Interface method that returns count of input variables that can be set with @ref BMI_SetValue. + @retval Count of input variables that can be set with @ref BMI_SetValue. + + @see + @ref BMI_GetInputVarNames, + @ref BMI_GetVarItemsize, + @ref BMI_GetVarNbytes, + @ref BMI_GetVarType, + @ref BMI_GetVarUnits, + @ref BMI_SetValue. + @par C++ Example: + @htmlonly + +
+			std::vector< std::string > InputVarNames = phreeqc_rm.BMI_GetInputVarNames();
+			int count = phreeqc_rm.BMI_GetInputItemCount();
+			oss << "BMI_SetValue variables:\n";
+			for (size_t i = 0; i < count; i++)
+			{
+				oss << "  " << i << "  " << InputVarNames[i] << "\n";
+				oss << "     Type:        " << phreeqc_rm.BMI_GetVarType(InputVarNames[i]) << "\n";
+				oss << "     Units:       " << phreeqc_rm.BMI_GetVarUnits(InputVarNames[i]) << "\n";
+				oss << "     Total bytes: " << phreeqc_rm.BMI_GetVarNbytes(InputVarNames[i]) << "\n";
+				oss << "     Item bytes:  " << phreeqc_rm.BMI_GetVarItemsize(InputVarNames[i]) << "\n";
+				oss << "     Dim:         " << phreeqc_rm.BMI_GetVarNbytes(InputVarNames[i]) /
+											   phreeqc_rm.BMI_GetVarItemsize(InputVarNames[i]) << "\n";
+			}
+	
+
+ @endhtmlonly + @par MPI: + Called by root. + */ + int BMI_GetInputItemCount() { return (int)this->bmi_input_vars.size(); } + + //-------------------------- + + /** + Basic Model Interface method that returns a list of the variable names that can be set with @ref BMI_SetValue. + @retval A list of the variable names that can be set with @ref BMI_SetValue. + + @see + @ref BMI_GetInputItemCount, + @ref BMI_GetVarItemsize, + @ref BMI_GetVarNbytes, + @ref BMI_GetVarType, + @ref BMI_GetVarUnits, + @ref BMI_SetValue. + @par C++ Example: + @htmlonly + +
+			std::vector< std::string > InputVarNames = phreeqc_rm.BMI_GetInputVarNames();
+			int count = phreeqc_rm.BMI_GetInputItemCount();
+			oss << "BMI_SetValue variables:\n";
+			for (size_t i = 0; i < count; i++)
+			{
+				oss << "  " << i << "  " << InputVarNames[i] << "\n";
+				oss << "     Type:        " << phreeqc_rm.BMI_GetVarType(InputVarNames[i]) << "\n";
+				oss << "     Units:       " << phreeqc_rm.BMI_GetVarUnits(InputVarNames[i]) << "\n";
+				oss << "     Total bytes: " << phreeqc_rm.BMI_GetVarNbytes(InputVarNames[i]) << "\n";
+				oss << "     Item bytes:  " << phreeqc_rm.BMI_GetVarItemsize(InputVarNames[i]) << "\n";
+				oss << "     Dim:         " << phreeqc_rm.BMI_GetVarNbytes(InputVarNames[i]) /
+											   phreeqc_rm.BMI_GetVarItemsize(InputVarNames[i]) << "\n";
+			}
+	
+
+ @endhtmlonly + @par MPI: + Called by root. + */ + std::vector< std::string > BMI_GetInputVarNames() { return this->bmi_input_vars; } + + //-------------------------- + + /** + Basic Model Interface method that returns count of output variables that can be retrieved with @ref BMI_GetValue. + @retval Count of output variables that can be retrieved with @ref BMI_GetValue. + + @see + @ref BMI_GetOutputVarNames, + @ref BMI_GetValue, + @ref BMI_GetVarItemsize, + @ref BMI_GetVarNbytes, + @ref BMI_GetVarType, + @ref BMI_GetVarUnits. + @par C++ Example: + @htmlonly + +
+			std::vector< std::string > OutputVarNames = phreeqc_rm.BMI_GetOutputVarNames();
+			int count = phreeqc_rm.BMI_GetOutputItemCount();
+			oss << "BMI_GetValue variables:\n";
+			for (size_t i = 0; i < count; i++)
+			{
+				oss << "  " << i << "  " << OutputVarNames[i] << "\n";
+				oss << "     Type:        " << phreeqc_rm.BMI_GetVarType(OutputVarNames[i]) << "\n";
+				oss << "     Units:       " << phreeqc_rm.BMI_GetVarUnits(OutputVarNames[i]) << "\n";
+				oss << "     Total bytes: " << phreeqc_rm.BMI_GetVarNbytes(OutputVarNames[i]) << "\n";
+				oss << "     Item bytes:  " << phreeqc_rm.BMI_GetVarItemsize(OutputVarNames[i]) << "\n";
+				oss << "     Dim:         " << phreeqc_rm.BMI_GetVarNbytes(OutputVarNames[i]) /
+											   phreeqc_rm.BMI_GetVarItemsize(OutputVarNames[i]) << "\n";
+			}
+	
+
+ @endhtmlonly + @par MPI: + Called by root. + */ + int BMI_GetOutputItemCount() { return (int)this->bmi_output_vars.size(); } + + //-------------------------- + + /** + Basic Model Interface method that returns a list of the variable names that can be retrieved with @ref BMI_GetValue. + @retval A list of the variable names that can be retrieved with @ref BMI_GetValue. + + @see + @ref BMI_GetOutputItemCount, + @ref BMI_GetValue, + @ref BMI_GetVarItemsize, + @ref BMI_GetVarNbytes, + @ref BMI_GetVarType, + @ref BMI_GetVarUnits. + @par C++ Example: + @htmlonly + +
+			std::vector< std::string > OutputVarNames = phreeqc_rm.BMI_GetOutputVarNames();
+			int count = phreeqc_rm.BMI_GetOutputItemCount();
+			oss << "BMI_GetValue variables:\n";
+			for (size_t i = 0; i < count; i++)
+			{
+				oss << "  " << i << "  " << OutputVarNames[i] << "\n";
+				oss << "     Type:        " << phreeqc_rm.BMI_GetVarType(OutputVarNames[i]) << "\n";
+				oss << "     Units:       " << phreeqc_rm.BMI_GetVarUnits(OutputVarNames[i]) << "\n";
+				oss << "     Total bytes: " << phreeqc_rm.BMI_GetVarNbytes(OutputVarNames[i]) << "\n";
+				oss << "     Item bytes:  " << phreeqc_rm.BMI_GetVarItemsize(OutputVarNames[i]) << "\n";
+				oss << "     Dim:         " << phreeqc_rm.BMI_GetVarNbytes(OutputVarNames[i]) /
+											   phreeqc_rm.BMI_GetVarItemsize(OutputVarNames[i]) << "\n";
+			}
+	
+
+ @endhtmlonly + @par MPI: + Called by root. + */ + std::vector< std::string > BMI_GetOutputVarNames() { return this->bmi_output_vars; }; + + //-------------------------- + + /** + Basic Model Interface method that returns the current simulation time step, in seconds. (Same as @ref GetTimeStep.) + The reaction module does not change the time-step value, so the + returned value is equal to the last time step set by + @ref BMI_SetValue("TimeStep", time_step) or @ref SetTimeStep. + @retval The current simulation time step, in seconds. + @see + @ref BMI_GetCurrentTime, + @ref BMI_GetEndTime, + @ref BMI_SetValue, + @ref GetTime, + @ref GetTimeStep, + @ref SetTime, + @ref SetTimeStep. + @par C++ Example: + @htmlonly + +
+	std::cout << "Current time step: "
+		 << BMI_GetTimeStep()
+		 << " seconds\n";
+	
+
+ @endhtmlonly + @par MPI: + Called by root. + */ + double BMI_GetTimeStep() { return this->GetTimeStep(); } + + //-------------------------- + + /** + Basic Model Interface method that returns the time units of PhreeqcRM. + All time units are seconds for PhreeqcRM. + @retval Returns the string "seconds". + @see + @ref BMI_GetCurrentTime, + @ref BMI_GetEndTime, + @ref BMI_GetTimeStep, + @ref BMI_SetValue, + @ref GetTime, + @ref GetTimeStep, + @ref SetTime, + @ref SetTimeStep. + @par C++ Example: + @htmlonly + +
+	std::cout << "PhreeqcRM time units are "
+		 << BMI_GetTimeUnits() << ".\n";
+	
+
+ @endhtmlonly + @par MPI: + Called by root. + */ + std::string BMI_GetTimeUnits() { return "seconds"; }; + + //-------------------------- + + /** + Basic Model Interface method that retrieves model variables. Only variables in the list + provided by @ref BMI_GetOutputVarNames can be retrieved. The BMI interface to PhreeqcRM is + only partial, and provides only the most basic functions. The native PhreeqcRM methods (those without the the BMI_ + prefix) provide a complete interface. + @param name Name of the variable to retrieve. + @param dest Variable in which to place results. + + Variable names for the first argument (@a name) and variable type of the + second argument (@a dest). + @n "ComponentCount", @a dest: int; + @n "Components", @a dest: std::vector< std::string >; + @n "Concentrations", @a dest: std::vector< double >; + @n "CurrentSelectedOutputUserNumber", @a dest: int; + @n "Density", @a dest: std::vector< double >; + @n "ErrorString", @a dest: std::string; + @n "FilePrefix", @a dest: std::string; + @n "Gfw", @a dest: std::vector< double >; + @n "GridCellCount", @a dest: int; + @n "InputVarNames", @a dest: std::vector< std::string >; + @n "OutputVarNames", @a dest: std::vector< std::string >; + @n "Porosity", @a dest: std::vector< double >; + @n "Pressure", @a dest: std::vector< double >; + @n "Saturation", @a dest: std::vector< double >; + @n "SelectedOutput", @a dest: std::vector< double >; + @n "SelectedOutputColumnCount", @a dest: int; + @n "SelectedOutputCount", @a dest: int; + @n "SelectedOutputHeadings", @a dest: std::vector< std::string >; + @n "SelectedOutputOn", @a dest: bool; + @n "SelectedOutputRowCount", @a dest: int; + @n "SolutionVolume", @a dest: std::vector< double >; + @n "Temperature", @a dest: std::vector< double >; + @n "Time", @a dest: double; + @n "TimeStep", @a dest: double. + + @see + @ref BMI_GetOutputVarNames, + @ref BMI_GetOutputItemCount, + @ref BMI_GetVarItemsize, + @ref BMI_GetVarNbytes, + @ref BMI_GetVarType, + @ref BMI_GetVarUnits, + @ref BMI_SetValue. + @par C++ Example: + @htmlonly + +
+		std::vector< double > bmi_density;
+		phreeqc_rm.BMI_GetValue("Density", bmi_density);
+		std::vector< std::string > bmi_comps;
+		phreeqc_rm.BMI_GetValue("Components", bmi_comps);
+	
+
+ @endhtmlonly + @par MPI: + Called by root, workers must be in the loop of @ref MpiWorker. + */ + void BMI_GetValue(std::string name, bool& dest); + /*! + * \overload void BMI_GetValue(std::string name, double& dest) + */ + void BMI_GetValue(std::string name, double& dest); + /*! + * \overload void BMI_GetValue(std::string name, int& dest) + */ + void BMI_GetValue(std::string name, int& dest); + /*! + * \overload void BMI_GetValue(std::string name, std::string& dest) + */ + void BMI_GetValue(std::string name, std::string& dest); + /*! + * \overload void BMI_GetValue(std::string name, std::vector < double >& dest) + */ + void BMI_GetValue(std::string name, std::vector < double >& dest); + /*! + * \overload void BMI_GetValue(std::string name, std::vector < std::string >& dest) + */ + void BMI_GetValue(std::string name, std::vector < std::string >& dest); + /*! + * \overload void BMI_GetValue(std::string name, void* dest) + */ + void BMI_GetValue(std::string name, void* dest); + + //-------------------------- + + /** + Basic Model Interface method that retrieves size of an + individual item that can be set or retrived. + Sizes may be sizeof(int), sizeof(double), + or a character length for string variables. Only variables in the list + provided by @ref BMI_GetInputVarNames can be set. + Only variables in the list + provided by @ref BMI_GetOutputVarNames can be retrieved. + @param name Name of the variable to retrieve size. + @retval Size of one element of variable. + + @see + @ref BMI_GetInputVarNames, + @ref BMI_GetInputItemCount, + @ref BMI_GetOutputVarNames, + @ref BMI_GetOutputItemCount, + @ref BMI_GetValue, + @ref BMI_GetVarNbytes, + @ref BMI_SetValue. + @par C++ Example: + @htmlonly + +
+		int nbytes = phreeqc_rm.BMI_GetVarNbytes("Temperature");
+		int item_size = phreeqc_rm.BMI_GetVarItemSize("Temperature");
+		int dim = nbytes/item_size;
+		std::vector< double > bmi_temperature(dim, 25.0);
+		phreeqc_rm.BMI_SetValue("Temperature", bmi_temperature);
+	
+
+ @endhtmlonly + @par MPI: + Called by root. + */ + int BMI_GetVarItemsize(std::string name); + + //-------------------------- + + /** + Basic Model Interface method that retrieves the total number of bytes that are set for a variable with + @ref BMI_SetValue or retrieved for a variable with @ref BMI_GetValue. + Only variables in the list + provided by @ref BMI_GetInputVarNames can be set. + Only variables in the list + provided by @ref BMI_GetOutputVarNames can be retrieved. + @param name Name of the variable to retrieve total bytes. + @retval Total number of bytes set or retrieved for variable. + @see + @ref BMI_GetInputVarNames, + @ref BMI_GetInputItemCount, + @ref BMI_GetOutputVarNames, + @ref BMI_GetOutputItemCount, + @ref BMI_GetValue, + @ref BMI_GetVarItemsize, + @ref BMI_SetValue. + @par C++ Example: + @htmlonly + +
+		int nbytes = phreeqc_rm.BMI_GetVarNbytes("Temperature");
+		int item_size = phreeqc_rm.BMI_GetVarItemSize("Temperature");
+		int dim = nbytes/item_size;
+		std::vector< double > bmi_temperature(dim, 25.0);
+		phreeqc_rm.BMI_SetValue("Temperature", bmi_temperature);
+	
+
+ @endhtmlonly + @par MPI: + Called by root. + */ + int BMI_GetVarNbytes(std::string name); + + //-------------------------- + + /** + Basic Model Interface method that retrieves the type of a variable that can be set with + @ref BMI_SetValue or retrieved with @ref BMI_GetValue. Types are "int", "double", or "string". + Only variables in the list + provided by @ref BMI_GetInputVarNames can be set. + Only variables in the list + provided by @ref BMI_GetOutputVarNames can be retrieved. + + @param name Name of the variable to retrieve type. + @retval Character string of variable type. + + @see + @ref BMI_GetInputVarNames, + @ref BMI_GetInputItemCount, + @ref BMI_GetOutputVarNames, + @ref BMI_GetOutputItemCount, + @ref BMI_GetVarUnits. + @par C++ Example: + @htmlonly + +
+	std::vector< std::string > OutputVarNames = phreeqc_rm.BMI_GetOutputVarNames();
+	int count = phreeqc_rm.BMI_GetOutputItemCount();
+	oss << "BMI_GetValue variables:\n";
+	for (size_t i = 0; i < count; i++)
+	{
+		oss << "  " << i << "  " << OutputVarNames[i] << "\n";
+		oss << "     Type:        " << phreeqc_rm.BMI_GetVarType(OutputVarNames[i]) << "\n";
+		oss << "     Units:       " << phreeqc_rm.BMI_GetVarUnits(OutputVarNames[i]) << "\n";
+		oss << "     Total bytes: " << phreeqc_rm.BMI_GetVarNbytes(OutputVarNames[i]) << "\n";
+		oss << "     Item bytes:  " << phreeqc_rm.BMI_GetVarItemsize(OutputVarNames[i]) << "\n";
+		oss << "     Dim:         " << phreeqc_rm.BMI_GetVarNbytes(OutputVarNames[i]) /
+										phreeqc_rm.BMI_GetVarItemsize(OutputVarNames[i]) << "\n";
+	}
+	
+
+ @endhtmlonly + @par MPI: + Called by root. + */ + std::string BMI_GetVarType(std::string name); + + //-------------------------- + + /** + Basic Model Interface method that retrieves the units of a variable that can be set with + @ref BMI_SetValue or retrieved with @ref BMI_GetValue. + Only variables in the list + provided by @ref BMI_GetInputVarNames can be set. + Only variables in the list + provided by @ref BMI_GetOutputVarNames can be retrieved. + + @param name Name of the variable to retrieve type. + @retval Character string of units for variable. + @see + @ref BMI_GetInputVarNames, + @ref BMI_GetInputItemCount, + @ref BMI_GetOutputVarNames, + @ref BMI_GetOutputItemCount, + @ref BMI_GetVarType. + @par C++ Example: + @htmlonly + +
+	std::vector< std::string > OutputVarNames = phreeqc_rm.BMI_GetOutputVarNames();
+	int count = phreeqc_rm.BMI_GetOutputItemCount();
+	oss << "BMI_GetValue variables:\n";
+	for (size_t i = 0; i < count; i++)
+	{
+		oss << "  " << i << "  " << OutputVarNames[i] << "\n";
+		oss << "     Type:        " << phreeqc_rm.BMI_GetVarType(OutputVarNames[i]) << "\n";
+		oss << "     Units:       " << phreeqc_rm.BMI_GetVarUnits(OutputVarNames[i]) << "\n";
+		oss << "     Total bytes: " << phreeqc_rm.BMI_GetVarNbytes(OutputVarNames[i]) << "\n";
+		oss << "     Item bytes:  " << phreeqc_rm.BMI_GetVarItemsize(OutputVarNames[i]) << "\n";
+		oss << "     Dim:         " << phreeqc_rm.BMI_GetVarNbytes(OutputVarNames[i]) /
+										phreeqc_rm.BMI_GetVarItemsize(OutputVarNames[i]) << "\n";
+	}
+	
+
+ @endhtmlonly + @par MPI: + Called by root. + */ + std::string BMI_GetVarUnits(std::string name); + + //-------------------------- +#ifdef USE_YAML + /** + Basic Model Interface method that can be used to initialize a PhreeqcRM instance. This method is equivalent to + @ref InitializeYAML. A YAML file can be used in initialization. The file contains a YAML map of PhreeqcRM methods + and the arguments corresponding to the method. For example, + @htmlonly + +
+	LoadDatabase: phreeqc.dat
+	RunFile:
+	  workers: true
+	  initial_phreeqc: true
+	  utility: true
+	  chemistry_name: advect.pqi
+	
+
+ @endhtmlonly + + BMI_Initialize will read the YAML file and execute the specified methods with the specified arguments. Using YAML + terminology, the argument(s) for a method may be a scalar, a sequence, or a map, depending if the argument is + a single item, a single vector, or there are multiple arguments. In the case of a map, the name associated + with each argument (for example "chemistry_name" above) is arbitrary. The names of the map keys for map + arguments are not used in parsing the YAML file; only the order of the arguments is important. + + The PhreeqcRM methods that can be specified in a YAML file include: + @htmlonly + +
+	CloseFiles(void);
+	CreateMapping(std::vector< int >& grid2chem);
+	DumpModule();
+	FindComponents();
+	InitialPhreeqc2Module(std::vector< int > initial_conditions1);
+	InitialPhreeqc2Module(std::vector< int > initial_conditions1, std::vector< int > initial_conditions2, std::vector< double > fraction1);
+	InitialPhreeqcCell2Module(int n, std::vector< int > cell_numbers);
+	LoadDatabase(std::string database);
+	OpenFiles(void);
+	OutputMessage(std::string str);
+	RunCells(void);
+	RunFile(bool workers, bool initial_phreeqc, bool utility, std::string chemistry_name);
+	RunString(bool workers, bool initial_phreeqc, bool utility, std::string input_string);
+	ScreenMessage(std::string str);
+	SetComponentH2O(bool tf);
+	SetConcentrations(std::vector< double > c);
+	SetCurrentSelectedOutputUserNumber(int n_user);
+	SetDensity(std::vector< double > density);
+	SetDumpFileName(std::string dump_name);
+	SetErrorHandlerMode(int mode);
+	SetErrorOn(bool tf);
+	SetFilePrefix(std::string prefix);
+	SetGasCompMoles(std::vector< double > gas_moles);
+	SetGasPhaseVolume(std::vector< double > gas_volume);
+	SetPartitionUZSolids(bool tf);
+	SetPorosity(std::vector< double > por);
+	SetPressure(std::vector< double > p);
+	SetPrintChemistryMask(std::vector< int > cell_mask);
+	SetPrintChemistryOn(bool workers, bool initial_phreeqc, bool utility);
+	SetRebalanceByCell(bool tf);
+	SetRebalanceFraction(double f);
+	SetRepresentativeVolume(std::vector< double > rv);
+	SetSaturation(std::vector< double > sat);
+	SetScreenOn(bool tf);
+	SetSelectedOutputOn(bool tf);
+	SetSpeciesSaveOn(bool save_on);
+	SetTemperature(std::vector< double > t);
+	SetTime(double time);
+	SetTimeConversion(double conv_factor);
+	SetTimeStep(double time_step);
+	SetUnitsExchange(int option);
+	SetUnitsGasPhase(int option);
+	SetUnitsKinetics(int option);
+	SetUnitsPPassemblage(int option);
+	SetUnitsSolution(int option);
+	SetUnitsSSassemblage(int option);
+	SetUnitsSurface(int option);
+	SpeciesConcentrations2Module(std::vector< double > species_conc);
+	StateSave(int istate);
+	StateApply(int istate);
+	StateDelete(int istate);
+	UseSolutionDensityVolume(bool tf);
+	WarningMessage(std::string warnstr);
+	
+
+ @endhtmlonly + @see + @ref BMI_Update. + @par C++ Example: + @htmlonly + +
+			int nthreads = 0;
+			std::string yaml_file = "myfile.yaml";
+			int nxyz = GetGridCellCountYAML(yaml_file);
+			PhreeqcRM phreeqc_rm(nxyz, nthreads);
+			phreeqc_rm.BMI_Initialize(yaml_file);
+			int ncomps;
+			phreeqc_rm.BMI_GetValue("ComponentCount", &ncomps);
+			int ngrid;
+			phreeqc_rm.BMI_GetValue("GridCellCount", ngrid);
+			std::vector< double > c;
+			phreeqc_rm.BMI_GetValue("Concentrations", c);
+			phreeqc_rm.BMI_SetValue("TimeStep", 86400);
+			for(double time = 0; time < 864000; time+=86400)
+			{
+				// Take a transport time step here and update the vector c.
+				phreeqc_rm.BMI_SetValue("Time", time);
+				phreeqc_rm.BMI_SetValue("Concentrations", c);
+				phreeqc_rm.BMI_Update();
+				phreeqc_rm.BMI_GetValue("Concentrations", c);
+			}
+	
+
+ @endhtmlonly + @par MPI: + Called by root, workers must be in the loop of @ref MpiWorker. + */ + void BMI_Initialize(std::string config_file) { InitializeYAML(config_file); }; +#endif + //-------------------------- + + /** + Basic Model Interface method that sets model variables. Only variables in the list + provided by @ref BMI_GetInputVarNames can be set. The BMI interface to PhreeqcRM is + only partial, and provides only the most basic functions. The native PhreeqcRM methods (those without the the BMI_ + prefix) provide a complete interface, and it is expected that the native methods will be used in preference to the BMI_ + methods. + + Variable names for the first argument + of BMI_SetValue and the equivalent PhreeqcRM method are as follows: + "Concentrations", @ref SetConcentrations; + "Density", @ref SetDensity; + "FilePrefix", @ref SetFilePrefix; + "NthSelectedOutput", @ref SetNthSelectedOutput; + "Porosity", @ref SetPorosity; + "Pressure", @ref SetPressure; + "Saturation", @ref SetSaturation; + "SelectedOutputOn", @ref SetSelectedOutputOn; + "Temperature", @ref SetTemperature; + "Time", @ref SetTime; + "TimeStep", @ref SetTimeStep. + + @see + @ref BMI_GetInputVarNames, + @ref BMI_GetInputItemCount,, + @ref BMI_GetValue, + @ref BMI_GetVarItemsize, + @ref BMI_GetVarNbytes, + @ref BMI_GetVarType, + @ref BMI_GetVarUnits. + @par C++ Example: + @htmlonly + +
+			std::vector< double > bmi_temperature(ngrid, 28.0);
+			phreeqc_rm.BMI_SetValue("Temperature", bmi_temperature);
+	
+
+ @endhtmlonly + @par MPI: + Called by root, workers must be in the loop of @ref MpiWorker. + */ + void BMI_SetValue(std::string name, void* src); + void BMI_SetValue(std::string name, bool& src); + void BMI_SetValue(std::string name, double& src); + void BMI_SetValue(std::string name, int& src); + void BMI_SetValue(std::string name, const std::string& src); + void BMI_SetValue(std::string name, std::vector < double >& src); + void BMI_SetValue(std::string name, std::vector < int >& src); + void BMI_SetValue(std::string name, std::vector < std::string >& src); + + //-------------------------- + /** + Basic Model Interface method that runs PhreeqcRM for one time step. This method is equivalent to + @ref RunCells. PhreeqcRM will equilibrate the solutions with all equilibrium reactants (EQUILIBRIUM_PHASES, + EXCHANGE, GAS_PHASE, SOLID_SOLUTIONS, and SURFACE) and + integrate KINETICS reactions for the specified time step (@ref SetTimeStep). + @see + @ref BMI_Initialize. + @par C++ Example: + @htmlonly + +
+			PhreeqcRM phreeqc_rm(nxyz, nthreads);
+			phreeqc_rm.BMI_Initialize("myfile.yaml");
+			int ncomps;
+			phreeqc_rm.BMI_GetValue("ComponentCount", &ncomps);
+			int ngrid;
+			phreeqc_rm.BMI_GetValue("GridCellCount", ngrid);
+			std::vector< double > c;
+			phreeqc_rm.BMI_GetValue("Concentrations", c);
+			phreeqc_rm.BMI_SetValue("TimeStep", 86400);
+			for(double time = 0; time < 864000; time+=86400)
+			{
+				// Take a transport time step here and update the vector c.
+				phreeqc_rm.BMI_SetValue("Time", time);
+				phreeqc_rm.BMI_SetValue("Concentrations", c);
+				phreeqc_rm.BMI_Update();
+				phreeqc_rm.BMI_GetValue("Concentrations", c);
+			}
+	
+
+ @endhtmlonly + @par MPI: + Called by root, workers must be in the loop of @ref MpiWorker. + */ + void BMI_Update(void) { this->RunCells(); }; +#ifdef NOT_IMPLEMENTED + void BMI_UpdateUntil(double time) + { + //throw LetItThrow("Not implemented"); + ErrorMessage("Not implemented"); + throw PhreeqcRMStop(); + } + int BMI_GetVarGrid(std::string name) + { + //throw LetItThrow("Not applicable"); + ErrorMessage("Not applicable"); + throw PhreeqcRMStop(); + }; + std::string BMI_GetVarLocation(std::string name) + { + //throw LetItThrow("Not applicable"); + ErrorMessage("Not applicable"); + throw PhreeqcRMStop(); + }; + double BMI_GetStartTime() + { + //throw LetItThrow("Not implemented"); + ErrorMessage("Not implemented"); + throw PhreeqcRMStop(); + }; + void* BMI_GetValuePtr(std::string name) + { + //throw LetItThrow("Not implemented"); + ErrorMessage("Not implemented"); + throw PhreeqcRMStop(); + } + void BMI_GetValueAtIndices(std::string name, void* dest, int* inds, int count) + { + //throw LetItThrow("Not implemented"); + ErrorMessage("Not implemented"); + throw PhreeqcRMStop(); + }; + void BMI_SetValueAtIndices(std::string name, int* inds, int len, void* src) + { + //throw LetItThrow("Not implemented"); + ErrorMessage("Not implemented"); + throw PhreeqcRMStop(); + }; + int BMI_GetGridRank(const int grid) + { + //throw LetItThrow("Not applicable"); + ErrorMessage("Not applicable"); + throw PhreeqcRMStop(); + }; + int BMI_GetGridSize(const int grid) + { + //throw LetItThrow("Not applicable"); + ErrorMessage("Not applicable"); + throw PhreeqcRMStop(); + }; + std::string BMI_GetGridType(const int grid) + { + //throw LetItThrow("Not applicable"); + ErrorMessage("Not applicable"); + throw PhreeqcRMStop(); + }; + void BMI_GetGridShape(const int grid, int* shape) + { + //throw LetItThrow("Not applicable"); + ErrorMessage("Not applicable"); + throw PhreeqcRMStop(); + }; + void BMI_GetGridSpacing(const int grid, double* spacing) + { + //throw LetItThrow("Not applicable"); + ErrorMessage("Not applicable"); + throw PhreeqcRMStop(); + }; + void GetGridOrigin(const int grid, double* origin) + { + //throw LetItThrow("Not applicable"); + ErrorMessage("Not applicable"); + throw PhreeqcRMStop(); + }; + void BMI_GetGridX(const int grid, double* x) + { + //throw LetItThrow("Not applicable"); + ErrorMessage("Not applicable"); + throw PhreeqcRMStop(); + }; + void BMI_GetGridY(const int grid, double* y) + { + //throw LetItThrow("Not applicable"); + ErrorMessage("Not applicable"); + throw PhreeqcRMStop(); + }; + void BMI_GetGridZ(const int grid, double* z) + { + //throw LetItThrow("Not applicable"); + ErrorMessage("Not applicable"); + throw PhreeqcRMStop(); + }; + + int BMI_GetGridNodeCount(const int grid) + { + //throw LetItThrow("Not applicable"); + ErrorMessage("Not applicable"); + throw PhreeqcRMStop(); + }; + int BMI_GetGridEdgeCount(const int grid) + { + //throw LetItThrow("Not applicable"); + ErrorMessage("Not applicable"); + throw PhreeqcRMStop(); + }; + int BMI_GetGridFaceCount(const int grid) + { + //throw LetItThrow("Not applicable"); + ErrorMessage("Not applicable"); + throw PhreeqcRMStop(); + }; + void BMI_GetGridEdgeNodes(const int grid, int* edge_nodes) + { + //throw LetItThrow("Not applicable"); + ErrorMessage("Not applicable"); + throw PhreeqcRMStop(); + }; + void BMI_GetGridFaceEdges(const int grid, int* face_edges) + { + //throw LetItThrow("Not applicable"); + ErrorMessage("Not applicable"); + throw PhreeqcRMStop(); + }; + void BMI_GetGridFaceNodes(const int grid, int* face_nodes) + { + //throw LetItThrow("Not applicable"); + ErrorMessage("Not applicable"); + throw PhreeqcRMStop(); + }; + void BMI_GetGridNodesPerFace(const int grid, int* nodes_per_face) + { + //throw LetItThrow("Not applicable"); + ErrorMessage("Not applicable"); + throw PhreeqcRMStop(); + }; +#endif +private: + void BMI_MakeVarMap(); +// End BMI data and methods diff --git a/src/BMI_not_implemented.inc b/src/BMI_not_implemented.inc new file mode 100644 index 000000000..4046fd975 --- /dev/null +++ b/src/BMI_not_implemented.inc @@ -0,0 +1,226 @@ + + ! ==================================================== + ! Functions not implemented + ! ==================================================== + integer FUNCTION bmif_get_var_location(id, var, location) + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER, INTENT(in) :: id + CHARACTER(len=*), INTENT(in) :: var + CHARACTER(len=*), INTENT(inout) :: location + bmif_get_var_location = BMI_FAILURE + END FUNCTION bmif_get_var_location + + !> \overload + INTEGER FUNCTION bmif_get_value_float(id, var, dest) + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER, INTENT(in) :: id + CHARACTER(len=*), INTENT(in) :: var + real(kind=4), INTENT(inout) :: dest + bmif_get_value_float = BMI_FAILURE + return + END FUNCTION bmif_get_value_float + + !> \overload + INTEGER FUNCTION bmif_get_value_ptr_float(id, var, dest) + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER, INTENT(in) :: id + CHARACTER(len=*), INTENT(in) :: var + real(kind=4), pointer, INTENT(inout) :: dest + bmif_get_value_ptr_float = BMI_FAILURE + return + END FUNCTION bmif_get_value_ptr_float + + !> \overload + INTEGER FUNCTION get_value_at_indices_double(id, var, dest, inds) + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER, INTENT(in) :: id + CHARACTER(len=*), INTENT(in) :: var + real(kind=8), INTENT(inout) :: dest(:) + integer, INTENT(inout) :: inds(:) + get_value_at_indices_double = BMI_FAILURE + return + END FUNCTION get_value_at_indices_double + + !> \overload + INTEGER FUNCTION get_value_at_indices_float(id, var, dest, inds) + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER, INTENT(in) :: id + CHARACTER(len=*), INTENT(in) :: var + real(kind=4), INTENT(inout) :: dest(:) + integer, INTENT(in) :: inds(:) + get_value_at_indices_float = BMI_FAILURE + return + END FUNCTION get_value_at_indices_float + + !> \overload + INTEGER FUNCTION get_value_at_indices_int(id, var, dest, inds) + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER, INTENT(in) :: id + CHARACTER(len=*), INTENT(in) :: var + integer, INTENT(inout) :: dest(:) + integer, INTENT(in) :: inds(:) + get_value_at_indices_int = BMI_FAILURE + return + END FUNCTION get_value_at_indices_int + + !> \overload + INTEGER FUNCTION bmif_set_value_float(id, var, src) + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER, INTENT(in) :: id + CHARACTER(len=*), INTENT(in) :: var + real(kind=4), INTENT(inout) :: src + bmif_set_value_float = BMI_FAILURE + return + END FUNCTION bmif_set_value_float + + !> \overload + INTEGER FUNCTION set_value_at_indices_double(id, var, dest, inds) + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER, INTENT(in) :: id + CHARACTER(len=*), INTENT(in) :: var + real(kind=8), INTENT(inout) :: dest(:) + integer, INTENT(inout) :: inds(:) + set_value_at_indices_double = BMI_FAILURE + return + END FUNCTION set_value_at_indices_double + + !> \overload + INTEGER FUNCTION set_value_at_indices_float(id, var, dest, inds) + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER, INTENT(in) :: id + CHARACTER(len=*), INTENT(in) :: var + real(kind=4), INTENT(inout) :: dest(:) + integer, INTENT(in) :: inds(:) + set_value_at_indices_float = BMI_FAILURE + return + END FUNCTION set_value_at_indices_float + + !> \overload + INTEGER FUNCTION set_value_at_indices_int(id, var, dest, inds) + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER, INTENT(in) :: id + CHARACTER(len=*), INTENT(in) :: var + integer, INTENT(inout) :: dest(:) + integer, INTENT(in) :: inds(:) + set_value_at_indices_int = BMI_FAILURE + return + END FUNCTION set_value_at_indices_int + + + ! Get the dimensions of the computational grid. + integer function bmif_get_grid_shape(grid, shape) result(bmi_status) + integer, intent(in) :: grid + integer, dimension(:), intent(inout) :: shape + bmi_status = BMI_FAILURE + return + end function bmif_get_grid_shape + + ! Get distance between nodes of the computational grid. + integer function bmif_get_grid_spacing(grid, spacing) result(bmi_status) + integer, intent(in) :: grid + double precision, dimension(:), intent(inout) :: spacing + bmi_status = BMI_FAILURE + return + end function bmif_get_grid_spacing + + ! Get coordinates of the origin of the computational grid. + integer function bmif_get_grid_origin(grid, origin) result(bmi_status) + integer, intent(in) :: grid + double precision, dimension(:), intent(inout) :: origin + bmi_status = BMI_FAILURE + return + end function bmif_get_grid_origin + + ! Get the x-coordinates of the nodes of a computational grid. + integer function bmif_get_grid_x(grid, x) result(bmi_status) + integer, intent(in) :: grid + double precision, dimension(:), intent(inout) :: x + bmi_status = BMI_FAILURE + return + end function bmif_get_grid_x + + ! Get the y-coordinates of the nodes of a computational grid. + integer function bmif_get_grid_y(grid, y) result(bmi_status) + integer, intent(in) :: grid + double precision, dimension(:), intent(inout) :: y + bmi_status = BMI_FAILURE + return + end function bmif_get_grid_y + + ! Get the z-coordinates of the nodes of a computational grid. + integer function bmif_get_grid_z(grid, z) result(bmi_status) + integer, intent(in) :: grid + double precision, dimension(:), intent(inout) :: z + bmi_status = BMI_FAILURE + return + end function bmif_get_grid_z + + ! Get the number of nodes in an unstructured grid. + integer function bmif_get_grid_node_count(grid, count) result(bmi_status) + integer, intent(in) :: grid + integer, intent(inout) :: count + bmi_status = BMI_FAILURE + return + end function bmif_get_grid_node_count + + ! Get the number of edges in an unstructured grid. + integer function bmif_get_grid_edge_count(grid, count) result(bmi_status) + integer, intent(in) :: grid + integer, intent(inout) :: count + bmi_status = BMI_FAILURE + return + end function bmif_get_grid_edge_count + + ! Get the number of faces in an unstructured grid. + integer function bmif_get_grid_face_count(grid, count) result(bmi_status) + integer, intent(in) :: grid + integer, intent(inout) :: count + bmi_status = BMI_FAILURE + return + end function bmif_get_grid_face_count + + ! Get the edge-node connectivity. + integer function bmif_get_grid_edge_nodes(grid, edge_nodes) & + result(bmi_status) + integer, intent(in) :: grid + integer, dimension(:), intent(inout) :: edge_nodes + bmi_status = BMI_FAILURE + return + end function bmif_get_grid_edge_nodes + + ! Get the face-edge connectivity. + integer function bmif_get_grid_face_edges(grid, face_edges) & + result(bmi_status) + integer, intent(in) :: grid + integer, dimension(:), intent(inout) :: face_edges + bmi_status = BMI_FAILURE + return + end function bmif_get_grid_face_edges + + ! Get the face-node connectivity. + integer function bmif_get_grid_face_nodes(grid, face_nodes) & + result(bmi_status) + integer, intent(in) :: grid + integer, dimension(:), intent(inout) :: face_nodes + bmi_status = BMI_FAILURE + return + end function bmif_get_grid_face_nodes + + ! Get the number of nodes for each face. + integer function bmif_get_grid_nodes_per_face(grid, nodes_per_face) & + result(bmi_status) + integer, intent(in) :: grid + integer, dimension(:), intent(inout) :: nodes_per_face + bmi_status = BMI_FAILURE + return + end function bmif_get_grid_nodes_per_face \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 000000000..2907cc9eb --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,3 @@ +if (SWIG_FOUND) + add_subdirectory(swig) +endif() diff --git a/src/IPhreeqcPhast/IPhreeqc/CVar.hxx b/src/IPhreeqcPhast/IPhreeqc/CVar.hxx index e0ad36877..9f2d1a32f 100644 --- a/src/IPhreeqcPhast/IPhreeqc/CVar.hxx +++ b/src/IPhreeqcPhast/IPhreeqc/CVar.hxx @@ -12,7 +12,7 @@ public: { ::VarInit(this); } - ~CVar(void) throw() + ~CVar(void) //throw() { Clear(); } diff --git a/src/IPhreeqcPhast/IPhreeqc/IPhreeqc.h b/src/IPhreeqcPhast/IPhreeqc/IPhreeqc.h index 93adac905..4c04c426e 100644 --- a/src/IPhreeqcPhast/IPhreeqc/IPhreeqc.h +++ b/src/IPhreeqcPhast/IPhreeqc/IPhreeqc.h @@ -1672,9 +1672,9 @@ Headings * FUNCTION SetBasicFortranCallback(ID,FCN) * INTEGER(KIND=4), INTENT(IN) :: ID * INTERFACE - * DOUBLE PRECISION FUNCTION FCN(x1, x2, str) - * DOUBLE PRECISION, INTENT(in) :: x1 - * DOUBLE PRECISION, INTENT(in) :: x2 + * real(kind=8) FUNCTION FCN(x1, x2, str) + * real(kind=8), INTENT(in) :: x1 + * real(kind=8), INTENT(in) :: x2 * CHARACTER(*), INTENT(in) :: str * END FUNCTION * END INTERFACE diff --git a/src/IPhreeqcPhast/IPhreeqc/IPhreeqc.hpp b/src/IPhreeqcPhast/IPhreeqc/IPhreeqc.hpp index 22bdf150d..c79957b5f 100644 --- a/src/IPhreeqcPhast/IPhreeqc/IPhreeqc.hpp +++ b/src/IPhreeqcPhast/IPhreeqc/IPhreeqc.hpp @@ -713,7 +713,7 @@ class IPQ_DLL_EXPORT IPhreeqc : public PHRQ_io * Sets a Fortran callback function for Basic programs. The syntax for the Basic command is * 10 result = CALLBACK(x1, x2, string$) * The syntax for the Fortran function is - * double precision my_callback(x1, x2, string), where x1 and x2 are double precision and string is a character variable. + * real(kind=8) my_callback(x1, x2, string), where x1 and x2 are real(kind=8) and string is a character variable. * @param fcn The name of a user-defined function. * @see SetBasicCallback */ diff --git a/src/IPhreeqcPhast/IPhreeqc/IPhreeqc_interface.F90 b/src/IPhreeqcPhast/IPhreeqc/IPhreeqc_interface.F90 index 6c726c832..45e6db0cd 100644 --- a/src/IPhreeqcPhast/IPhreeqc/IPhreeqc_interface.F90 +++ b/src/IPhreeqcPhast/IPhreeqc/IPhreeqc_interface.F90 @@ -688,7 +688,7 @@ END FUNCTION GetSelectedOutputValueF END INTERFACE INTEGER, INTENT(in) :: id, row, col INTEGER, INTENT(out) :: vtype - DOUBLE PRECISION, INTENT(out) :: dvalue + real(kind=8), INTENT(out) :: dvalue CHARACTER(len=*), INTENT(out) :: svalue INTEGER, INTENT(out), OPTIONAL :: slength INTEGER :: sz, sz_fortran @@ -898,9 +898,9 @@ INTEGER FUNCTION SetBasicFortranCallbackF(id, fcn) IMPLICIT NONE INTEGER, INTENT(in) :: id INTERFACE - DOUBLE PRECISION FUNCTION fcn(x1, x2, str, l) + real(kind=8) FUNCTION fcn(x1, x2, str, l) INTEGER, INTENT(in) :: l - DOUBLE PRECISION, INTENT(in) :: x1, x2 + real(kind=8), INTENT(in) :: x1, x2 CHARACTER, INTENT(in) :: str(*) END FUNCTION fcn END INTERFACE @@ -908,9 +908,9 @@ END FUNCTION SetBasicFortranCallbackF END INTERFACE INTEGER, INTENT(in) :: id INTERFACE - DOUBLE PRECISION FUNCTION fcn(x1, x2, str, l) + real(kind=8) FUNCTION fcn(x1, x2, str, l) INTEGER, INTENT(in) :: l - DOUBLE PRECISION, INTENT(in) :: x1, x2 + real(kind=8), INTENT(in) :: x1, x2 CHARACTER, INTENT(in) :: str(*) END FUNCTION fcn END INTERFACE diff --git a/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/cl1.cpp b/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/cl1.cpp index 107a8ad95..b0dd1be43 100644 --- a/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/cl1.cpp +++ b/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/cl1.cpp @@ -142,7 +142,7 @@ cl1(int k, int l, int m, int n, /* AT LEAST NKLMD COLUMNS USED FOR WORKSPACE. */ /* S INTEGER ARRAY OF SIZE AT LEAST KLMD, USED FOR */ /* WORKSPACE. */ -/* DOUBLE PRECISION DBLE */ +/* real(kind=8) DBLE */ /* REAL */ /* INITIALIZATION. */ diff --git a/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/gases.cpp b/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/gases.cpp index d64d2c973..b373068a7 100644 --- a/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/gases.cpp +++ b/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/gases.cpp @@ -624,7 +624,6 @@ int Phreeqc:: calc_fixed_volume_gas_pressures(void) /* ---------------------------------------------------------------------- */ { - int n_g = 0; LDBLE lp; class rxn_token *rxn_ptr; class phase *phase_ptr; @@ -645,7 +644,6 @@ calc_fixed_volume_gas_pressures(void) { if (!PR && phase_ptr->t_c > 0 && phase_ptr->p_c > 0) PR = true; - n_g++; } gas_phase_ptr->Set_total_moles(gas_phase_ptr->Get_total_moles() + gas_unknowns[i]->moles); } diff --git a/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/model.cpp b/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/model.cpp index 9bebfc87d..bf8d8fd7b 100644 --- a/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/model.cpp +++ b/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/model.cpp @@ -2543,7 +2543,6 @@ int Phreeqc:: calc_gas_pressures(void) /* ---------------------------------------------------------------------- */ { - int n_g = 0; LDBLE lp, V_m = 0; class rxn_token *rxn_ptr; std::vector phase_ptrs; @@ -2576,7 +2575,6 @@ calc_gas_pressures(void) phase_ptrs.push_back(phase_ptr); if (!PR && phase_ptr->t_c > 0 && phase_ptr->p_c > 0) PR = true; - n_g++; } if (iterations > 2 && gas_phase_ptr->Get_type() == cxxGasPhase::GP_VOLUME) { @@ -3778,7 +3776,6 @@ residuals(void) int converge; LDBLE l_toler; - LDBLE sum_residual; LDBLE sinh_constant; LDBLE sum, sum1; class master *master_ptr, *master_ptr1, *master_ptr2; @@ -3786,7 +3783,6 @@ residuals(void) int print_fail; std::vector cd_psi; print_fail = FALSE; - sum_residual = 0.0; sigmaddl = 0; sum = 0; /* @@ -4530,7 +4526,6 @@ residuals(void) * Store residuals in array */ my_array[((size_t)i + 1) * (count_unknowns + 1) - 1] = residual[i]; - sum_residual += fabs(residual[i]); } /* * Return diff --git a/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/pitzer.cpp b/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/pitzer.cpp index 77de08e5d..b71f24d31 100644 --- a/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/pitzer.cpp +++ b/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/pitzer.cpp @@ -52,7 +52,7 @@ pitzer_tidy(void) const char *string1, *string2; int i, j, order; int i0, i1, i2; - int count_pos, count_neg, count_neut, count[3], jj; + int count_neut, count[3], jj; LDBLE z0, z1; class pitz_param *pzp_ptr; class theta_param *theta_param_ptr; @@ -339,21 +339,21 @@ pitzer_tidy(void) i0 = pitz_params[i]->ispec[0]; i1 = pitz_params[i]->ispec[1]; i2 = pitz_params[i]->ispec[2]; - count_pos = count_neg = count_neut = 0; + count_neut = 0; for (j = 0; j <= 2; j++) { - if (spec[pitz_params[i]->ispec[j]]->z > 0) - { - count_pos++; - } + //if (spec[pitz_params[i]->ispec[j]]->z > 0) + //{ + // count_pos++; + //} if (spec[pitz_params[i]->ispec[j]]->z == 0) { count_neut++; } - if (spec[pitz_params[i]->ispec[j]]->z < 0) - { - count_neg++; - } + //if (spec[pitz_params[i]->ispec[j]]->z < 0) + //{ + // count_neg++; + //} } /* All neutral */ if (count_neut == 3) diff --git a/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/prep.cpp b/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/prep.cpp index 82b3125c2..0d26ba983 100644 --- a/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/prep.cpp +++ b/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/prep.cpp @@ -1980,14 +1980,13 @@ get_list_master_ptrs(const char* cptr, class master *master_ptr) * Output: space is allocated and a list of master species pointers is * returned. */ - int j, l, count_list; + int j, l; char token[MAX_LENGTH]; std::vector master_ptr_list; class master *master_ptr0; /* * Make list of master species pointers */ - count_list = 0; //master_ptr_list = unknown_alloc_master(); master_ptr0 = master_ptr; if (master_ptr0 == master_ptr->s->primary) @@ -2147,7 +2146,7 @@ mb_for_species_aq(int n) * by coef, usually moles. * mb_unknowns.coef - coefficient of s[n] in equation or relation */ - int i, j; + int i; class master *master_ptr; class unknown *unknown_ptr; @@ -2223,7 +2222,6 @@ mb_for_species_aq(int n) */ if (use.Get_surface_ptr() != NULL && s[n]->type < H2O && dl_type_x != cxxSurface::NO_DL) { - j = 0; for (i = 0; i < count_unknowns; i++) { if (x[i]->type == SURFACE_CB) @@ -2235,7 +2233,6 @@ mb_for_species_aq(int n) store_mb_unknowns(unknown_ptr, s_diff_layer[n][charge_ptr->Get_name()].Get_g_moles_address(), s[n]->z, s_diff_layer[n][charge_ptr->Get_name()].Get_dg_g_moles_address()); - j++; } } } diff --git a/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/spread.cpp b/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/spread.cpp index 77ada3e7b..5d7137b5d 100644 --- a/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/spread.cpp +++ b/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/spread.cpp @@ -1141,7 +1141,7 @@ copy_token_tab(std::string& token, const char **cptr) * EOL, * UNKNOWN. */ - int i, return_value; + int return_value; char c; /* * Strip leading spaces @@ -1180,7 +1180,6 @@ copy_token_tab(std::string& token, const char **cptr) /* * Begin copying to token */ - i = 0; for (;;) { c = **cptr; @@ -1197,7 +1196,6 @@ copy_token_tab(std::string& token, const char **cptr) { token.push_back(c); (*cptr)++; - i++; } } return (return_value); diff --git a/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/sundialsmath.h b/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/sundialsmath.h index 59e49d3a8..4f240e81b 100644 --- a/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/sundialsmath.h +++ b/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/sundialsmath.h @@ -13,10 +13,10 @@ * listed here work with the type realtype as defined in * * sundialstypes.h. * * To do single precision floating point arithmetic, set the type * - * realtype to be float. To do double precision arithmetic, set * + * realtype to be float. To do real(kind=8) arithmetic, set * * the type realtype to be double. The default implementations * * for RPowerR and RSqrt call standard math library functions * - * which do double precision arithmetic. If this is unacceptable * + * which do real(kind=8) arithmetic. If this is unacceptable * * when realtype is float, then the user should re-implement * * these two routines by calling single precision routines * * available on his/her machine. * diff --git a/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/sundialstypes.h b/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/sundialstypes.h index 1003410f7..ddf6c84a5 100644 --- a/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/sundialstypes.h +++ b/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/sundialstypes.h @@ -25,7 +25,7 @@ * The types for realtype and integertype below have been set to * * double and long int, respectively. A user should modify these * * type declarations as he/she sees fit. For example, if a user * - * wants the work with type float because double precision * + * wants the work with type float because real(kind=8) * * floating point arithmetic is too expensive on the user's * * machine, then the definition below should be changed to: * * * diff --git a/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/tally.cpp b/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/tally.cpp index 969b165d1..131411e15 100644 --- a/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/tally.cpp +++ b/src/IPhreeqcPhast/IPhreeqc/phreeqcpp/tally.cpp @@ -798,7 +798,6 @@ build_tally_table(void) */ int j, k, l, p, save_print_use; size_t n; - int count_tt_pure_phase, count_tt_ss_phase, count_tt_kinetics; class phase *phase_ptr; char token[MAX_LENGTH]; const char* cptr; @@ -871,7 +870,6 @@ build_tally_table(void) /* * Count pure phases */ - count_tt_pure_phase = 0; if (Rxn_pp_assemblage_map.size() > 0) { /* @@ -904,7 +902,6 @@ build_tally_table(void) /* * Add to table */ - count_tt_pure_phase++; n = count_tally_table_columns; extend_tally_table(); tally_table[n].name = phase_ptr->name; @@ -931,7 +928,6 @@ build_tally_table(void) /* * Add solid-solution pure phases */ - count_tt_ss_phase = 0; if (Rxn_ss_assemblage_map.size() > 0) { /* @@ -964,7 +960,6 @@ build_tally_table(void) /* * Add to table */ - count_tt_ss_phase++; n = count_tally_table_columns; extend_tally_table(); tally_table[n].name = phase_ptr->name; @@ -982,7 +977,6 @@ build_tally_table(void) /* * Add kinetic reactants */ - count_tt_kinetics = 0; if (Rxn_kinetics_map.size() > 0) { std::map::iterator it; @@ -1006,7 +1000,6 @@ build_tally_table(void) /* * Add to table */ - count_tt_kinetics++; n = count_tally_table_columns; extend_tally_table(); tally_table[n].name = string_hsave(kinetics_comp_ptr->Get_rate_name().c_str()); diff --git a/src/PhreeqcRM.cpp b/src/PhreeqcRM.cpp index 2f71ad7f8..c5eb9c30c 100644 --- a/src/PhreeqcRM.cpp +++ b/src/PhreeqcRM.cpp @@ -12,6 +12,7 @@ #define CLOCK() clock()/CLOCKS_PER_SEC #endif #include "PhreeqcRM.h" +#include "RMVARS.h" #include "PHRQ_base.h" #include "PHRQ_io.h" #include "IPhreeqc.h" @@ -32,6 +33,9 @@ #define gzprintf fprintf //#define ogzstream std::ofstream #endif +#ifdef USE_YAML +#include "yaml-cpp/yaml.h" +#endif #include "cxxMix.h" #include "Solution.h" #include "Exchange.h" @@ -62,7 +66,8 @@ size_t PhreeqcRM::InstancesIndex = 0; //// static PhreeqcRM methods /* ---------------------------------------------------------------------- */ -void PhreeqcRM::CleanupReactionModuleInstances(void) +void +PhreeqcRM::CleanupReactionModuleInstances(void) /* ---------------------------------------------------------------------- */ { std::map::iterator it = PhreeqcRM::Instances.begin(); @@ -126,7 +131,22 @@ PhreeqcRM::ErrorHandler(int result, const std::string & e_string) throw PhreeqcRMStop(); } } - +#ifdef USE_YAML +/* ---------------------------------------------------------------------- */ +int +PhreeqcRM::GetGridCellCountYAML(const char* YAML_file) +/* ---------------------------------------------------------------------- */ +{ + YAML::Node yaml = YAML::LoadFile(YAML_file); + std::string keyword; + YAML::Node node; + if (yaml["SetGridCellCount"].IsDefined()) + { + return yaml["SetGridCellCount"].as(); + } + return 0; +} +#endif /* ---------------------------------------------------------------------- */ PhreeqcRM* PhreeqcRM::GetInstance(int id) @@ -252,6 +272,7 @@ PhreeqcRM::PhreeqcRM(int nxyz_arg, MP_TYPE data_for_parallel_processing, PHRQ_io std::cerr << "Reaction module not created." << std::endl; exit(4); } + this->var_man = NULL; this->file_prefix = "myrun"; this->dump_file_name = file_prefix; this->dump_file_name.append(".dump"); @@ -303,6 +324,7 @@ PhreeqcRM::PhreeqcRM(int nxyz_arg, MP_TYPE data_for_parallel_processing, PHRQ_io forward_mapping_root.push_back(i); print_chem_mask_root.push_back(0); density_root.push_back(1.0); + viscosity_root.push_back(1.0); porosity_root.push_back(0.1); rv_root.push_back(1.0); pressure_root.push_back(1.0); @@ -324,7 +346,6 @@ PhreeqcRM::PhreeqcRM(int nxyz_arg, MP_TYPE data_for_parallel_processing, PHRQ_io mpi_worker_callback_fortran = NULL; mpi_worker_callback_c = NULL; mpi_worker_callback_cookie = NULL; - BMI_MakeVarMap(); } PhreeqcRM::~PhreeqcRM(void) { @@ -350,8 +371,8 @@ IRM_RESULT PhreeqcRM::CellInitialize( int ixyz, int n_user_new, - int *initial_conditions1, - int *initial_conditions2, + const int *initial_conditions1, + const int *initial_conditions2, double *fraction1, std::set &error_set) /* ---------------------------------------------------------------------- */ @@ -3360,10 +3381,9 @@ PhreeqcRM::GetCurrentSelectedOutputUserNumber(void) /* ---------------------------------------------------------------------- */ { this->phreeqcrm_error_string.clear(); - int return_value = IRM_INVALIDARG; try { - return_value = this->workers[0]->GetCurrentSelectedOutputUserNumber(); + return this->workers[0]->GetCurrentSelectedOutputUserNumber(); } catch (...) { @@ -4055,6 +4075,14 @@ PhreeqcRM::GetNthSelectedOutputUserNumber(int i) this->ReturnHandler(PhreeqcRM::Int2IrmResult(return_value, true), "PhreeqcRM::GetNthSelectedOutputUserNumber"); return return_value; } + +/* ---------------------------------------------------------------------- */ +const std::vector& +PhreeqcRM::GetPorosity(void) +/* ---------------------------------------------------------------------- */ +{ + return this->porosity_root; +} #ifdef USE_MPI /* ---------------------------------------------------------------------- */ const std::vector & @@ -4410,6 +4438,36 @@ PhreeqcRM::GetSelectedOutputHeading(int icol, std::string &heading) return this->ReturnHandler(IRM_INVALIDARG, "PhreeqcRM::GetSelectedOutputHeading"); } /* ---------------------------------------------------------------------- */ +IRM_RESULT +PhreeqcRM::GetSelectedOutputHeadings(std::vector& headings) +/* ---------------------------------------------------------------------- */ +{ + this->phreeqcrm_error_string.clear(); + headings.clear(); + try + { + int ncol = this->GetSelectedOutputColumnCount(); + if (ncol >= 0) + { + for (size_t i = 0; i < ncol; i++) + { + std::string heading; + this->GetSelectedOutputHeading(i, heading); + headings.push_back(heading); + } + return IRM_OK; + } + else + { + this->ErrorHandler(IRM_INVALIDARG, "Selected output not found."); + } + } + catch (...) + { + } + return this->ReturnHandler(IRM_INVALIDARG, "PhreeqcRM::GetSelectedOutputHeadings"); +} +/* ---------------------------------------------------------------------- */ int PhreeqcRM::GetSelectedOutputRowCount() /* ---------------------------------------------------------------------- */ @@ -4972,6 +5030,67 @@ PhreeqcRM::GetTemperature(void) return this->tempc_root; } #endif +#ifdef VISCOSITY +/* ---------------------------------------------------------------------- */ +IRM_RESULT +PhreeqcRM::GetViscosity(std::vector& viscosity_arg) +/* ---------------------------------------------------------------------- */ +{ + this->phreeqcrm_error_string.clear(); + try + { +#ifdef USE_MPI + if (this->mpi_myself == 0) + { + int method = METHOD_GETVISCOSITY; + MPI_Bcast(&method, 1, MPI_INT, 0, phreeqcrm_comm); + } + std::vector local_viscosity_worker; + int size = this->end_cell[this->mpi_myself] - this->start_cell[this->mpi_myself] + 1; + local_viscosity_worker.resize(size, INACTIVE_CELL_VALUE); + + // fill viscosity_root + int n = this->mpi_myself; + for (int i = this->start_cell[n]; i <= this->end_cell[n]; i++) + { + int l = i - this->start_cell[n]; + local_viscosity_worker[l] = this->workers[0]->Get_solution(i)->Get_viscosity(); + } + + // Gather to root + GatherNchem(local_viscosity_worker, viscosity_arg); +#else + viscosity_arg.resize(this->nxyz, INACTIVE_CELL_VALUE); + std::vector dbuffer; + for (int n = 0; n < this->nthreads; n++) + { + for (int i = start_cell[n]; i <= this->end_cell[n]; i++) + { + cxxSolution* soln_ptr = this->workers[n]->Get_solution(i); + if (!soln_ptr) + { + this->ErrorHandler(IRM_FAIL, "Solution not found for solution volume."); + } + else + { + double d = this->workers[n]->Get_solution(i)->Get_viscosity(); + for (size_t j = 0; j < backward_mapping[i].size(); j++) + { + int n = backward_mapping[i][j]; + viscosity_arg[n] = d; + } + } + } + } +#endif + } + catch (...) + { + this->ReturnHandler(IRM_FAIL, "PhreeqcRM::GetViscosity"); + } + return IRM_OK; +} +#endif #ifdef USE_MPI /* ---------------------------------------------------------------------- */ IRM_RESULT @@ -5068,10 +5187,417 @@ PhreeqcRM::HandleErrorsInternal(std::vector< int > &rtn) return IRM_OK; } #endif +#ifdef USE_YAML +IRM_RESULT PhreeqcRM::InitializeYAML(std::string config) +{ + YAML::Node yaml = YAML::LoadFile(config); + std::string keyword; + YAML::Node node; + for (YAML::Node::const_iterator it = yaml.begin();it != yaml.end();++it) + { + keyword = it->first.as(); + YAML::Node node = it->second; + if (keyword == "CloseFiles") + { + this->CloseFiles(); + continue; + } + if (keyword == "CreateMapping") + { + assert(node.IsSequence()); + std::vector grid2chem = it->second.as>(); + this->CreateMapping(grid2chem); + continue; + } + if (keyword == "DumpModule") + { + assert(node.IsMap()); + assert(node.size() == 2); + YAML::const_iterator it1 = node.begin(); + bool dump_on = it1++->second.as(); + bool append = it1++->second.as(); + this->DumpModule(dump_on, append); + continue; + } + if (keyword == "FindComponents") + { + this->FindComponents(); + continue; + } + if (keyword == "InitialPhreeqc2Module") + { + if (node.IsSequence()) + { + std::vector< int > ic = node.as< std::vector< int > >(); + this->InitialPhreeqc2Module(ic); + continue; + } + else if (node.IsMap()) + { + assert(node.IsMap()); + assert(node.size() == 3); + YAML::const_iterator it1 = node.begin(); + std::vector < int > ic1 = it1++->second.as< std::vector < int > >(); + std::vector < int > ic2 = it1++->second.as< std::vector < int > >(); + std::vector < double > f1 = it1->second.as< std::vector < double > >(); + this->InitialPhreeqc2Module(ic1, ic2, f1); + continue; + } + //throw LetItThrow("YAML argument mismatch InitialPhreeqc2Module"); + ErrorMessage("YAML argument mismatch InitialPhreeqc2Module"); + throw PhreeqcRMStop(); + } + if (keyword == "InitialPhreeqcCell2Module") + { + assert(node.IsMap()); + assert(node.size() == 2); + YAML::const_iterator it1 = node.begin(); + int n = it1++->second.as(); + std::vector< int > cell_numbers = it1->second.as< std::vector >(); + this->InitialPhreeqcCell2Module(n, cell_numbers); + continue; + } + if (keyword == "LoadDatabase") + { + std::string file = node.as< std::string >(); + this->LoadDatabase(file); + continue; + } + if (keyword == "OpenFiles") + { + this->OpenFiles(); + continue; + } + if (keyword == "OutputMessage") + { + assert(node.IsScalar()); + std::string str = node.as< std::string >(); + this->OutputMessage(str); + continue; + } + if (keyword == "RunCells") + { + this->RunCells(); + continue; + } + if (keyword == "RunFile") + { + assert(node.IsMap()); + assert(node.size() == 4); + YAML::const_iterator it1 = node.begin(); + bool workers = it1++->second.as(); + bool initial = it1++->second.as(); + bool utility = it1++->second.as(); + std::string file = it1->second.as< std::string >(); + this->RunFile(workers, initial, utility, file); + continue; + } + if (keyword == "RunString") + { + assert(node.IsMap()); + assert(node.size() == 4); + YAML::const_iterator it1 = node.begin(); + bool workers = it1++->second.as(); + bool initial = it1++->second.as(); + bool utility = it1++->second.as(); + std::string string = it1->second.as(); + this->RunString(workers, initial, utility, string); + continue; + } + if (keyword == "ScreenMessage") + { + assert(node.IsScalar()); + std::string str = node.as< std::string >(); + this->ScreenMessage(str); + continue; + } + if (keyword == "SetComponentH2O") + { + assert(node.IsScalar()); + bool tf = node.as< bool >(); + this->SetComponentH2O(tf); + continue; + } + if (keyword == "SetConcentrations") { + assert(node.IsSequence()); + std::vector< double > c = node.as< std::vector< double > >(); + this->SetConcentrations(c); + continue; + } + if (keyword == "SetCurrentSelectedOutputUserNumber") + { + assert(node.IsScalar()); + int n = node.as< int >(); + this->SetCurrentSelectedOutputUserNumber(n); + continue; + } + if (keyword == "SetDensity") + { + assert(node.IsSequence()); + std::vector< double > den = node.as< std::vector< double > >(); + this->SetDensity(den); + continue; + } + if (keyword == "SetDumpFileName") + { + assert(node.IsScalar()); + std::string str = node.as< std::string >(); + this->SetDumpFileName(str); + continue; + } + if (keyword == "SetErrorHandlerMode") + { + assert(node.IsScalar()); + int mode = node.as< int >(); + this->SetErrorHandlerMode(mode); + continue; + } + if (keyword == "SetErrorOn") { + assert(node.IsScalar()); + bool tf = node.as< bool >(); + this->SetErrorOn(tf); + continue; + } + if (keyword == "SetFilePrefix") + { + assert(node.IsScalar()); + std::string prefix = node.as< std::string >(); + this->SetFilePrefix(prefix); + continue; + } + if (keyword == "SetGasCompMoles") { + assert(node.IsSequence()); + std::vector mol = node.as< std::vector < double > >(); + this->SetGasCompMoles(mol); + continue; + } + if (keyword == "SetGasPhaseVolume") { + assert(node.IsSequence()); + std::vector vol = node.as< std::vector < double > >(); + this->SetGasPhaseVolume(vol); + continue; + } + if (keyword == "SetGridCellCount") { + //this->WarningMessage("SetGridCellCount has no effect after the PhreeqcRM instance is created."); + continue; + } + if (keyword == "SetPartitionUZSolids") + { + assert(node.IsScalar()); + bool tf = node.as< bool >(); + this->SetPartitionUZSolids(tf); + continue; + } + if (keyword == "SetPorosity") + { + assert(node.IsSequence()); + std::vector por = node.as< std::vector< double > >(); + this->SetPorosity(por); + continue; + } + if (keyword == "SetPressure") + { + assert(node.IsSequence()); + std::vector pressure = node.as< std::vector< double > >(); + this->SetPressure(pressure); + continue; + } + if (keyword == "SetPrintChemistryMask") + { + assert(node.IsSequence()); + std::vector mask = node.as< std::vector< int > >(); + this->SetPrintChemistryMask(mask); + continue; + } + if (keyword == "SetPrintChemistryOn") + { + assert(node.IsMap()); + assert(node.size() == 3); + YAML::const_iterator it1 = node.begin(); + bool workers = it1++->second.as< bool >(); + bool initial = it1++->second.as< bool >(); + bool utility = it1->second.as< bool >(); + this->SetPrintChemistryOn(workers, initial, utility); + continue; + } + if (keyword == "SetRebalanceByCell") + { + assert(node.IsScalar()); + bool tf = node.as< bool >(); + this->SetRebalanceByCell(tf); + continue; + } + if (keyword == "SetRebalanceFraction") + { + assert(node.IsScalar()); + double f = node.as(); + this->SetRebalanceFraction(f); + continue; + } + if (keyword == "SetRepresentativeVolume") + { + assert(node.IsSequence()); + std::vector rv = it->second.as< std::vector >(); + this->SetRepresentativeVolume(rv); + continue; + } + if (keyword == "SetSaturation") + { + assert(node.IsSequence()); + std::vector< double > sat = node.as< std::vector< double> >(); + this->SetSaturation(sat); + continue; + } + if (keyword == "SetScreenOn") { + assert(node.IsScalar()); + bool tf = node.as< bool >(); + this->SetScreenOn(tf); + continue; + } + if (keyword == "SetSelectedOutputOn") + { + assert(node.IsScalar()); + bool tf = node.as< bool >(); + this->SetSelectedOutputOn(tf); + continue; + } + if (keyword == "SetSpeciesSaveOn") + { + assert(node.IsScalar()); + bool tf = node.as< bool >(); + this->SetSpeciesSaveOn(tf); + continue; + } + if (keyword == "SetTemperature") + { + assert(node.IsSequence()); + std::vector temp = node.as>(); + this->SetTemperature(temp); + continue; + } + if (keyword == "SetTime") + { + assert(node.IsScalar()); + double time = node.as(); + this->SetTime(time); + continue; + } + if (keyword == "SetTimeConversion") + { + assert(node.IsScalar()); + double time_conv = node.as(); + this->SetTimeConversion(time_conv); + continue; + } + if (keyword == "SetTimeStep") + { + assert(node.IsScalar()); + double time_step = node.as(); + this->SetTimeStep(time_step); + continue; + } + if (keyword == "SetUnitsExchange") + { + assert(node.IsScalar()); + int units = node.as(); + this->SetUnitsExchange(units); + continue; + } + if (keyword == "SetUnitsGasPhase") + { + assert(node.IsScalar()); + int units = node.as< int >(); + this->SetUnitsGasPhase(units); + continue; + } + if (keyword == "SetUnitsKinetics") + { + assert(node.IsScalar()); + int units = node.as< int >(); + this->SetUnitsKinetics(units); + continue; + } + if (keyword == "SetUnitsPPassemblage") + { + assert(node.IsScalar()); + int units = node.as< int >(); + this->SetUnitsPPassemblage(units); + continue; + } + if (keyword == "SetUnitsSolution") + { + assert(node.IsScalar()); + int units = node.as< int >(); + this->SetUnitsSolution(units); + continue; + } + if (keyword == "SetUnitsSSassemblage") + { + assert(node.IsScalar()); + int units = node.as< int >(); + this->SetUnitsSSassemblage(units); + continue; + } + if (keyword == "SetUnitsSurface") + { + assert(node.IsScalar()); + int units = node.as< int >(); + this->SetUnitsSurface(units); + continue; + } + if (keyword == "SpeciesConcentrations2Module") + { + assert(node.IsSequence()); + std::vector < double > scond = node.as< std::vector < double > >(); + this->SpeciesConcentrations2Module(scond); + continue; + } + if (keyword == "StateSave") + { + assert(node.IsScalar()); + int n = node.as< int >(); + this->StateSave(n); + continue; + } + if (keyword == "StateApply") + { + assert(node.IsScalar()); + int n = node.as< int >(); + this->StateApply(n); + continue; + } + if (keyword == "StateDelete") + { + assert(node.IsScalar()); + int n = node.as< int >(); + this->StateDelete(n); + continue; + } + if (keyword == "UseSolutionDensityVolume") + { + assert(node.IsScalar()); + bool tf = node.as< bool >(); + this->UseSolutionDensityVolume(tf); + continue; + } + if (keyword == "WarningMessage") + { + assert(node.IsScalar()); + std::string str = node.as< std::string >(); + this->WarningMessage(str); + continue; + } + //throw LetItThrow("YAML keyword not found"); + ErrorMessage("YAML keyword not found"); + throw PhreeqcRMStop(); + } + return IRM_RESULT::IRM_OK; +} +#endif /* ---------------------------------------------------------------------- */ IRM_RESULT PhreeqcRM::InitialPhreeqc2Concentrations(std::vector < double > &destination_c, - std::vector < int > & boundary_solution1) + const std::vector < int > & boundary_solution1) { this->phreeqcrm_error_string.clear(); std::vector< int > dummy; @@ -5081,9 +5607,9 @@ PhreeqcRM::InitialPhreeqc2Concentrations(std::vector < double > &destination_c, /* ---------------------------------------------------------------------- */ IRM_RESULT PhreeqcRM::InitialPhreeqc2Concentrations(std::vector < double > &destination_c, - std::vector < int > & boundary_solution1, - std::vector < int > & boundary_solution2, - std::vector < double > & fraction1) + const std::vector < int > & boundary_solution1, + const std::vector < int > & boundary_solution2, + const std::vector < double > & fraction1) /* ---------------------------------------------------------------------- */ { /* @@ -5194,7 +5720,7 @@ PhreeqcRM::InitialPhreeqc2Concentrations(std::vector < double > &destination_c, /* ---------------------------------------------------------------------- */ IRM_RESULT PhreeqcRM::InitialPhreeqc2Module( - std::vector < int > & initial_conditions1_in) + const std::vector < int > & initial_conditions1_in) /* ---------------------------------------------------------------------- */ { this->phreeqcrm_error_string.clear(); @@ -5210,7 +5736,7 @@ PhreeqcRM::InitialPhreeqc2Module( /* ---------------------------------------------------------------------- */ IRM_RESULT PhreeqcRM::InitialPhreeqc2Module( - std::vector < int > & initial_conditions1, + const std::vector < int > & initial_conditions1, std::vector < int > & initial_conditions2, std::vector < double > & fraction1) /* ---------------------------------------------------------------------- */ @@ -6138,6 +6664,13 @@ PhreeqcRM::MpiWorker() this->GetTemperature(); } break; + case METHOD_GETVISCOSITY: + if (debug_worker) std::cerr << "METHOD_GETVISCOSITY" << std::endl; + { + std::vector dummy; + this->GetViscosity(dummy); + } + break; case METHOD_INITIALPHREEQC2MODULE: if (debug_worker) std::cerr << "METHOD_INITIALPHREEQC2MODULE" << std::endl; { @@ -8467,9 +9000,9 @@ PhreeqcRM::RebalanceLoadPerCell(void) } // Split up work - double f_low, f_high; - f_high = 1 + 0.5 / ((double) this->nthreads); - f_low = 1; + //double f_low, f_high; + //f_high = 1 + 0.5 / ((double) this->nthreads); + //f_low = 1; int j = 0; for (size_t i = 0; i < (size_t) this->nthreads - 1; i++) { @@ -8477,7 +9010,6 @@ PhreeqcRM::RebalanceLoadPerCell(void) { start_cell_new[i] = end_cell_new[i - 1] + 1; } - double sum_work = 0; double temp_sum_work = 0; bool next = true; while (next) @@ -8485,7 +9017,7 @@ PhreeqcRM::RebalanceLoadPerCell(void) temp_sum_work += normalized_cell_times[j] / normalized_total_time; if ((temp_sum_work < task_fraction[i]) && ((count_chemistry - (int) j) > (this->nthreads - (int) i))) { - sum_work = temp_sum_work; + //sum_work = temp_sum_work; j++; next = true; } @@ -10486,7 +11018,7 @@ PhreeqcRM::SetDensity(const std::vector &t) std::string methodName = "SetDensity"; IRM_RESULT result_value = SetGeneric(t, this->density_root, density_worker, METHOD_SETDENSITY, methodName); return this->ReturnHandler(result_value, "PhreeqcRM::" + methodName); - } +} /* ---------------------------------------------------------------------- */ IRM_RESULT @@ -10829,6 +11361,7 @@ PhreeqcRM::SetPorosity(const std::vector &t) this->phreeqcrm_error_string.clear(); std::string methodName = "SetPorosity"; IRM_RESULT result_value = SetGeneric(t, this->porosity_root, porosity_worker, METHOD_SETPOROSITY, methodName); + this->UpdateBMI(RMVARS::Porosity); return this->ReturnHandler(result_value, "PhreeqcRM::" + methodName); } @@ -10894,6 +11427,7 @@ PhreeqcRM::SetPressure(const std::vector &t) { return_value = IRM_FAIL; } + this->UpdateBMI(RMVARS::Pressure); return this->ReturnHandler(return_value, "PhreeqcRM::SetPressure"); } /* ---------------------------------------------------------------------- */ @@ -10934,7 +11468,7 @@ PhreeqcRM::SetPrintChemistryOn(bool worker, bool ip, bool utility) /* ---------------------------------------------------------------------- */ IRM_RESULT -PhreeqcRM::SetPrintChemistryMask(std::vector & m) +PhreeqcRM::SetPrintChemistryMask(const std::vector & m) /* ---------------------------------------------------------------------- */ { this->phreeqcrm_error_string.clear(); @@ -11029,6 +11563,7 @@ PhreeqcRM::SetSaturation(const std::vector &t) this->phreeqcrm_error_string.clear(); std::string methodName = "SetSaturation"; IRM_RESULT result_value = SetGeneric(t, this->saturation_root, saturation_worker, METHOD_SETSATURATION, methodName); + this->UpdateBMI(RMVARS::Saturation); return this->ReturnHandler(result_value, "PhreeqcRM::" + methodName); } /* ---------------------------------------------------------------------- */ @@ -11071,6 +11606,7 @@ PhreeqcRM::SetSelectedOutputOn(bool t) this->selected_output_on = (temp_tf == 0) ? false : true; //MPI_Bcast(&this->selected_output_on, 1, MPI_LOGICAL, 0, phreeqcrm_comm); #endif + this->UpdateBMI(RMVARS::SelectedOutputOn); return IRM_OK; } @@ -11156,6 +11692,7 @@ PhreeqcRM::SetTemperature(const std::vector &t) { return_value = IRM_FAIL; } + this->UpdateBMI(RMVARS::Temperature); return this->ReturnHandler(return_value, "PhreeqcRM::SetTemperature"); } /* ---------------------------------------------------------------------- */ @@ -11179,6 +11716,7 @@ PhreeqcRM::SetTime(double t) #ifdef USE_MPI MPI_Bcast(&this->time, 1, MPI_DOUBLE, 0, phreeqcrm_comm); #endif + this->UpdateBMI(RMVARS::Time); return IRM_OK; } @@ -11227,6 +11765,7 @@ PhreeqcRM::SetTimeStep(double t) #ifdef USE_MPI MPI_Bcast(&this->time_step, 1, MPI_DOUBLE, 0, phreeqcrm_comm); #endif + this->UpdateBMI(RMVARS::TimeStep); return IRM_OK; } /* ---------------------------------------------------------------------- */ @@ -11864,6 +12403,16 @@ PhreeqcRM::TransferCellsUZ(std::ostringstream &raw_stream, int old, int nnew) #endif /* ---------------------------------------------------------------------- */ void +PhreeqcRM::UpdateBMI(RMVARS v_enum) +/* ---------------------------------------------------------------------- */ +{ + if (this->var_man != NULL) + { + this->var_man->RM2BMIUpdate(v_enum); + } +} +/* ---------------------------------------------------------------------- */ +void PhreeqcRM::UseSolutionDensityVolume(bool tf) /* ---------------------------------------------------------------------- */ { diff --git a/src/PhreeqcRM.h b/src/PhreeqcRM.h index cb1106262..70ef5bada 100644 --- a/src/PhreeqcRM.h +++ b/src/PhreeqcRM.h @@ -21,7 +21,9 @@ class PHRQ_io; #include #include #include - +#include "VarManager.h" +#include "RMVARS.h" +//class VarManager; #if defined(_WINDLL) #define IRM_DLL_EXPORT __declspec(dllexport) #else @@ -68,6 +70,7 @@ enum { METHOD_GETSPECIESLOG10GAMMAS, METHOD_GETSPECIESLOG10MOLALITIES, METHOD_GETTEMPERATURE, + METHOD_GETVISCOSITY, METHOD_INITIALPHREEQC2MODULE, METHOD_INITIALPHREEQCCELL2MODULE, METHOD_LOADDATABASE, @@ -111,23 +114,6 @@ enum { METHOD_USESOLUTIONDENSITYVOLUME } /* MPI_METHOD */; -int IRM_DLL_EXPORT -GetGridCellCountYAML(std::string YAML_file); - -/** - * @mainpage PhreeqcRM Library Documentation (@PHREEQC_VER@-@REVISION_SVN@) - * - * @htmlonly - * - * - * - * - * - * - *
PhreeqRM.h C++ Documentation
RM_interface_C.h C Documentation
RM_interface.F90Fortran Documentation
IrmResult.hReturn codes
YAMLPhreeqcRM.hC++ YAML Support
- * @endhtmlonly - */ - /** * @class PhreeqcRM * @@ -142,6 +128,56 @@ class IRM_DLL_EXPORT PhreeqcRM static int CreateReactionModule(int nxyz, MP_TYPE nthreads); static IRM_RESULT DestroyReactionModule(int n); static PhreeqcRM * GetInstance(int n); + class VarManager* var_man; +private: + void UpdateBMI(RMVARS v_enum); +public: +#ifdef USE_YAML +/** +@a GetGridCellCountYAML will read the YAML file and extract the value +of GridCellCount, which can be used to construct a PhreeqcRM +instance. The constructor for a PhreeqcRM instance requires a +value for the number of cells. If a GUI or preprocessor is +used to write a YAML file to initialize PhreeqcRM, the number +of cells can be written to the YAML file and extracted with +this method. +@param YAML_file String containing the YAML file name. +@retval Number of grid cells specified in the YAML file; returns +zero if GridCellCount is not defined. +@see @ref InitializeYAML @ref PhreeqcRM. +@par C++ Example: +@htmlonly + +
+int nthreads = 0;
+std::string yaml_file = "myfile.yaml";
+int nxyz = PhreeqcRM::GetGridCellCountYAML(yaml_file);
+PhreeqcRM phreeqc_rm(nxyz, nthreads);
+phreeqc_rm.InitializeYAML(yaml_file);
+
+
+@endhtmlonly +@par Sequence: +Called before PhreeqcRM is created. +*/ + static int GetGridCellCountYAML(const char* YAML_file); +#endif // #ifdef USE_YAML + +/** + * @mainpage PhreeqcRM Library Documentation (@PHREEQC_VER@-@REVISION_SVN@) + * + * @htmlonly + * + * + * + * + * + * + * + *
PhreeqRM.h C++ Documentation
RM_interface_C.h C Documentation
RM_interface.F90Fortran Documentation
IrmResult.hReturn codes
YAMLPhreeqcRM.hC++ YAML Support
YAML_interface.F90Fortran YAML Support
+ * @endhtmlonly + */ + /** Constructor for the PhreeqcRM reaction module. If the code is compiled with @@ -226,7 +262,7 @@ for (int i = 0; i < ncomps; i++) { c_well[i] = 0.5 * c[0 + nxyz*i] + 0.5 * c[9 + nxyz*i]; } -std::vector tc, p_atm; +std::vector< double > tc, p_atm; tc.resize(1, 15.0); p_atm.resize(1, 3.0); IPhreeqc * util_ptr = phreeqc_rm.Concentrations2Utility(c_well, tc, p_atm); @@ -247,8 +283,8 @@ iphreeqc_result = util_ptr->GetSelectedOutputValue2(1, 0, &vtype, &pH, svalue, 1 @par MPI: Called only by root. */ - IPhreeqc * Concentrations2Utility(std::vector &c, - std::vector tc, std::vector p_atm); + IPhreeqc * Concentrations2Utility(std::vector< double > &c, + std::vector< double > tc, std::vector< double > p_atm); /** Provides a mapping from grid cells in the user's model to reaction cells for which chemistry needs to be run. The mapping is used to eliminate inactive cells and to use symmetry to decrease the number of cells @@ -268,7 +304,7 @@ negative is an inactive cell. Vector is of size @a nxyz (number of grid cells, @
 // For demonstation, two equivalent rows by symmetry
-std::vector grid2chem;
+std::vector< int > grid2chem;
 grid2chem.resize(nxyz, -1);
 for (int i = 0; i < nxyz/2; i++)
 {
@@ -284,7 +320,7 @@ int nchem = phreeqc_rm.GetChemistryCellCount();
 @par MPI:
 Called by root, workers must be in the loop of @ref MpiWorker.
  */
-	IRM_RESULT                                CreateMapping(std::vector &grid2chem);
+	IRM_RESULT                                CreateMapping(std::vector< int > &grid2chem);
 /**
 If @a result is negative, this method prints an error message corresponding to IRM_RESULT @a result.
 If @a result is non-negative, no action is taken.
@@ -445,7 +481,7 @@ cumulative list of components.
 
 
 int ncomps = phreeqc_rm.FindComponents();
-const std::vector &components = phreeqc_rm.GetComponents();
+const std::vector< std::string > &components = phreeqc_rm.GetComponents();
 const std::vector < double > & gfw = phreeqc_rm.GetGfw();
 for (int i = 0; i < ncomps; i++)
 {
@@ -532,13 +568,13 @@ Called by root.
 	int                                       GetComponentCount(void) const {return (int) this->components.size();}
 /**
 Returns a reference to the reaction-module component list that was generated by calls to @ref FindComponents.
-@retval const std::vector&       A vector of strings; each string is a component name.
+@retval const std::vector< std::string >&       A vector of strings; each string is a component name.
 @see                    @ref FindComponents, @ref GetComponentCount
 @par C++ Example:
 @htmlonly
 
 
-const std::vector &components = phreeqc_rm.GetComponents();
+const std::vector< std::string > &components = phreeqc_rm.GetComponents();
 const std::vector < double > & gfw = phreeqc_rm.GetGfw();
 int ncomps = phreeqc_rm.GetComponentCount();
 for (int i = 0; i < ncomps; i++)
@@ -554,7 +590,7 @@ for (int i = 0; i < ncomps; i++)
 @par MPI:
 Called by root and (or) workers.
  */
-const std::vector &          GetComponents(void) const {return this->components;}
+const std::vector< std::string > &          GetComponents(void) const {return this->components;}
 	
 /**
 Transfer solution concentrations from each reaction cell
@@ -585,7 +621,7 @@ Values for inactive cells are set to 1e30.
 @htmlonly
 
 
-std::vector c;
+std::vector< double > c;
 status = phreeqc_rm.RunCells();
 status = phreeqc_rm.GetConcentrations(c);
 
@@ -594,7 +630,7 @@ status = phreeqc_rm.GetConcentrations(c); @par MPI: Called by root, workers must be in the loop of @ref MpiWorker. */ - IRM_RESULT GetConcentrations(std::vector &c); + IRM_RESULT GetConcentrations(std::vector< double > &c); /** Returns the user number of the current selected-output definition. @ref SetCurrentSelectedOutputUserNumber or @ref SetNthSelectedOutput specifies which of the @@ -620,13 +656,13 @@ for (int isel = 0; isel < phreeqc_rm.GetSelectedOutputCount(); isel++) { status = phreeqc_rm.SetCurrentSelectedOutput(isel); int n_user = phreeqc_rm.GetCurrentSelectedOutputUserNumber(isel); - std::vector so; + std::vector< double > so; int col = phreeqc_rm.GetSelectedOutputColumnCount(); status = phreeqc_rm.GetSelectedOutput(so); // Print results for (int i = 0; i < phreeqc_rm.GetSelectedOutputRowCount()/2; i++) { - std::vector headings; + std::vector< std::string > headings; headings.resize(col); std::cerr << " Selected output " << n_user <<": " << "\n"; for (int j = 0; j < col; j++) @@ -662,7 +698,9 @@ Called by root and (or) workers. */ std::string GetDatabaseFileName(void) {return this->database_file_name;} /** -Transfer solution densities from the reaction-module workers to the vector given in the argument list (@a density). +Transfer solution densities from the reaction-module workers to the vector given +in the argument list (@a density). This method always returns the calculated +densities; @ref SetDensity does not affect the result. @param density Vector to receive the densities. Dimension of the array is set to @a nxyz, where @a nxyz is the number of user grid cells (@ref GetGridCellCount). Values for inactive cells are set to 1e30. @@ -677,7 +715,7 @@ to accurately calculate density: phreeqc.dat, Amm.dat, and pitzer.dat.
 status = phreeqc_rm.RunCells();
 status = phreeqc_rm.GetConcentrations(c);
-std::vector density;
+std::vector< double > density;
 status = phreeqc_rm.GetDensity(density);
 
@@ -685,7 +723,7 @@ status = phreeqc_rm.GetDensity(density); @par MPI: Called by root, workers must be in the loop of @ref MpiWorker. */ - IRM_RESULT GetDensity(std::vector & density); + IRM_RESULT GetDensity(std::vector< double > & density); /** Returns a vector of integers that contains the largest reaction-cell number assigned to each worker. Each worker is assigned a range of reaction-cell numbers that are run during a call to @ref RunCells. @@ -729,7 +767,7 @@ the initial-phreeqc module. @ref FindComponents must be called before @ref GetEquilibriumPhases. This method may be useful when generating selected output definitions related to equilibrium phases. -@retval const std::vector& A vector of strings; each string is a unique +@retval const std::vector< std::string >& A vector of strings; each string is a unique equilibrium phases name. @see @ref FindComponents, @@ -740,7 +778,7 @@ equilibrium phases name.
 oss << "  -equilibrium_phases " << "\n";
 // equilibrium phases
-const std::vector &eq_phases = phreeqc_rm.GetEquilibriumPhases();
+const std::vector< std::string > &eq_phases = phreeqc_rm.GetEquilibriumPhases();
 for (size_t i = 0; i < phreeqc_rm.GetEquilibriumPhasesCount(); i++)
 {
 oss << "    " << eq_phases[i] << "\n";
@@ -751,7 +789,7 @@ oss << "    " << eq_phases[i] << "\n";
 @par MPI:
 Called by root.
 */
-const std::vector &          GetEquilibriumPhases(void) const { return this->EquilibriumPhasesList; }
+const std::vector< std::string > &          GetEquilibriumPhases(void) const { return this->EquilibriumPhasesList; }
 /**
 Returns the number of equilibrium phases in the initial-phreeqc module.
 @ref FindComponents must be called before @ref GetEquilibriumPhasesCount.
@@ -768,7 +806,7 @@ equilibrium phases.
 
 oss << "  -equilibrium_phases " << "\n";
 // equilibrium phases
-const std::vector &eq_phases = phreeqc_rm.GetEquilibriumPhases();
+const std::vector< std::string > &eq_phases = phreeqc_rm.GetEquilibriumPhases();
 for (size_t i = 0; i < phreeqc_rm.GetEquilibriumPhasesCount(); i++)
 {
 oss << "    " << eq_phases[i] << "\n";
@@ -831,7 +869,7 @@ The exchange names vector is the same length as the exchange species names vecto
 and provides the corresponding exchange site.
 This method may be useful when generating selected output definitions related to exchangers.
 
-@retval const std::vector&       A vector of strings; each string is an
+@retval const std::vector< std::string >&       A vector of strings; each string is an
 exchange name corresponding to the exchange species vector; an exchange name may occur
 multiple times.
 
@@ -842,8 +880,8 @@ multiple times.
 
 
 // molalities of exchange species
-const std::vector &ex_species = phreeqc_rm.GetExchangeSpecies();
-const std::vector &ex_names = phreeqc_rm.GetExchangeNames();
+const std::vector< std::string > &ex_species = phreeqc_rm.GetExchangeSpecies();
+const std::vector< std::string > &ex_names = phreeqc_rm.GetExchangeNames();
 for (size_t i = 0; i < phreeqc_rm.GetExchangeSpeciesCount(); i++)
 {
 
@@ -858,7 +896,7 @@ oss << " # " << ex_names[i] << "\n";
 @par MPI:
 Called by root.
 */
-const std::vector &          GetExchangeNames(void) const { return this->ExchangeNamesList; }
+const std::vector< std::string > &          GetExchangeNames(void) const { return this->ExchangeNamesList; }
 /**
 Returns a reference to the vector of exchange species names (such as "NaX").
 The list of exchange species (such as "NaX") is derived from the list of components
@@ -867,7 +905,7 @@ that are included in EXCHANGE definitions in the initial-phreeqc module.
 @ref FindComponents must be called before @ref GetExchangeSpecies.
 This method may be useful when generating selected output definitions related to exchangers.
 
-@retval const std::vector&       A vector of strings; each string is a
+@retval const std::vector< std::string >&       A vector of strings; each string is a
 unique exchange species name.
 
 @see                    @ref FindComponents,
@@ -877,8 +915,8 @@ unique exchange species name.
 
 
 // molalities of exchange species
-const std::vector &ex_species = phreeqc_rm.GetExchangeSpecies();
-const std::vector &ex_names = phreeqc_rm.GetExchangeNames();
+const std::vector< std::string > &ex_species = phreeqc_rm.GetExchangeSpecies();
+const std::vector< std::string > &ex_names = phreeqc_rm.GetExchangeNames();
 for (size_t i = 0; i < phreeqc_rm.GetExchangeSpeciesCount(); i++)
 {
 
@@ -893,7 +931,7 @@ oss << " # " << ex_names[i] << "\n";
 @par MPI:
 Called by root.
 */
-const std::vector &          GetExchangeSpecies(void) const { return this->ExchangeSpeciesNamesList; }
+const std::vector< std::string > &          GetExchangeSpecies(void) const { return this->ExchangeSpeciesNamesList; }
 /**
 Returns the number of exchange species in the initial-phreeqc module.
 @ref FindComponents must be called before @ref GetExchangeSpeciesCount.
@@ -909,8 +947,8 @@ This method may be useful when generating selected output definitions related to
 
 
 // molalities of exchange species
-const std::vector &ex_species = phreeqc_rm.GetExchangeSpecies();
-const std::vector &ex_names = phreeqc_rm.GetExchangeNames();
+const std::vector< std::string > &ex_species = phreeqc_rm.GetExchangeSpecies();
+const std::vector< std::string > &ex_names = phreeqc_rm.GetExchangeNames();
 for (size_t i = 0; i < phreeqc_rm.GetExchangeSpeciesCount(); i++)
 {
 
@@ -959,7 +997,7 @@ Nonnegative is a reaction-cell number (0 based), negative is an inactive cell.
 @htmlonly
 
 
-const std::vector &f_map = phreeqc_rm.GetForwardMapping();
+const std::vector< int > &f_map = phreeqc_rm.GetForwardMapping();
 
@endhtmlonly @@ -975,7 +1013,7 @@ the initial-phreeqc module. @ref FindComponents must be called before @ref GetGasComponents. This method may be useful when generating selected output definitions related to gas phases. -@retval const std::vector& A vector of strings; each string is a unique +@retval const std::vector< std::string >& A vector of strings; each string is a unique gas component name. @see @ref FindComponents, @@ -986,7 +1024,7 @@ gas component name.
 oss << "  -gases " << "\n";
 // gas components
-const std::vector &gas_phases = phreeqc_rm.GetGasComponents();
+const std::vector< std::string > &gas_phases = phreeqc_rm.GetGasComponents();
 for (size_t i = 0; i < phreeqc_rm.GetGasComponentsCount(); i++)
 {
 oss << "    " << gas_phases[i] << "\n";
@@ -997,7 +1035,7 @@ oss << "    " << gas_phases[i] << "\n";
 @par MPI:
 Called by root.
 */
-const std::vector &          GetGasComponents(void) const { return this->GasComponentsList; }
+const std::vector< std::string > &          GetGasComponents(void) const { return this->GasComponentsList; }
 /**
 Returns the number of gas phase components in the initial-phreeqc module.
 @ref FindComponents must be called before @ref GetGasComponentsCount.
@@ -1014,7 +1052,7 @@ gas phases.
 
 oss << "  -gases " << "\n";
 // gas components
-const std::vector &gas_phases = phreeqc_rm.GetGasComponents();
+const std::vector< std::string > &gas_phases = phreeqc_rm.GetGasComponents();
 for (size_t i = 0; i < phreeqc_rm.GetGasComponentsCount(); i++)
 {
 oss << "    " << gas_phases[i] << "\n";
@@ -1050,7 +1088,7 @@ Values for inactive cells are set to 1e30.
 @htmlonly
 
 
-std::vector gas_moles;
+std::vector< double > gas_moles;
 status = phreeqc_rm.RunCells();
 status = phreeqc_rm.GetGasCompMoles(gas_moles);
 
@@ -1059,7 +1097,7 @@ status = phreeqc_rm.GetGasCompMoles(gas_moles); @par MPI: Called by root, workers must be in the loop of @ref MpiWorker. */ -IRM_RESULT GetGasCompMoles(std::vector& gas_moles); +IRM_RESULT GetGasCompMoles(std::vector< double >& gas_moles); /** Transfer pressures of gas components from each reaction cell @@ -1084,7 +1122,7 @@ Values for inactive cells are set to 1e30. @htmlonly
-std::vector gas_pressure;
+std::vector< double > gas_pressure;
 status = phreeqc_rm.RunCells();
 status = phreeqc_rm.GetGasCompPressures(gas_pressure);
 
@@ -1093,7 +1131,7 @@ status = phreeqc_rm.GetGasCompPressures(gas_pressure); @par MPI: Called by root, workers must be in the loop of @ref MpiWorker. */ -IRM_RESULT GetGasCompPressures(std::vector& gas_pressure); +IRM_RESULT GetGasCompPressures(std::vector< double >& gas_pressure); /** Transfer fugacity coefficients (phi) of gas components from each reaction cell @@ -1119,7 +1157,7 @@ Values for inactive cells are set to 1e30. @htmlonly
-std::vector gas_phi;
+std::vector< double > gas_phi;
 status = phreeqc_rm.RunCells();
 status = phreeqc_rm.GetGasCompPhi(gas_phi);
 
@@ -1128,7 +1166,7 @@ status = phreeqc_rm.GetGasCompPhi(gas_phi); @par MPI: Called by root, workers must be in the loop of @ref MpiWorker. */ -IRM_RESULT GetGasCompPhi(std::vector& gas_phi); +IRM_RESULT GetGasCompPhi(std::vector< double >& gas_phi); /** Transfer volume of gas phase from each reaction cell @@ -1152,7 +1190,7 @@ Values for inactive cells are set to 1e30. @htmlonly
-std::vector gas_volume;
+std::vector< double > gas_volume;
 status = phreeqc_rm.RunCells();
 status = phreeqc_rm.GetGasPhaseVolume(gas_volume);
 
@@ -1161,19 +1199,19 @@ status = phreeqc_rm.GetGasPhaseVolume(gas_volume); @par MPI: Called by root, workers must be in the loop of @ref MpiWorker. */ -IRM_RESULT GetGasPhaseVolume(std::vector& gas_volume); +IRM_RESULT GetGasPhaseVolume(std::vector< double >& gas_volume); /** Returns a reference to a vector of doubles that contains the gram-formula weight of each component. Called after @ref FindComponents. Order of weights corresponds to the list of components from @ref GetComponents. -@retval const std::vector& A vector of doubles; each value is a component gram-formula weight, g/mol. +@retval const std::vector< double >& A vector of doubles; each value is a component gram-formula weight, g/mol. @see @ref FindComponents, @ref GetComponents. @par C++ Example: @htmlonly
-const std::vector &components = phreeqc_rm.GetComponents();
+const std::vector< std::string > &components = phreeqc_rm.GetComponents();
 const std::vector < double > & gfw = phreeqc_rm.GetGfw();
 int ncomps = phreeqc_rm.GetComponentCount();
 for (int i = 0; i < ncomps; i++)
@@ -1247,7 +1285,7 @@ the reaction model.
 @ref FindComponents must be called before @ref GetKineticReactions.
 This method may be useful when generating selected output definitions related to kinetic reactions.
 
-@retval const std::vector&       A vector of strings; each string is a unique
+@retval const std::vector< std::string >&       A vector of strings; each string is a unique
 kinetic reaction name.
 
 @see                    @ref FindComponents,
@@ -1258,7 +1296,7 @@ kinetic reaction name.
 
 oss << "  -kinetics " << "\n";
 // kinetic reactions
-const std::vector &kin_reactions = phreeqc_rm.GetKineticReactions();
+const std::vector< std::string > &kin_reactions = phreeqc_rm.GetKineticReactions();
 for (size_t i = 0; i < phreeqc_rm.GetKineticReactionsCount(); i++)
 {
 oss << "    " << kin_reactions[i] << "\n";
@@ -1269,7 +1307,7 @@ oss << "    " << kin_reactions[i] << "\n";
 @par MPI:
 Called by root.
 */
-const std::vector &          GetKineticReactions(void) const { return this->KineticReactionsList; }
+const std::vector< std::string > &          GetKineticReactions(void) const { return this->KineticReactionsList; }
 /**
 Returns the number of kinetic reactions in the initial-phreeqc module.
 @ref FindComponents must be called before @ref GetKineticReactionsCount.
@@ -1286,7 +1324,7 @@ kinetic reactions.
 
 oss << "  -kinetics " << "\n";
 // kinetic reactions
-const std::vector &kin_reactions = phreeqc_rm.GetKineticReactions();
+const std::vector< std::string > &kin_reactions = phreeqc_rm.GetKineticReactions();
 for (size_t i = 0; i < phreeqc_rm.GetKineticReactionsCount(); i++)
 {
 oss << "    " << kin_reactions[i] << "\n";
@@ -1383,7 +1421,7 @@ for (int isel = 0; isel < phreeqc_rm.GetSelectedOutputCount(); isel++)
   status = phreeqc_rm.SetCurrentSelectedOutputUserNumber(n_user);
   std::cerr << "Selected output sequence number: " << isel << "\n";
   std::cerr << "Selected output user number:     " << n_user << "\n";
-  std::vector so;
+  std::vector< double > so;
   int col = phreeqc_rm.GetSelectedOutputColumnCount();
   status = phreeqc_rm.GetSelectedOutput(so);
   // Process results here
@@ -1435,22 +1473,42 @@ defined by the last use of @ref SetPoreVolume or the default (0.1 L).
 Pore volume is used with cell volume (@ref SetCellVolume) in calculating porosity.
 Pore volumes may change as a function of pressure, in which case they can be updated
 with @ref SetPoreVolume.
-@retval const std::vector&       A vector reference to the pore volumes.
+@retval const std::vector< double >&       A vector reference to the pore volumes.
 Size of vector is @a nxyz, the number of grid cells in the user's model (@ref GetGridCellCount).
 @see                 @ref GetCellVolume, @ref SetCellVolume, @ref SetPoreVolume.
 @par C++ Example:
 @htmlonly
 
 
-const std::vector & vol = phreeqc_rm.GetPoreVolume();
+const std::vector< double > & vol = phreeqc_rm.GetPoreVolume();
 
@endhtmlonly @par MPI: Called by root and (or) workers. */ - std::vector & GetPoreVolume(void) {return this->pore_volume;} + std::vector< double > & GetPoreVolume(void) {return this->pore_volume;} #endif +/** + Returns the porosity for each cell. + By default, the porosity vector is initialized with 0.1, unitless. + PhreeqcRM does not change the porosity, so the values that are retrieved are + either the default, or the values set by the last call to @ref SetPorosity. + @retval const std::vector< double >& A vector reference to the porosities in each cell, unitless. + Size of vector is @a nxyz, the number of grid cells in the user's model (@ref GetGridCellCount). + @see @ref SetPorosity, ref SetPressure, @ref GetTemperature, @ref SetTemperature. + @par C++ Example: + @htmlonly + +
+	const std::vector< double > & por = phreeqc_rm.GetPorosity();
+	
+
+ @endhtmlonly + @par MPI: + Called by root. + */ + const std::vector< double >& GetPorosity(void); /** Returns the pressure for each cell. By default, the pressure vector is initialized with 1 atm; @@ -1458,26 +1516,26 @@ if @ref SetPressure has not been called, worker solutions will have pressures as input files (@ref RunFile) or input strings (@ref RunString); if @ref SetPressure has been called, worker solutions will have the pressures as defined by @ref SetPressure. Pressure effects are considered by three PHREEQC databases: phreeqc.dat, Amm.dat, and pitzer.dat. -@retval const std::vector& A vector reference to the pressures in each cell, in atm. +@retval const std::vector< double >& A vector reference to the pressures in each cell, in atm. Size of vector is @a nxyz, the number of grid cells in the user's model (@ref GetGridCellCount). @see @ref SetPressure, @ref GetTemperature, @ref SetTemperature. @par C++ Example: @htmlonly
-const std::vector & p_atm = phreeqc_rm.GetPressure();
+const std::vector< double > & p_atm = phreeqc_rm.GetPressure();
 
@endhtmlonly @par MPI: Called by root and (or) workers. */ - const std::vector & GetPressure(void); + const std::vector< double > & GetPressure(void); /** Return a reference to the vector of print flags that enable or disable detailed output for each cell. Printing for a cell will occur only when the printing is enabled with @ref SetPrintChemistryOn, and the value in the vector for the cell is 1. -@retval std::vector & Vector of integers. Size of vector is @a nxyz, where @a nxyz is the number +@retval std::vector< int > & Vector of integers. Size of vector is @a nxyz, where @a nxyz is the number of grid cells in the user's model (@ref GetGridCellCount). A value of 0 for a cell indicates printing is disabled; a value of 1 for a cell indicates printing is enabled. @@ -1486,14 +1544,14 @@ a value of 1 for a cell indicates printing is enabled. @htmlonly
-const std::vector & print_chemistry_mask1 = phreeqc_rm.GetPrintChemistryMask();
+const std::vector< int > & print_chemistry_mask1 = phreeqc_rm.GetPrintChemistryMask();
 
@endhtmlonly @par MPI: Called by root. */ - const std::vector & GetPrintChemistryMask (void) {return this->print_chem_mask_root;} + const std::vector< int > & GetPrintChemistryMask (void) {return this->print_chem_mask_root;} /** Returns a vector reference to the current print flags for detailed output for the three sets of IPhreeqc instances: the workers, the InitialPhreeqc instance, and the Utility instance. Dimension of the vector is 3. @@ -1509,13 +1567,13 @@ amount of information printed can be limited by use of options in the PRINT data (applied by using @ref RunFile or @ref RunString). Printing the detailed output for the workers is generally used only for debugging, and PhreeqcRM will run faster when printing detailed output for the workers is disabled (@ref SetPrintChemistryOn). -@retval const std::vector & Print flag for the workers, InitialPhreeqc, and Utility IPhreeqc instances, respectively. +@retval const std::vector< bool > & Print flag for the workers, InitialPhreeqc, and Utility IPhreeqc instances, respectively. @see @ref SetPrintChemistryOn, @ref SetPrintChemistryMask. @par C++ Example: @htmlonly
-const std::vector & print_on = phreeqc_rm.GetPrintChemistryOn();
+const std::vector< bool > & print_on = phreeqc_rm.GetPrintChemistryOn();
 
@endhtmlonly @@ -1573,7 +1631,9 @@ Called by root. */ double GetRebalanceFraction(void) const {return this->rebalance_fraction;} /** -Returns a vector of saturations (@a sat) as calculated by the reaction module. +Returns a vector of saturations (@a sat) as calculated by the reaction module. +This method always returns solution_volume/(rv * porosity); the method +@ref SetSaturation has no effect on the values returned. Reactions will change the volume of solution in a cell. The transport code must decide whether to ignore or account for this change in solution volume due to reactions. Following reactions, the cell saturation is calculated as solution volume (@ref GetSolutionVolume) @@ -1594,7 +1654,7 @@ Values for inactive cells are set to 1e30. @htmlonly
-std::vector sat;
+std::vector< double > sat;
 status = phreeqc_rm.GetSaturation(sat);
 
@@ -1602,7 +1662,7 @@ status = phreeqc_rm.GetSaturation(sat); @par MPI: Called by root, workers must be in the loop of @ref MpiWorker. */ -IRM_RESULT GetSaturation(std::vector & sat); +IRM_RESULT GetSaturation(std::vector< double > & sat); /** Returns the array of selected-output values for the current selected-output definition. @ref SetCurrentSelectedOutputUserNumber @@ -1631,7 +1691,7 @@ for (int isel = 0; isel < phreeqc_rm.GetSelectedOutputCount(); isel++) { int n_user = phreeqc_rm.GetNthSelectedOutputUserNumber(isel); status = phreeqc_rm.SetCurrentSelectedOutputUserNumber(n_user); - std::vector so; + std::vector< double > so; int col = phreeqc_rm.GetSelectedOutputColumnCount(); status = phreeqc_rm.GetSelectedOutput(so); // Process results here @@ -1642,7 +1702,7 @@ for (int isel = 0; isel < phreeqc_rm.GetSelectedOutputCount(); isel++) @par MPI: Called by root, workers must be in the loop of @ref MpiWorker. */ - IRM_RESULT GetSelectedOutput(std::vector &so); + IRM_RESULT GetSelectedOutput(std::vector< double > &so); /** Returns the number of columns in the current selected-output definition. @ref SetCurrentSelectedOutputUserNumber specifies which of the selected-output definitions is used. @@ -1667,13 +1727,13 @@ for (int isel = 0; isel < phreeqc_rm.GetSelectedOutputCount(); isel++) { int n_user = phreeqc_rm.GetNthSelectedOutputUserNumber(isel); status = phreeqc_rm.SetCurrentSelectedOutputUserNumber(n_user); - std::vector so; + std::vector< double > so; int col = phreeqc_rm.GetSelectedOutputColumnCount(); status = phreeqc_rm.GetSelectedOutput(so); // Print results for (int i = 0; i < phreeqc_rm.GetSelectedOutputRowCount()/2; i++) { - std::vector headings; + std::vector< std::string > headings; headings.resize(col); std::cerr << " Selected output: " << "\n"; for (int j = 0; j < col; j++) @@ -1713,7 +1773,7 @@ for (int isel = 0; isel < phreeqc_rm.GetSelectedOutputCount(); isel++) { int n_user = phreeqc_rm.GetNthSelectedOutputUserNumber(isel); status = phreeqc_rm.SetCurrentSelectedOutputUserNumber(n_user); - std::vector so; + std::vector< double > so; int col = phreeqc_rm.GetSelectedOutputColumnCount(); status = phreeqc_rm.GetSelectedOutput(so); // Process results here @@ -1751,10 +1811,10 @@ for (int isel = 0; isel < phreeqc_rm.GetSelectedOutputCount(); isel++) { int n_user = phreeqc_rm.GetNthSelectedOutputUserNumber(isel); status = phreeqc_rm.SetCurrentSelectedOutputUserNumber(n_user); - std::vector so; + std::vector< double > so; int col = phreeqc_rm.GetSelectedOutputColumnCount(); status = phreeqc_rm.GetSelectedOutput(so); - std::vector headings; + std::vector< std::string > headings; headings.resize(col); std::cerr << " Selected output: " << "\n"; for (int j = 0; j < col; j++) @@ -1769,7 +1829,53 @@ for (int isel = 0; isel < phreeqc_rm.GetSelectedOutputCount(); isel++) @par MPI: Called by root. */ - IRM_RESULT GetSelectedOutputHeading(int icol, std::string &heading); + IRM_RESULT GetSelectedOutputHeading(int icol, std::string &heading); + /** + Returns a list of the current selected-output headings. + The number of headings is determined by @ref GetSelectedOutputColumnCount. + @ref SetCurrentSelectedOutputUserNumber or @ref BMI_SetValue("NthSelectedOutput",i) are + used to specify which of the selected-output definitions is used. + @param headings A vector of std::strings to receive the headings. + @retval IRM_RESULT 0 is success, negative is failure (See @ref DecodeError). + @see + @ref BMI_GetValue, + @ref GetCurrentSelectedOutputUserNumber, + @ref GetNthSelectedOutputUserNumber, + @ref GetSelectedOutput, + @ref GetSelectedOutputColumnCount, + @ref GetSelectedOutputCount, + @ref GetSelectedOutputHeading, + @ref GetSelectedOutputOn, + @ref GetSelectedOutputRowCount, + @ref SetCurrentSelectedOutputUserNumber, + @ref SetNthSelectedOutput, + @ref SetSelectedOutputOn. + @par C++ Example: + @htmlonly + +
+	for (int isel = 0; isel < phreeqc_rm.GetSelectedOutputCount(); isel++)
+	{
+	  int n_user = phreeqc_rm.GetNthSelectedOutputUserNumber(isel);
+	  status = phreeqc_rm.SetCurrentSelectedOutputUserNumber(n_user);
+	  std::vector< double > so;
+	  int col = phreeqc_rm.GetSelectedOutputColumnCount();
+	  status = phreeqc_rm.GetSelectedOutput(so);
+	  std::vector< std::string > headings;
+	  status = phreeqc_rm.GetSelectedOutputHeadings(headings);
+	  std::cerr << "     Selected output: " << "\n";
+	  for (int j = 0; j < col; j++)
+	  {
+		std::cerr << "          " << j << " " << headings[j] << "\n";
+	  }
+	}
+	
+
+ @endhtmlonly + @par MPI: + Called by root. + */ + IRM_RESULT GetSelectedOutputHeadings(std::vector< std::string >& headings); /** Returns the current value of the selected-output property. A value of true for this property indicates that selected output data will be requested this time step. @@ -1824,13 +1930,13 @@ for (int isel = 0; isel < phreeqc_rm.GetSelectedOutputCount(); isel++) { int n_user = phreeqc_rm.GetNthSelectedOutputUserNumber(isel); status = phreeqc_rm.SetCurrentSelectedOutputUserNumber(n_user); - std::vector so; + std::vector< double > so; int col = phreeqc_rm.GetSelectedOutputColumnCount(); status = phreeqc_rm.GetSelectedOutput(so); // Print results for (int i = 0; i < phreeqc_rm.GetSelectedOutputRowCount()/2; i++) { - std::vector headings; + std::vector< std::string > headings; headings.resize(col); std::cerr << " Selected output: " << "\n"; for (int j = 0; j < col; j++) @@ -1863,7 +1969,7 @@ could be calculated. @htmlonly
-const std::vector &si = phreeqc_rm.GetSINames();
+const std::vector< std::string > &si = phreeqc_rm.GetSINames();
 for (size_t i = 0; i < phreeqc_rm.GetSICount(); i++)
 {
 oss << "    " << si[i] << "\n";
@@ -1886,7 +1992,7 @@ it may be that one or more components are missing in any specific cell.
 This method may be useful when generating selected output definitions related to
 saturation indices.
 
-@retval const std::vector&       A vector of strings; each string is a unique
+@retval const std::vector< std::string >&       A vector of strings; each string is a unique
 phase name.
 
 @see                    @ref FindComponents,
@@ -1897,7 +2003,7 @@ phase name.
 
 oss << "  -saturation_indices " << "\n";
 // molalities of aqueous species
-const std::vector &si = phreeqc_rm.GetSINames();
+const std::vector< std::string > &si = phreeqc_rm.GetSINames();
 for (size_t i = 0; i < phreeqc_rm.GetSICount(); i++)
 {
 oss << "    " << si[i] << "\n";
@@ -1908,7 +2014,7 @@ oss << "    " << si[i] << "\n";
 @par MPI:
 Called by root.
 */
-const std::vector &          GetSINames(void) const { return this->SINamesList; }
+const std::vector< std::string > &          GetSINames(void) const { return this->SINamesList; }
 
 /**
 Returns a reference to the vector of solid solution components.
@@ -1918,7 +2024,7 @@ definitions in the initial-phreeqc module.
 This method may be useful when generating selected output definitions related to
 solid solutions.
 
-@retval const std::vector&       A vector of strings; each string is a
+@retval const std::vector< std::string >&       A vector of strings; each string is a
 unique solid solution component.
 
 @see                    @ref FindComponents,
@@ -1929,8 +2035,8 @@ unique solid solution component.
 
 oss << "  -solid_solutions " << "\n";
 // solid solutions
-const std::vector &ss_comps = phreeqc_rm.GetSolidSolutionComponents();
-const std::vector &ss_names = phreeqc_rm.GetSolidSolutionNames();
+const std::vector< std::string > &ss_comps = phreeqc_rm.GetSolidSolutionComponents();
+const std::vector< std::string > &ss_names = phreeqc_rm.GetSolidSolutionNames();
 for (size_t i = 0; i < phreeqc_rm.GetSolidSolutionComponentsCount(); i++)
 {
 
@@ -1945,7 +2051,7 @@ oss << " # " << ss_names[i] << "\n";
 @par MPI:
 Called by root.
 */
-const std::vector &          GetSolidSolutionComponents(void) const { return this->SolidSolutionComponentsList; }
+const std::vector< std::string > &          GetSolidSolutionComponents(void) const { return this->SolidSolutionComponentsList; }
 /**
 Returns the number of solid solution components in the initial-phreeqc module.
 @ref FindComponents must be called before @ref GetSolidSolutionComponentsCount.
@@ -1962,8 +2068,8 @@ This method may be useful when generating selected output definitions related to
 
 oss << "  -solid_solutions " << "\n";
 // solid solutions
-const std::vector &ss_comps = phreeqc_rm.GetSolidSolutionComponents();
-const std::vector &ss_names = phreeqc_rm.GetSolidSolutionNames();
+const std::vector< std::string > &ss_comps = phreeqc_rm.GetSolidSolutionComponents();
+const std::vector< std::string > &ss_names = phreeqc_rm.GetSolidSolutionNames();
 for (size_t i = 0; i < phreeqc_rm.GetSolidSolutionComponentsCount(); i++)
 {
 
@@ -1988,7 +2094,7 @@ The solid solution names vector is the same length as the solid solution compone
 and provides the corresponding name of solid solution containing the component.
 This method may be useful when generating selected output definitions related to solid solutions.
 
-@retval const std::vector&       A vector of strings; each string is a
+@retval const std::vector< std::string >&       A vector of strings; each string is a
 solid solution name corresponding to the solid solution components vector; a solid solution name may occur
 multiple times.
 
@@ -2000,8 +2106,8 @@ multiple times.
 
 oss << "  -solid_solutions " << "\n";
 // solid solutions
-const std::vector &ss_comps = phreeqc_rm.GetSolidSolutionComponents();
-const std::vector &ss_names = phreeqc_rm.GetSolidSolutionNames();
+const std::vector< std::string > &ss_comps = phreeqc_rm.GetSolidSolutionComponents();
+const std::vector< std::string > &ss_names = phreeqc_rm.GetSolidSolutionNames();
 for (size_t i = 0; i < phreeqc_rm.GetSolidSolutionComponentsCount(); i++)
 {
 
@@ -2016,7 +2122,7 @@ oss << " # " << ss_names[i] << "\n";
 @par MPI:
 Called by root.
 */
-const std::vector &          GetSolidSolutionNames(void) const { return this->SolidSolutionNamesList; }
+const std::vector< std::string > &          GetSolidSolutionNames(void) const { return this->SolidSolutionNamesList; }
 
 /**
 Return a vector reference to the current solution volumes as calculated by the reaction module.
@@ -2031,14 +2137,14 @@ needed to accurately calculate solution volume: phreeqc.dat, Amm.dat, and pitzer
 
 
 status = phreeqc_rm.RunCells();
-const std::vector &volume = phreeqc_rm.GetSolutionVolume();
+const std::vector< double > &volume = phreeqc_rm.GetSolutionVolume();
 
@endhtmlonly @par MPI: Called by root, workers must be in the loop of @ref MpiWorker. */ - const std::vector & GetSolutionVolume(void); + const std::vector< double > & GetSolutionVolume(void); /** Returns a vector reference to aqueous species concentrations (@a species_conc). This method is intended for use with multicomponent-diffusion transport calculations, @@ -2076,7 +2182,7 @@ status = phreeqc_rm.SetSpeciesSaveOn(true); int ncomps = phreeqc_rm.FindComponents(); int npecies = phreeqc_rm.GetSpeciesCount(); status = phreeqc_rm.RunCells(); -std::vector c; +std::vector< double > c; status = phreeqc_rm.GetSpeciesConcentrations(c);
@@ -2084,7 +2190,7 @@ status = phreeqc_rm.GetSpeciesConcentrations(c); @par MPI: Called by root, workers must be in the loop of @ref MpiWorker. */ - IRM_RESULT GetSpeciesConcentrations(std::vector & species_conc); + IRM_RESULT GetSpeciesConcentrations(std::vector< double > & species_conc); /** Returns the number of aqueous species used in the reaction module. This method is intended for use with multicomponent-diffusion transport calculations, @@ -2151,7 +2257,7 @@ const std::vector < double > & species_d = phreeqc_rm.GetSpeciesD25(); @par MPI: Called by root and (or) workers. */ - const std::vector & GetSpeciesD25(void) {return this->species_d_25;} + const std::vector< double > & GetSpeciesD25(void) {return this->species_d_25;} /** Returns a vector reference to log10 aqueous species activity coefficients (@a species_log10gammas). This method is intended for use with multicomponent-diffusion transport calculations, @@ -2185,7 +2291,7 @@ status = phreeqc_rm.SetSpeciesSaveOn(true); int ncomps = phreeqc_rm.FindComponents(); int npecies = phreeqc_rm.GetSpeciesCount(); status = phreeqc_rm.RunCells(); -std::vector species_gammas; +std::vector< double > species_gammas; status = phreeqc_rm.GetSpeciesLog10Gammas(species_gammas);
@@ -2193,7 +2299,7 @@ status = phreeqc_rm.GetSpeciesLog10Gammas(species_gammas); @par MPI: Called by root, workers must be in the loop of @ref MpiWorker. */ - IRM_RESULT GetSpeciesLog10Gammas(std::vector & species_log10gammas); + IRM_RESULT GetSpeciesLog10Gammas(std::vector< double > & species_log10gammas); /** Returns a vector reference to log10 aqueous species molalities (@a species_log10molalities). @@ -2227,7 +2333,7 @@ status = phreeqc_rm.SetSpeciesSaveOn(true); int ncomps = phreeqc_rm.FindComponents(); int npecies = phreeqc_rm.GetSpeciesCount(); status = phreeqc_rm.RunCells(); -std::vector species_molalities; +std::vector< double > species_molalities; status = phreeqc_rm.GetSpeciesLog10Molalities(species_molalities);
@@ -2235,7 +2341,7 @@ status = phreeqc_rm.GetSpeciesLog10Molalities(species_molalities); @par MPI: Called by root, workers must be in the loop of @ref MpiWorker. */ -IRM_RESULT GetSpeciesLog10Molalities(std::vector& species_log10molalities); +IRM_RESULT GetSpeciesLog10Molalities(std::vector< double >& species_log10molalities); /** Returns a vector reference to the names of the aqueous species. @@ -2263,14 +2369,14 @@ where @a nspecies is the number of aqueous species (@ref GetSpeciesCount). status = phreeqc_rm.SetSpeciesSaveOn(true); int ncomps = phreeqc_rm.FindComponents(); int npecies = phreeqc_rm.GetSpeciesCount(); -const std::vector &species = phreeqc_rm.GetSpeciesNames(); +const std::vector< std::string > &species = phreeqc_rm.GetSpeciesNames();
@endhtmlonly @par MPI: Called by root and (or) workers. */ - const std::vector & GetSpeciesNames(void) {return this->species_names;} + const std::vector< std::string > & GetSpeciesNames(void) {return this->species_names;} /** Returns the value of the species-save property. By default, concentrations of aqueous species are not saved. Setting the species-save property to true allows @@ -2334,7 +2440,7 @@ where @a nspecies is the number of aqueous species (@ref GetSpeciesCount). @htmlonly
-const std::vector &species = phreeqc_rm.GetSpeciesNames();
+const std::vector< std::string > &species = phreeqc_rm.GetSpeciesNames();
 const std::vector < double > & species_z = phreeqc_rm.GetSpeciesZ();
 const std::vector < double > & species_d = phreeqc_rm.GetSpeciesD25();
 bool species_on = phreeqc_rm.GetSpeciesSaveOn();
@@ -2391,7 +2497,7 @@ const std::vector < double > & species_z = phreeqc_rm.GetSpeciesZ();
 @par MPI:
 Called by root and (or) workers.
  */
-	const std::vector &               GetSpeciesZ(void) {return this->species_z;}
+	const std::vector< double > &               GetSpeciesZ(void) {return this->species_z;}
 /**
 Returns a vector of integers that contains the smallest reaction-cell number assigned to each worker.
 Each worker is assigned a range of reaction-cell numbers that are run during a call to @ref RunCells.
@@ -2435,7 +2541,7 @@ and @ref GetSurfaceNames are the same length.
 @ref FindComponents must be called before @ref GetSurfaceNames.
 This method may be useful when generating selected output definitions related to surfaces.
 
-@retval const std::vector&       A vector of strings; each string is a
+@retval const std::vector< std::string >&       A vector of strings; each string is a
 surface name corresponding to the surface species vector;
 a surface name may occur multiple times.
 
@@ -2446,9 +2552,9 @@ a surface name may occur multiple times.
 
 
 // molalities of surface species
-const std::vector &surf_species = phreeqc_rm.GetSurfaceSpecies();
-const std::vector &surf_types = phreeqc_rm.GetSurfaceTypes();
-const std::vector &surf_names = phreeqc_rm.GetSurfaceNames();
+const std::vector< std::string > &surf_species = phreeqc_rm.GetSurfaceSpecies();
+const std::vector< std::string > &surf_types = phreeqc_rm.GetSurfaceTypes();
+const std::vector< std::string > &surf_names = phreeqc_rm.GetSurfaceNames();
 for (size_t i = 0; i < phreeqc_rm.GetSurfaceSpeciesCount(); i++)
 {
 oss << "    ";
@@ -2464,7 +2570,7 @@ oss << surf_types[i] << "   " << surf_names[i] << "\n";
 @par MPI:
 Called by root.
 */
-const std::vector &          GetSurfaceNames(void) const { return this->SurfaceNamesList; }
+const std::vector< std::string > &          GetSurfaceNames(void) const { return this->SurfaceNamesList; }
 
 /**
 Returns a reference to the vector of surface species names (such as "Hfo_wOH").
@@ -2474,7 +2580,7 @@ that are included in SURFACE definitions in the initial-phreeqc module.
 @ref FindComponents must be called before @ref GetSurfaceSpecies.
 This method may be useful when generating selected output definitions related to surfaces.
 
-@retval const std::vector&       A vector of strings; each string is a
+@retval const std::vector< std::string >&       A vector of strings; each string is a
 unique surface species name.
 @see                    @ref FindComponents,
 @ref GetSurfaceSpeciesCount, @ref GetSurfaceTypes, @ref GetSurfaceNames.
@@ -2483,9 +2589,9 @@ unique surface species name.
 
 
 // molalities of surface species
-const std::vector &surf_species = phreeqc_rm.GetSurfaceSpecies();
-const std::vector &surf_types = phreeqc_rm.GetSurfaceTypes();
-const std::vector &surf_names = phreeqc_rm.GetSurfaceNames();
+const std::vector< std::string > &surf_species = phreeqc_rm.GetSurfaceSpecies();
+const std::vector< std::string > &surf_types = phreeqc_rm.GetSurfaceTypes();
+const std::vector< std::string > &surf_names = phreeqc_rm.GetSurfaceNames();
 for (size_t i = 0; i < phreeqc_rm.GetSurfaceSpeciesCount(); i++)
 {
 oss << "    ";
@@ -2501,7 +2607,7 @@ oss << surf_types[i] << "   " << surf_names[i] << "\n";
 @par MPI:
 Called by root.
 */
-const std::vector &          GetSurfaceSpecies(void) const { return this->SurfaceSpeciesNamesList; }
+const std::vector< std::string > &          GetSurfaceSpecies(void) const { return this->SurfaceSpeciesNamesList; }
 
 /**
 Returns the number of surface species (such as "Hfo_wOH") in the initial-phreeqc module.
@@ -2517,9 +2623,9 @@ This method may be useful when generating selected output definitions related to
 
 
 // molalities of surface species
-const std::vector &surf_species = phreeqc_rm.GetSurfaceSpecies();
-const std::vector &surf_types = phreeqc_rm.GetSurfaceTypes();
-const std::vector &surf_names = phreeqc_rm.GetSurfaceNames();
+const std::vector< std::string > &surf_species = phreeqc_rm.GetSurfaceSpecies();
+const std::vector< std::string > &surf_types = phreeqc_rm.GetSurfaceTypes();
+const std::vector< std::string > &surf_names = phreeqc_rm.GetSurfaceNames();
 for (size_t i = 0; i < phreeqc_rm.GetSurfaceSpeciesCount(); i++)
 {
 oss << "    ";
@@ -2546,7 +2652,7 @@ The vectors referenced by @ref GetSurfaceSpecies and
 @ref FindComponents must be called before @ref GetSurfaceTypes.
 This method may be useful when generating selected output definitions related to surfaces.
 
-@retval const std::vector&       A vector of strings; each string is a
+@retval const std::vector< std::string >&       A vector of strings; each string is a
 surface site type for the corresponding species in the surface species vector;
 a surface site type may occur multiple times.
 
@@ -2557,9 +2663,9 @@ a surface site type may occur multiple times.
 
 
 // molalities of surface species
-const std::vector &surf_species = phreeqc_rm.GetSurfaceSpecies();
-const std::vector &surf_types = phreeqc_rm.GetSurfaceTypes();
-const std::vector &surf_names = phreeqc_rm.GetSurfaceNames();
+const std::vector< std::string > &surf_species = phreeqc_rm.GetSurfaceSpecies();
+const std::vector< std::string > &surf_types = phreeqc_rm.GetSurfaceTypes();
+const std::vector< std::string > &surf_names = phreeqc_rm.GetSurfaceNames();
 for (size_t i = 0; i < phreeqc_rm.GetSurfaceSpeciesCount(); i++)
 {
 oss << "    ";
@@ -2575,7 +2681,7 @@ oss << surf_types[i] << "   " << surf_names[i] << "\n";
 @par MPI:
 Called by root.
 */
-const std::vector &          GetSurfaceTypes(void) const { return this->SurfaceTypesList; }
+const std::vector< std::string > &          GetSurfaceTypes(void) const { return this->SurfaceTypesList; }
 
 /**
 Vector reference to the current temperatures of the cells.
@@ -2590,15 +2696,19 @@ of grid cells in the user's model (@ref GetGridCellCount).
 @htmlonly
 
 
-const std::vector &  tempc = phreeqc_rm.GetTemperature();
+const std::vector< double > &  tempc = phreeqc_rm.GetTemperature();
 
@endhtmlonly @par MPI: Called by root. */ - //const std::vector & GetTemperature(void) {return this->tempc;} - const std::vector & GetTemperature(void); + //const std::vector< double > & GetTemperature(void) {return this->tempc;} + const std::vector< double > & GetTemperature(void); + +#ifdef VISCOSITY + IRM_RESULT GetViscosity(std::vector& viscosity_arg); +#endif /** Returns the number of threads, which is equal to the number of workers used to run in parallel with OPENMP. For the OPENMP version, the number of threads is set implicitly or explicitly @@ -2951,7 +3061,10 @@ The names of the map keys for map arguments are not used in parsing the YAML file; only the order of the arguments is important. -The PhreeqcRM methods that can be specified in a YAML file include: +The class YAMLPhreeqcRM can be used to write a YAML file. +The methods defined in the YAMLPhreeqcRM class include the +following list; +all but SetGridCellCount correspond to PhreeqcRM methods. @htmlonly
@@ -2979,6 +3092,7 @@ SetErrorOn(bool tf);
 SetFilePrefix(std::string prefix);
 SetGasCompMoles(std::vector< double > gas_moles);
 SetGasPhaseVolume(std::vector< double > gas_volume);
+SetGridCellCount(int nxyz);
 SetPartitionUZSolids(bool tf);
 SetPorosity(std::vector< double > por);
 SetPressure(std::vector< double > p);
@@ -3016,8 +3130,11 @@ WarningMessage(std::string warnstr);
 @htmlonly
 
 
+		int nthreads = 0;
+		std::string yaml_file = "myfile.yaml";
+		int nxyz = GetGridCellCountYAML(yaml_file);
 		PhreeqcRM phreeqc_rm(nxyz, nthreads);
-		phreeqc_rm.InitializeYAML("myfile.yaml");
+		phreeqc_rm.InitializeYAML(yaml_file);
 
@endhtmlonly @@ -3042,8 +3159,8 @@ Size is @a n_boundary. @htmlonly
-std::vector bc_conc;
-std::vector bc1;
+std::vector< double > bc_conc;
+std::vector< int > bc1;
 int nbound = 1;
 bc1.resize(nbound, 0);                      // solution 0 from InitialIPhreeqc instance
 status = phreeqc_rm.InitialPhreeqc2Concentrations(bc_conc, bc1);
@@ -3055,7 +3172,7 @@ Called by root.
  */
 	IRM_RESULT                                InitialPhreeqc2Concentrations(
 													std::vector < double > & destination_c,
-													std::vector < int >    & boundary_solution1);
+													const std::vector < int >    & boundary_solution1);
 /**
 Fills a vector (@a destination_c) with concentrations from solutions in the InitialPhreeqc instance.
 The method is used to obtain concentrations for boundary conditions that are mixtures of solutions. If a negative value
@@ -3081,8 +3198,8 @@ Size is @a n_boundary.
 @htmlonly
 
 
-std::vector bc_conc, bc_f1;
-std::vector bc1, bc2;
+std::vector< double > bc_conc, bc_f1;
+std::vector< int > bc1, bc2;
 int nbound = 1;
 bc1.resize(nbound, 0);                      // solution 0 from InitialIPhreeqc instance
 bc2.resize(nbound, 1);                      // solution 1 from InitialIPhreeqc instance
@@ -3096,9 +3213,9 @@ Called by root.
  */
 	IRM_RESULT								  InitialPhreeqc2Concentrations(
 													std::vector < double > & destination_c,
-													std::vector < int >    & boundary_solution1,
-													std::vector < int >    & boundary_solution2,
-													std::vector < double > & fraction1);
+													const std::vector < int >    & boundary_solution1,
+													const std::vector < int >    & boundary_solution2,
+													const std::vector < double > & fraction1);
 /**
 Transfer solutions and reactants from the InitialPhreeqc instance to the reaction-module workers.
 @a Initial_conditions1 is used to select initial conditions, including solutions and reactants,
@@ -3120,7 +3237,7 @@ Negative values are ignored, resulting in no definition of that entity for that
 @htmlonly
 
 
-std::vector ic1;
+std::vector< int > ic1;
 ic1.resize(nxyz*7, -1);
 for (int i = 0; i < nxyz; i++)
 {
@@ -3139,7 +3256,7 @@ status = phreeqc_rm.InitialPhreeqc2Module(ic1);
 @par MPI:
 Called by root, workers must be in the loop of @ref MpiWorker.
  */
-	IRM_RESULT  InitialPhreeqc2Module(std::vector < int >    & initial_conditions1);
+	IRM_RESULT  InitialPhreeqc2Module(const std::vector < int >    & initial_conditions1);
 /**
 Transfer solutions and reactants from the InitialPhreeqc instance to the reaction-module workers, possibly with mixing.
 In its simplest form, @a  initial_conditions1 is used to select initial conditions, including solutions and reactants,
@@ -3180,10 +3297,10 @@ Size is 7 times @a nxyz. The order of definitions is given above.
 @htmlonly
 
 
-std::vector ic1, ic2;
+std::vector< int > ic1, ic2;
 ic1.resize(nxyz*7, -1);
 ic2.resize(nxyz*7, -1);
-std::vector f1;
+std::vector< double > f1;
 f1.resize(nxyz*7, 1.0);
 for (int i = 0; i < nxyz; i++)
 {
@@ -3203,7 +3320,7 @@ status = phreeqc_rm.InitialPhreeqc2Module(ic1, ic2, f1);
 Called by root, workers must be in the loop of @ref MpiWorker.
  */
 	IRM_RESULT InitialPhreeqc2Module(
-		std::vector < int >    & initial_conditions1,
+		const std::vector < int >    & initial_conditions1,
 		std::vector < int >    & initial_conditions2,
 		std::vector < double > & fraction1);
 /**
@@ -3224,8 +3341,8 @@ and @a n_boundary is the dimension of @a boundary_solution1.
 @htmlonly
 
 
-std::vector bc_conc, bc_f1;
-std::vector bc1, bc2;
+std::vector< double > bc_conc, bc_f1;
+std::vector< int > bc1, bc2;
 int nbound = 1;
 bc1.resize(nbound, 0);                      // solution 0 from Initial IPhreeqc instance
 status = phreeqc_rm.InitialPhreeqc2SpeciesConcentrations(bc_conc, bc1);
@@ -3264,8 +3381,8 @@ Size is same as @a boundary_solution1.
 @htmlonly
 
 
-std::vector bc_conc, bc_f1;
-std::vector bc1, bc2;
+std::vector< double > bc_conc, bc_f1;
+std::vector< int > bc1, bc2;
 int nbound = 1;
 bc1.resize(nbound, 0);                      // solution 0 from Initial IPhreeqc instance
 bc2.resize(nbound, -1);                     // no bc2 solution for mixing
@@ -3298,7 +3415,7 @@ will be populated with cell @a n from the InitialPhreeqc instance.
 @htmlonly
 
 
-std::vector module_cells;
+std::vector< int > module_cells;
 module_cells.push_back(18);
 module_cells.push_back(19);
 status = phreeqc_rm.InitialPhreeqcCell2Module(-1, module_cells);
@@ -3308,7 +3425,7 @@ status = phreeqc_rm.InitialPhreeqcCell2Module(-1, module_cells);
 @par MPI:
 Called by root, workers must be in the loop of @ref MpiWorker.
  */
-	IRM_RESULT                                InitialPhreeqcCell2Module(int n, const std::vector &cell_numbers);
+	IRM_RESULT                                InitialPhreeqcCell2Module(int n, const std::vector< int > &cell_numbers);
 /**
 Load a database for all IPhreeqc instances--workers, InitialPhreeqc, and Utility. All definitions
 of the reaction module are cleared (SOLUTION_SPECIES, PHASES, SOLUTIONs, etc.), and the database is read.
@@ -3649,7 +3766,7 @@ by @ref FindComponents or @ref GetComponentCount and
 @htmlonly
 
 
-std::vector c;
+std::vector< double > c;
 c.resize(nxyz * components.size());
 ...
 AdvectCpp(c, bc_conc, ncomps, nxyz, nbound);
@@ -3668,7 +3785,7 @@ status = phreeqc_rm.RunCells();
 @par MPI:
 Called by root, workers must be in the loop of @ref MpiWorker.
  */
-	IRM_RESULT                                SetConcentrations(const std::vector &c);
+	IRM_RESULT                                SetConcentrations(const std::vector< double > &c);
 /**
 Select the current selected output by user number. The user may define multiple SELECTED_OUTPUT
 data blocks for the workers. A user number is specified for each data block. The value of
@@ -3697,7 +3814,7 @@ for (int isel = 0; isel < phreeqc_rm.GetSelectedOutputCount(); isel++)
   status = phreeqc_rm.SetCurrentSelectedOutputUserNumber(n_user);
   std::cerr << "Selected output sequence number: " << isel << "\n";
   std::cerr << "Selected output user number:     " << n_user << "\n";
-  std::vector so;
+  std::vector< double > so;
   status = phreeqc_rm.GetSelectedOutput(so);
   // Process results here
 }
@@ -3723,7 +3840,7 @@ of grid cells in the user's model (@ref GetGridCellCount).
 @htmlonly
 
 
-std::vector initial_density;
+std::vector< double > initial_density;
 initial_density.resize(nxyz, 1.0);
 phreeqc_rm.SetDensity(initial_density);
 
@@ -3732,7 +3849,7 @@ phreeqc_rm.SetDensity(initial_density); @par MPI: Called by root, workers must be in the loop of @ref MpiWorker. */ - IRM_RESULT SetDensity(const std::vector &density); + IRM_RESULT SetDensity(const std::vector< double > &density); /** Set the name of the dump file. It is the name used by @ref DumpModule. @param dump_name Name of dump file. @@ -3838,7 +3955,7 @@ not be defined for the GAS_PHASE of the reaction cell. @htmlonly
-std::vector gas_moles;
+std::vector< double > gas_moles;
 gas_moles.resize(nxyz*ngas);
 ...
 status = phreeqc_rm.SetGasCompMoles(gas_moles);
@@ -3849,7 +3966,7 @@ status = phreeqc_rm.RunCells();
 @par MPI:
 Called by root, workers must be in the loop of @ref MpiWorker.
 	*/
-IRM_RESULT                                SetGasCompMoles(const std::vector& gas_moles);
+IRM_RESULT                                SetGasCompMoles(const std::vector< double >& gas_moles);
 /**
 Transfer volumes of gas phases from
 the vector given in the argument list (@a gas_volume) to each reaction cell.
@@ -3877,7 +3994,7 @@ not changed.
 @htmlonly
 
 
-std::vector gas_volume;
+std::vector< double > gas_volume;
 gas_volume.resize(nxyz, -1.0);
 ...
 status = phreeqc_rm.SetGasPhaseVolume(gas_volume);
@@ -3888,7 +4005,7 @@ status = phreeqc_rm.RunCells();
 @par MPI:
 Called by root, workers must be in the loop of @ref MpiWorker.
 	*/
-IRM_RESULT                                SetGasPhaseVolume(const std::vector& gas_volume);
+IRM_RESULT                                SetGasPhaseVolume(const std::vector< double >& gas_volume);
 
 /**
 MPI and C/C++ only. Defines a callback function that allows additional tasks to be done
@@ -4089,13 +4206,13 @@ for (int isel = 0; isel < phreeqc_rm.GetSelectedOutputCount(); isel++)
 {
 	status = phreeqc_rm.SetCurrentSelectedOutput(isel);
 	int n_user = phreeqc_rm.GetCurrentSelectedOutputUserNumber(isel);
-	std::vector so;
+	std::vector< double > so;
 	int col = phreeqc_rm.GetSelectedOutputColumnCount();
 	status = phreeqc_rm.GetSelectedOutput(so);
 	// Print results
 	for (int i = 0; i < phreeqc_rm.GetSelectedOutputRowCount()/2; i++)
 	{
-		std::vector headings;
+		std::vector< std::string > headings;
 		headings.resize(col);
 		std::cerr << "     Selected output " << n_user <<": " << "\n";
 		for (int j = 0; j < col; j++)
@@ -4161,7 +4278,7 @@ of grid cells in the user's model (@ref GetGridCellCount).
 @htmlonly
 
 
-std::vector por;
+std::vector< double > por;
 por.resize(nxyz, 0.2);
 status = phreeqc_rm.SetPorosity(por);
 
@@ -4170,7 +4287,7 @@ status = phreeqc_rm.SetPorosity(por); @par MPI: Called by root, workers must be in the loop of @ref MpiWorker. */ - IRM_RESULT SetPorosity(const std::vector &por); + IRM_RESULT SetPorosity(const std::vector< double > &por); /** Set the pressure for each reaction cell. Pressure effects are considered only in three of the @@ -4183,7 +4300,7 @@ where @a nxyz is the number of grid cells in the user's model (@ref GetGridCellC @htmlonly
-std::vector pressure;
+std::vector< double > pressure;
 pressure.resize(nxyz, 2.0);
 phreeqc_rm.SetPressure(pressure);
 
@@ -4192,7 +4309,7 @@ phreeqc_rm.SetPressure(pressure); @par MPI: Called by root, workers must be in the loop of @ref MpiWorker. */ - IRM_RESULT SetPressure(const std::vector &p); + IRM_RESULT SetPressure(const std::vector< double > &p); /** Enable or disable detailed output for each reaction cell. Printing for a reaction cell will occur only when the @@ -4206,7 +4323,7 @@ disable printing detailed output for the cell; a value of 1 will enable printing @htmlonly
-std::vector print_chemistry_mask;
+std::vector< int > print_chemistry_mask;
 print_chemistry_mask.resize(nxyz, 0);
 for (int i = 0; i < nxyz/2; i++)
 {
@@ -4219,7 +4336,7 @@ status = phreeqc_rm.SetPrintChemistryMask(print_chemistry_mask);
 @par MPI:
 Called by root, workers must be in the loop of @ref MpiWorker.
  */
-	IRM_RESULT                                SetPrintChemistryMask(std::vector & cell_mask);
+	IRM_RESULT                                SetPrintChemistryMask(const std::vector & cell_mask);
 /**
 Set property that enables or disables printing detailed output from reaction calculations
 to the output file for a set of cells defined by @ref SetPrintChemistryMask.
@@ -4331,7 +4448,7 @@ of grid cells in the user's model (@ref GetGridCellCount).
 @htmlonly
 
 
-std::vector rv;
+std::vector< double > rv;
 rv.resize(nxyz, 2.0);
 status = phreeqc_rm.SetRepresentativeVolume(rv);
 
@@ -4340,7 +4457,7 @@ status = phreeqc_rm.SetRepresentativeVolume(rv); @par MPI: Called by root, workers must be in the loop of @ref MpiWorker. */ - IRM_RESULT SetRepresentativeVolume(const std::vector &rv); + IRM_RESULT SetRepresentativeVolume(const std::vector< double > &rv); /** Set the saturation of each reaction cell. Saturation is a fraction ranging from 0 to 1. The volume of water in a cell is the product of porosity (@ref SetPorosity), saturation (@a SetSaturation), @@ -4360,7 +4477,7 @@ where @a nxyz is the number of grid cells in the user's model (@ref GetGridCellC @htmlonly
-std::vector sat;
+std::vector< double > sat;
 sat.resize(nxyz, 1.0);
 status = phreeqc_rm.SetSaturation(sat);
 
@@ -4369,7 +4486,7 @@ status = phreeqc_rm.SetSaturation(sat); @par MPI: Called by root, workers must be in the loop of @ref MpiWorker. */ - IRM_RESULT SetSaturation(const std::vector &sat); + IRM_RESULT SetSaturation(const std::vector< double > &sat); /** Set the property that controls whether messages are written to the screen. Messages include information about rebalancing during @ref RunCells, and @@ -4475,7 +4592,7 @@ of grid cells in the user's model (@ref GetGridCellCount). @htmlonly
-std::vector temperature;
+std::vector< double > temperature;
 temperature.resize(nxyz, 20.0);
 phreeqc_rm.SetTemperature(temperature);
 
@@ -4484,7 +4601,7 @@ phreeqc_rm.SetTemperature(temperature); @par MPI: Called by root and (or) workers. */ - IRM_RESULT SetTemperature(const std::vector &t); + IRM_RESULT SetTemperature(const std::vector< double > &t); /** Set current simulation time for the reaction module. @param time Current simulation time, in seconds. @@ -4843,7 +4960,7 @@ Concentrations are moles per liter. status = phreeqc_rm.SetSpeciesSaveOn(true); int ncomps = phreeqc_rm.FindComponents(); int nspecies = phreeqc_rm.GetSpeciesCount(); -std::vector c; +std::vector< double > c; status = phreeqc_rm.GetSpeciesConcentrations(c); ... SpeciesAdvectCpp(c, bc_conc, nspecies, nxyz, nbound); @@ -4855,7 +4972,7 @@ status = phreeqc_rm.RunCells(); @par MPI: Called by root, workers must be in the loop of @ref MpiWorker. */ -IRM_RESULT SpeciesConcentrations2Module(std::vector & species_conc); +IRM_RESULT SpeciesConcentrations2Module(std::vector< double > & species_conc); /** Save the state of the chemistry in all model cells, including SOLUTIONs, @@ -4992,938 +5109,6 @@ phreeqc_rm.WarningMessage("Parameter is out of range, using default"); Called by root and (or) workers; only root writes to the log file. */ void WarningMessage(const std::string &warnstr); -// BMI data and methods -private: - std::map bmi_var_map; - std::vector bmi_input_vars; - std::vector bmi_output_vars; -public: - - //void BMI_Finalize(); -/** -Basic Model Interface method that returns the component name--PhreeqcRM. The BMI interface to PhreeqcRM is -only partial, and provides only the most basic functions. The native PhreeqcRM methods (those without the the BMI_ -prefix) provide a complete interface, and it is expected that the native methods will be used in preference to the BMI_ -methods. - -@retval The string "PhreeqcRM". -@par C++ Example: -@htmlonly - -
-std::cout << phreeqc_rm.BMI_GetComponentName();
-
-
-@endhtmlonly -@par MPI: -Called by root. -*/ - std::string BMI_GetComponentName() { return "PhreeqcRM"; } - - //-------------------------- - - /** - Basic Model Interface method that returns the current simulation time, in seconds. (Same as @ref GetTime.) - The reaction module does not change the time value, so the - returned value is equal to the default (0.0) or the last time set by - @ref BMI_SetValue("Time", time) or @ref SetTime. - @retval The current simulation time, in seconds. - @see - @ref BMI_GetEndTime, - @ref BMI_GetTimeStep, - @ref BMI_SetValue, - @ref GetTime, - @ref GetTimeStep, - @ref SetTime, - @ref SetTimeStep. - @par C++ Example: - @htmlonly - -
-	std::cout << "Current time: "
-		 << BMI_GetCurrentTime()
-		 << " seconds\n";
-	
-
- @endhtmlonly - @par MPI: - Called by root. - */ - double BMI_GetCurrentTime() { return this->GetTime(); } - - //-------------------------- - - /** - Basic Model Interface method that returns @ref BMI_GetCurrentTime plus @ref BMI_GetTimeStep, in seconds. - @retval The end of the time step, in seconds. - @see - @ref BMI_GetCurrentTime, - @ref BMI_GetTimeStep, - @ref BMI_SetValue, - @ref GetTime, - @ref GetTimeStep, - @ref SetTime, - @ref SetTimeStep. - @par C++ Example: - @htmlonly - -
-	std::cout << "End of time step "
-		 << BMI_GetEndTime()
-		 << " seconds\n";
-	
-
- @endhtmlonly - @par MPI: - Called by root. - */ - double BMI_GetEndTime() { return this->GetTime() + this->GetTimeStep(); } - - //-------------------------- - - /** - Basic Model Interface method that returns count of input variables that can be set with @ref BMI_SetValue. - @retval Count of input variables that can be set with @ref BMI_SetValue. - - @see - @ref BMI_GetInputVarNames, - @ref BMI_GetVarItemsize, - @ref BMI_GetVarNbytes, - @ref BMI_GetVarType, - @ref BMI_GetVarUnits, - @ref BMI_SetValue. - @par C++ Example: - @htmlonly - -
-			std::vector InputVarNames = phreeqc_rm.BMI_GetInputVarNames();
-			int count = phreeqc_rm.BMI_GetInputItemCount();
-			oss << "BMI_SetValue variables:\n";
-			for (size_t i = 0; i < count; i++)
-			{
-				oss << "  " << i << "  " << InputVarNames[i] << "\n";
-				oss << "     Type:        " << phreeqc_rm.BMI_GetVarType(InputVarNames[i]) << "\n";
-				oss << "     Units:       " << phreeqc_rm.BMI_GetVarUnits(InputVarNames[i]) << "\n";
-				oss << "     Total bytes: " << phreeqc_rm.BMI_GetVarNbytes(InputVarNames[i]) << "\n";
-				oss << "     Item bytes:  " << phreeqc_rm.BMI_GetVarItemsize(InputVarNames[i]) << "\n";
-				oss << "     Dim:         " << phreeqc_rm.BMI_GetVarNbytes(InputVarNames[i]) /
-											   phreeqc_rm.BMI_GetVarItemsize(InputVarNames[i]) << "\n";
-			}
-	
-
- @endhtmlonly - @par MPI: - Called by root. - */ - int BMI_GetInputItemCount() { return (int)this->bmi_input_vars.size(); } - - //-------------------------- - - /** - Basic Model Interface method that returns a list of the variable names that can be set with @ref BMI_SetValue. - @retval A list of the variable names that can be set with @ref BMI_SetValue. - - @see - @ref BMI_GetInputItemCount, - @ref BMI_GetVarItemsize, - @ref BMI_GetVarNbytes, - @ref BMI_GetVarType, - @ref BMI_GetVarUnits, - @ref BMI_SetValue. - @par C++ Example: - @htmlonly - -
-			std::vector InputVarNames = phreeqc_rm.BMI_GetInputVarNames();
-			int count = phreeqc_rm.BMI_GetInputItemCount();
-			oss << "BMI_SetValue variables:\n";
-			for (size_t i = 0; i < count; i++)
-			{
-				oss << "  " << i << "  " << InputVarNames[i] << "\n";
-				oss << "     Type:        " << phreeqc_rm.BMI_GetVarType(InputVarNames[i]) << "\n";
-				oss << "     Units:       " << phreeqc_rm.BMI_GetVarUnits(InputVarNames[i]) << "\n";
-				oss << "     Total bytes: " << phreeqc_rm.BMI_GetVarNbytes(InputVarNames[i]) << "\n";
-				oss << "     Item bytes:  " << phreeqc_rm.BMI_GetVarItemsize(InputVarNames[i]) << "\n";
-				oss << "     Dim:         " << phreeqc_rm.BMI_GetVarNbytes(InputVarNames[i]) /
-											   phreeqc_rm.BMI_GetVarItemsize(InputVarNames[i]) << "\n";
-			}
-	
-
- @endhtmlonly - @par MPI: - Called by root. - */ - std::vector BMI_GetInputVarNames() { return this->bmi_input_vars; } - - //-------------------------- - - /** - Basic Model Interface method that returns count of output variables that can be retrieved with @ref BMI_GetValue. - @retval Count of output variables that can be retrieved with @ref BMI_GetValue. - - @see - @ref BMI_GetOutputVarNames, - @ref BMI_GetValue, - @ref BMI_GetVarItemsize, - @ref BMI_GetVarNbytes, - @ref BMI_GetVarType, - @ref BMI_GetVarUnits. - @par C++ Example: - @htmlonly - -
-			std::vector OutputVarNames = phreeqc_rm.BMI_GetOutputVarNames();
-			int count = phreeqc_rm.BMI_GetOutputItemCount();
-			oss << "BMI_GetValue variables:\n";
-			for (size_t i = 0; i < count; i++)
-			{
-				oss << "  " << i << "  " << OutputVarNames[i] << "\n";
-				oss << "     Type:        " << phreeqc_rm.BMI_GetVarType(OutputVarNames[i]) << "\n";
-				oss << "     Units:       " << phreeqc_rm.BMI_GetVarUnits(OutputVarNames[i]) << "\n";
-				oss << "     Total bytes: " << phreeqc_rm.BMI_GetVarNbytes(OutputVarNames[i]) << "\n";
-				oss << "     Item bytes:  " << phreeqc_rm.BMI_GetVarItemsize(OutputVarNames[i]) << "\n";
-				oss << "     Dim:         " << phreeqc_rm.BMI_GetVarNbytes(OutputVarNames[i]) /
-											   phreeqc_rm.BMI_GetVarItemsize(OutputVarNames[i]) << "\n";
-			}
-	
-
- @endhtmlonly - @par MPI: - Called by root. - */ - int BMI_GetOutputItemCount() { return (int)this->bmi_output_vars.size(); } - - //-------------------------- - - /** - Basic Model Interface method that returns a list of the variable names that can be retrieved with @ref BMI_GetValue. - @retval A list of the variable names that can be retrieved with @ref BMI_GetValue. - - @see - @ref BMI_GetOutputItemCount, - @ref BMI_GetValue, - @ref BMI_GetVarItemsize, - @ref BMI_GetVarNbytes, - @ref BMI_GetVarType, - @ref BMI_GetVarUnits. - @par C++ Example: - @htmlonly - -
-			std::vector OutputVarNames = phreeqc_rm.BMI_GetOutputVarNames();
-			int count = phreeqc_rm.BMI_GetOutputItemCount();
-			oss << "BMI_GetValue variables:\n";
-			for (size_t i = 0; i < count; i++)
-			{
-				oss << "  " << i << "  " << OutputVarNames[i] << "\n";
-				oss << "     Type:        " << phreeqc_rm.BMI_GetVarType(OutputVarNames[i]) << "\n";
-				oss << "     Units:       " << phreeqc_rm.BMI_GetVarUnits(OutputVarNames[i]) << "\n";
-				oss << "     Total bytes: " << phreeqc_rm.BMI_GetVarNbytes(OutputVarNames[i]) << "\n";
-				oss << "     Item bytes:  " << phreeqc_rm.BMI_GetVarItemsize(OutputVarNames[i]) << "\n";
-				oss << "     Dim:         " << phreeqc_rm.BMI_GetVarNbytes(OutputVarNames[i]) /
-											   phreeqc_rm.BMI_GetVarItemsize(OutputVarNames[i]) << "\n";
-			}
-	
-
- @endhtmlonly - @par MPI: - Called by root. - */ - std::vector BMI_GetOutputVarNames() { return this->bmi_output_vars; }; - - //-------------------------- - - /** - Basic Model Interface method that returns the current simulation time step, in seconds. (Same as @ref GetTimeStep.) - The reaction module does not change the time-step value, so the - returned value is equal to the last time steo set by - @ref BMI_SetValue("TimeStep", time_step) or @ref SetTimeStep. - @retval The current simulation time step, in seconds. - @see - @ref BMI_GetCurrentTime, - @ref BMI_GetEndTime, - @ref BMI_SetValue, - @ref GetTime, - @ref GetTimeStep, - @ref SetTime, - @ref SetTimeStep. - @par C++ Example: - @htmlonly - -
-	std::cout << "Current time step: "
-		 << BMI_GetTimeStep()
-		 << " seconds\n";
-	
-
- @endhtmlonly - @par MPI: - Called by root.. - */ - double BMI_GetTimeStep() { return this->GetTimeStep(); } - - //-------------------------- - - /** - Basic Model Interface method that returns the time units of PhreeqcRM. - All time units are seconds for PhreeqcRM. - @retval Returns the string "seconds". - @see - @ref BMI_GetCurrentTime, - @ref BMI_GetEndTime, - @ref BMI_GetTimeStep, - @ref BMI_SetValue, - @ref GetTime, - @ref GetTimeStep, - @ref SetTime, - @ref SetTimeStep. - @par C++ Example: - @htmlonly - -
-	std::cout << "PhreeqcRM time units are "
-		 << BMI_GetTimeUnits() << ".\n";
-	
-
- @endhtmlonly - @par MPI: - Called by root. - */ - std::string BMI_GetTimeUnits() { return "seconds"; }; - - //-------------------------- - - /** - Basic Model Interface method that retrieves model variables. Only variables in the list - provided by @ref BMI_GetOutputVarNames can be retrieved. The BMI interface to PhreeqcRM is - only partial, and provides only the most basic functions. The native PhreeqcRM methods (those without the the BMI_ - prefix) provide a complete interface, and it is expected that the native methods will be used in preference to the BMI_ - methods. - - Variable names for the first argument - of BMI_GetValue and the equivalent PhreeqcRM method are as follows: - "ComponentCount", @ref GetComponentCount; - "Components", @ref GetComponents; - "Concentrations", @ref GetConcentrations; - "CurrentSelectedOutputUserNumber", @ref GetCurrentSelectedOutputUserNumber; - "Density", @ref GetDensity; - "ErrorString", @ref GetErrorString; - "Gfw", @ref GetGfw; - "GridCellCount", @ref GetGridCellCount; - "Pressure", @ref GetPressure; - "Saturation", @ref GetSaturation; - "SelectedOutput", @ref GetSelectedOutput; - "SelectedOutputColumnCount", @ref GetSelectedOutputColumnCount - "SelectedOutputCount", @ref GetSelectedOutputCount; - "SelectedOutputHeadings, @ref GetSelectedOutputHeadings; - "SelectedOutputRowCount", @ref GetSelectedOutputRowCount; - "Temperature", @ref GetTemperature. - - @see - @ref BMI_GetOutputVarNames, - @ref BMI_GetOutputItemCount, - @ref BMI_GetValue, - @ref BMI_GetVarItemsize, - @ref BMI_GetVarNbytes, - @ref BMI_GetVarType, - @ref BMI_GetVarUnits. - @par C++ Example: - @htmlonly - -
-			int nbytes;
-			phreeqc_rm.BMI_GetVarNbytes("Density", &nbytes);
-			int item_size;
-			phreeqc_rm.BMI_GetVarItemSize("Density", &item_size);
-			int dim = nbytes/item_size;
-			std::vector bmi_density(dim, 0.0);
-			phreeqc_rm.BMI_GetValue("Density", bmi_density.data());
-			// equivalent to:
-			// std::vector rm_density;
-			// phreeqc_rm.GetDensity(rm_density);
-
-			int ncomps;
-			phreeqc_rm.BMI_GetValue("ComponentCount", &ncomps);
-			int nbytes = phreeqc_rm.BMI_GetVarNbytes("Components");
-			std::string all_comps(nbytes, ' ');
-			phreeqc_rm.BMI_GetValue("Components", all_comps.data());
-			int string_size = phreeqc_rm.BMI_GetVarItemsize("Components");
-			std::vector bmi_comps;
-			for (size_t i = 0; i < ncomps; i++)
-			{
-				std::string bmi_comp = all_comps.substr((i * string_size), string_size);
-				size_t end = bmi_comp.find_last_not_of(' ');
-				bmi_comp = (end == std::string::npos) ? "" : bmi_comp.substr(0, end + 1);
-				bmi_comps.push_back(bmi_comp);
-			}
-			// equivalent to:
-			// std::vector< std::string > components = phreeqc_rm.GetComponents();
-	
-
- @endhtmlonly - @par MPI: - Called by root, workers must be in the loop of @ref MpiWorker. - */ - void BMI_GetValue(std::string name, void* dest); - - //-------------------------- - - /** - Basic Model Interface method that retrieves size of an - individual item that can be set or retrived. - Sizes may be sizeof(int), sizeof(double), - or a character length for string variables. Only variables in the list - provided by @ref BMI_GetInputVarNames can be set. - See @ref BMI_SetValue for the list of input variable names. - Only variables in the list - provided by @ref BMI_GetOutputVarNames can be retrieved. - See @ref BMI_GetValue for the list of output variable names. - - - @see - @ref BMI_GetInputVarNames, - @ref BMI_GetInputItemCount, - @ref BMI_GetOutputVarNames, - @ref BMI_GetOutputItemCount, - @ref BMI_GetValue, - @ref BMI_GetVarNbytes, - @ref BMI_SetValue. - @par C++ Example: - @htmlonly - -
-			int nbytes;
-			phreeqc_rm.BMI_GetVarNbytes("Density", &nbytes);
-			int item_size;
-			phreeqc_rm.BMI_GetVarItemSize("Density", &item_size);
-			int dim = nbytes/item_size;
-			std::vector bmi_density(dim, 0.0);
-			phreeqc_rm.BMI_GetValue("Density", bmi_density.data());
-			// equivalent to:
-			// std::vector rm_density;
-			// phreeqc_rm.GetDensity(rm_density);
-
-			int ncomps;
-			phreeqc_rm.BMI_GetValue("ComponentCount", &ncomps);
-			int nbytes = phreeqc_rm.BMI_GetVarNbytes("Components");
-			std::string all_comps(nbytes, ' ');
-			phreeqc_rm.BMI_GetValue("Components", all_comps.data());
-			int string_size = phreeqc_rm.BMI_GetVarItemsize("Components");
-			std::vector bmi_comps;
-			for (size_t i = 0; i < ncomps; i++)
-			{
-				std::string bmi_comp = all_comps.substr((i * string_size), string_size);
-				size_t end = bmi_comp.find_last_not_of(' ');
-				bmi_comp = (end == std::string::npos) ? "" : bmi_comp.substr(0, end + 1);
-				bmi_comps.push_back(bmi_comp);
-			}
-			// equivalent to:
-			// std::vector< std::string > components = phreeqc_rm.GetComponents();
-	
-
- @endhtmlonly - @par MPI: - Called by root. - */ - int BMI_GetVarItemsize(std::string name); - - //-------------------------- - - /** - Basic Model Interface method that retrieves the total number of bytes that are set for a variable with - @ref BMI_SetValue or retrieved for a variable with @ref BMI_GetValue. - Only variables in the list - provided by @ref BMI_GetInputVarNames can be set. - See @ref BMI_SetValue for the list of input variable names. - Only variables in the list - provided by @ref BMI_GetOutputVarNames can be retrieved. - See @ref BMI_GetValue for the list of output variable names. - - - @see - @ref BMI_GetInputVarNames, - @ref BMI_GetInputItemCount, - @ref BMI_GetOutputVarNames, - @ref BMI_GetOutputItemCount, - @ref BMI_GetValue, - @ref BMI_GetVarItemsize, - @ref BMI_SetValue. - @par C++ Example: - @htmlonly - -
-			int nbytes;
-			phreeqc_rm.BMI_GetVarNbytes("Density", &nbytes);
-			int item_size;
-			phreeqc_rm.BMI_GetVarItemSize("Density", &item_size);
-			int dim = nbytes/item_size;
-			std::vector bmi_density(dim, 0.0);
-			phreeqc_rm.BMI_GetValue("Density", bmi_density.data());
-			// equivalent to:
-			// std::vector rm_density;
-			// phreeqc_rm.GetDensity(rm_density);
-
-			int ncomps;
-			phreeqc_rm.BMI_GetValue("ComponentCount", &ncomps);
-			int nbytes = phreeqc_rm.BMI_GetVarNbytes("Components");
-			std::string all_comps(nbytes, ' ');
-			phreeqc_rm.BMI_GetValue("Components", all_comps.data());
-			int string_size = phreeqc_rm.BMI_GetVarItemsize("Components");
-			std::vector bmi_comps;
-			for (size_t i = 0; i < ncomps; i++)
-			{
-				std::string bmi_comp = all_comps.substr((i * string_size), string_size);
-				size_t end = bmi_comp.find_last_not_of(' ');
-				bmi_comp = (end == std::string::npos) ? "" : bmi_comp.substr(0, end + 1);
-				bmi_comps.push_back(bmi_comp);
-			}
-			// equivalent to:
-			// std::vector< std::string > components = phreeqc_rm.GetComponents();
-		}
-	
-
- @endhtmlonly - @par MPI: - Called by root. - */ - int BMI_GetVarNbytes(std::string name); - - //-------------------------- - - /** - Basic Model Interface method that retrieves the type of a variable that can be set with - @ref BMI_SetValue or retrieved with @ref BMI_GetValue. Types are "int", "double", or "string". - Only variables in the list - provided by @ref BMI_GetInputVarNames can be set. - See @ref BMI_SetValue for the list of input variable names. - Only variables in the list - provided by @ref BMI_GetOutputVarNames can be retrieved. - See @ref BMI_GetValue for the list of output variable names. - - - @see - @ref BMI_GetInputVarNames, - @ref BMI_GetInputItemCount, - @ref BMI_GetOutputVarNames, - @ref BMI_GetOutputItemCount, - @ref BMI_GetVarUnits. - @par C++ Example: - @htmlonly - -
-			std::vector OutputVarNames = phreeqc_rm.BMI_GetOutputVarNames();
-			int count = phreeqc_rm.BMI_GetOutputItemCount();
-			oss << "BMI_GetValue variables:\n";
-			for (size_t i = 0; i < count; i++)
-			{
-				oss << "  " << i << "  " << OutputVarNames[i] << "\n";
-				oss << "     Type:        " << phreeqc_rm.BMI_GetVarType(OutputVarNames[i]) << "\n";
-				oss << "     Units:       " << phreeqc_rm.BMI_GetVarUnits(OutputVarNames[i]) << "\n";
-				oss << "     Total bytes: " << phreeqc_rm.BMI_GetVarNbytes(OutputVarNames[i]) << "\n";
-				oss << "     Item bytes:  " << phreeqc_rm.BMI_GetVarItemsize(OutputVarNames[i]) << "\n";
-				oss << "     Dim:         " << phreeqc_rm.BMI_GetVarNbytes(OutputVarNames[i]) /
-											   phreeqc_rm.BMI_GetVarItemsize(OutputVarNames[i]) << "\n";
-			}
-	
-
- @endhtmlonly - @par MPI: - Called by root. - */ - std::string BMI_GetVarType(std::string name); - - //-------------------------- - - /** - Basic Model Interface method that retrieves the units of a variable that can be set with - @ref BMI_SetValue or retrieved with @ref BMI_GetValue. - Only variables in the list - provided by @ref BMI_GetInputVarNames can be set. - See @ref BMI_SetValue for the list of input variable names. - Only variables in the list - provided by @ref BMI_GetOutputVarNames can be retrieved. - See @ref BMI_GetValue for the list of output variable names. - - - @see - @ref BMI_GetInputVarNames, - @ref BMI_GetInputItemCount, - @ref BMI_GetOutputVarNames, - @ref BMI_GetOutputItemCount, - @ref BMI_GetVarType. - @par C++ Example: - @htmlonly - -
-			std::vector OutputVarNames = phreeqc_rm.BMI_GetOutputVarNames();
-			int count = phreeqc_rm.BMI_GetOutputItemCount();
-			oss << "BMI_GetValue variables:\n";
-			for (size_t i = 0; i < count; i++)
-			{
-				oss << "  " << i << "  " << OutputVarNames[i] << "\n";
-				oss << "     Type:        " << phreeqc_rm.BMI_GetVarType(OutputVarNames[i]) << "\n";
-				oss << "     Units:       " << phreeqc_rm.BMI_GetVarUnits(OutputVarNames[i]) << "\n";
-				oss << "     Total bytes: " << phreeqc_rm.BMI_GetVarNbytes(OutputVarNames[i]) << "\n";
-				oss << "     Item bytes:  " << phreeqc_rm.BMI_GetVarItemsize(OutputVarNames[i]) << "\n";
-				oss << "     Dim:         " << phreeqc_rm.BMI_GetVarNbytes(OutputVarNames[i]) /
-											   phreeqc_rm.BMI_GetVarItemsize(OutputVarNames[i]) << "\n";
-			}
-	
-
- @endhtmlonly - @par MPI: - Called by root. - */ - std::string BMI_GetVarUnits(std::string name); - - //-------------------------- -#ifdef USE_YAML - /** - Basic Model Interface method that can be used to initialize a PhreeqcRM instance. This method is equivalent to - @ref InitializeYAML. A YAML file can be used in initialization. The file contains a YAML map of PhreeqcRM methods - and the arguments corresponding to the method. For example, - @htmlonly - -
-	LoadDatabase: phreeqc.dat
-	RunFile:
-	  workers: true
-	  initial_phreeqc: true
-	  utility: true
-	  chemistry_name: advect.pqi
-	
-
- @endhtmlonly - - BMI_Initialize will read the YAML file and execute the specified methods with the specified arguments. Using YAML - terminology, the argument(s) for a method may be a scalar, a sequence, or a map, depending if the argument is - a single item, a single vector, or there are multiple arguments. In the case of a map, the name associated - with each argument (for example "chemistry_name" above) is arbitrary. The names of the map keys for map - arguments are not used in parsing the YAML file; only the order of the arguments is important. - - The PhreeqcRM methods that can be specified in a YAML file include: - @htmlonly - -
-	CloseFiles(void);
-	CreateMapping(std::vector< int >& grid2chem);
-	DumpModule();
-	FindComponents();
-	InitialPhreeqc2Module(std::vector< int > initial_conditions1);
-	InitialPhreeqc2Module(std::vector< int > initial_conditions1, std::vector< int > initial_conditions2, std::vector< double > fraction1);
-	InitialPhreeqcCell2Module(int n, std::vector< int > cell_numbers);
-	LoadDatabase(std::string database);
-	OpenFiles(void);
-	OutputMessage(std::string str);
-	RunCells(void);
-	RunFile(bool workers, bool initial_phreeqc, bool utility, std::string chemistry_name);
-	RunString(bool workers, bool initial_phreeqc, bool utility, std::string input_string);
-	ScreenMessage(std::string str);
-	SetComponentH2O(bool tf);
-	SetConcentrations(std::vector< double > c);
-	SetCurrentSelectedOutputUserNumber(int n_user);
-	SetDensity(std::vector< double > density);
-	SetDumpFileName(std::string dump_name);
-	SetErrorHandlerMode(int mode);
-	SetErrorOn(bool tf);
-	SetFilePrefix(std::string prefix);
-	SetGasCompMoles(std::vector< double > gas_moles);
-	SetGasPhaseVolume(std::vector< double > gas_volume);
-	SetPartitionUZSolids(bool tf);
-	SetPorosity(std::vector< double > por);
-	SetPressure(std::vector< double > p);
-	SetPrintChemistryMask(std::vector< int > cell_mask);
-	SetPrintChemistryOn(bool workers, bool initial_phreeqc, bool utility);
-	SetRebalanceByCell(bool tf);
-	SetRebalanceFraction(double f);
-	SetRepresentativeVolume(std::vector< double > rv);
-	SetSaturation(std::vector< double > sat);
-	SetScreenOn(bool tf);
-	SetSelectedOutputOn(bool tf);
-	SetSpeciesSaveOn(bool save_on);
-	SetTemperature(std::vector< double > t);
-	SetTime(double time);
-	SetTimeConversion(double conv_factor);
-	SetTimeStep(double time_step);
-	SetUnitsExchange(int option);
-	SetUnitsGasPhase(int option);
-	SetUnitsKinetics(int option);
-	SetUnitsPPassemblage(int option);
-	SetUnitsSolution(int option);
-	SetUnitsSSassemblage(int option);
-	SetUnitsSurface(int option);
-	SpeciesConcentrations2Module(std::vector< double > species_conc);
-	StateSave(int istate);
-	StateApply(int istate);
-	StateDelete(int istate);
-	UseSolutionDensityVolume(bool tf);
-	WarningMessage(std::string warnstr);
-	
-
- @endhtmlonly - @see - @ref BMI_Update. - @par C++ Example: - @htmlonly - -
-			PhreeqcRM phreeqc_rm(nxyz, nthreads);
-			phreeqc_rm.BMI_Initialize("myfile.yaml");
-			int ncomps;
-			phreeqc_rm.BMI_GetValue("ComponentCount", &ncomps);
-			int ngrid;
-			phreeqc_rm.BMI_GetValue("GridCellCount", ngrid);
-			std::vector c(ngrid*ncomps, 0.0);
-			phreeqc_rm.BMI_GetValue("Concentrations", c.data());
-			phreeqc_rm.BMI_SetValue("TimeStep", 86400);
-			for(double time = 0; time < 864000; time+=86400)
-			{
-				// Take a transport time step here and update the vector c.
-				phreeqc_rm.BMI_SetValue("Time", time);
-				phreeqc_rm.BMI_SetValue("Concentrations", c.data());
-				phreeqc_rm.BMI_Update();
-				phreeqc_rm.BMI_GetValue("Concentrations", c.data());
-			}
-	
-
- @endhtmlonly - @par MPI: - Called by root, workers must be in the loop of @ref MpiWorker. - */ - void BMI_Initialize(std::string config_file) { IRM_RESULT status = InitializeYAML(config_file); }; -#endif - //-------------------------- - - /** - Basic Model Interface method that sets model variables. Only variables in the list - provided by @ref BMI_GetInputVarNames can be set. The BMI interface to PhreeqcRM is - only partial, and provides only the most basic functions. The native PhreeqcRM methods (those without the the BMI_ - prefix) provide a complete interface, and it is expected that the native methods will be used in preference to the BMI_ - methods. - - Variable names for the first argument - of BMI_SetValue and the equivalent PhreeqcRM method are as follows: - "Concentrations", @ref SetConcentrations; - "Density", @ref SetDensity; - "NthSelectedOutput", @ref SetNthSelectedOutput; - "Porosity", @ref SetPorosity; - "Pressure", @ref SetPressure; - "Saturation", @ref SetSaturation; - "SelectedOutputOn", @ref SetSelectedOutputOn; - "Temperature", @ref SetTemperature; - "Time", @ref SetTime; - "TimeStep", @ref SetTimeStep. - - @see - @ref BMI_GetInputVarNames, - @ref BMI_GetInputItemCount, - @ref BMI_GetVarItemsize, - @ref BMI_GetVarNbytes, - @ref BMI_GetVarType, - @ref BMI_GetVarUnits, - @ref BMI_SetValue. - @par C++ Example: - @htmlonly - -
-			int nbytes;
-			phreeqc_rm.BMI_GetVarNbytes("Temperature", &nbytes);
-			int item_size;
-			phreeqc_rm.BMI_GetVarItemSize("Temperature", &item_size);
-			int dim = nbytes/item_size;
-			std::vector bmi_temperature(dim, 28.0);
-			phreeqc_rm.BMI_SetValue("Temperature", bmi_temperature.data());
-			// equivalent to:
-			// std::vector rm_temperature(dim, 28.0);
-			// phreeqc_rm.SetTemperature(rm_temperature);
-	
-
- @endhtmlonly - @par MPI: - Called by root, workers must be in the loop of @ref MpiWorker. - */ - void BMI_SetValue(std::string name, void* src); - - //-------------------------- - /** - Basic Model Interface method that runs PhreeqcRM for one time step. This method is equivalent to - @ref RunCells. PhreeqcRM will equilibrate the solutions with all equilibrium reactants (EQUILIBRIUM_PHASES, - EXCHANGE, GAS_PHASE, SOLID_SOLUTIONS, and SURFACE) and - integrate KINETICS reactions for the specified time step (@ref SetTimeStep). - @see - @ref BMI_Initialize. - @par C++ Example: - @htmlonly - -
-			PhreeqcRM phreeqc_rm(nxyz, nthreads);
-			phreeqc_rm.BMI_Initialize("myfile.yaml");
-			int ncomps;
-			phreeqc_rm.BMI_GetValue("ComponentCount", &ncomps);
-			int ngrid;
-			phreeqc_rm.BMI_GetValue("GridCellCount", ngrid);
-			std::vector c(ngrid*ncomps, 0.0);
-			phreeqc_rm.BMI_GetValue("Concentrations", c.data());
-			phreeqc_rm.BMI_SetValue("TimeStep", 86400);
-			for(double time = 0; time < 864000; time+=86400)
-			{
-				// Take a transport time step here and update the vector c.
-				phreeqc_rm.BMI_SetValue("Time", time);
-				phreeqc_rm.BMI_SetValue("Concentrations", c.data());
-				phreeqc_rm.BMI_Update();
-				phreeqc_rm.BMI_GetValue("Concentrations", c.data());
-			}
-	
-
- @endhtmlonly - @par MPI: - Called by root, workers must be in the loop of @ref MpiWorker. - */ - void BMI_Update(void) { this->RunCells(); }; -#ifdef NOT_IMPLEMENTED - void BMI_UpdateUntil(double time) - { - //throw LetItThrow("Not implemented"); - ErrorMessage("Not implemented"); - throw PhreeqcRMStop(); - } - int BMI_GetVarGrid(std::string name) - { - //throw LetItThrow("Not applicable"); - ErrorMessage("Not applicable"); - throw PhreeqcRMStop(); - }; - std::string BMI_GetVarLocation(std::string name) - { - //throw LetItThrow("Not applicable"); - ErrorMessage("Not applicable"); - throw PhreeqcRMStop(); - }; - double BMI_GetStartTime() - { - //throw LetItThrow("Not implemented"); - ErrorMessage("Not implemented"); - throw PhreeqcRMStop(); - }; - void* BMI_GetValuePtr(std::string name) - { - //throw LetItThrow("Not implemented"); - ErrorMessage("Not implemented"); - throw PhreeqcRMStop(); - } - void BMI_GetValueAtIndices(std::string name, void* dest, int* inds, int count) - { - //throw LetItThrow("Not implemented"); - ErrorMessage("Not implemented"); - throw PhreeqcRMStop(); - }; - void BMI_SetValueAtIndices(std::string name, int* inds, int len, void* src) - { - //throw LetItThrow("Not implemented"); - ErrorMessage("Not implemented"); - throw PhreeqcRMStop(); - }; - int BMI_GetGridRank(const int grid) - { - //throw LetItThrow("Not applicable"); - ErrorMessage("Not applicable"); - throw PhreeqcRMStop(); - }; - int BMI_GetGridSize(const int grid) - { - //throw LetItThrow("Not applicable"); - ErrorMessage("Not applicable"); - throw PhreeqcRMStop(); - }; - std::string BMI_GetGridType(const int grid) - { - //throw LetItThrow("Not applicable"); - ErrorMessage("Not applicable"); - throw PhreeqcRMStop(); - }; - void BMI_GetGridShape(const int grid, int* shape) - { - //throw LetItThrow("Not applicable"); - ErrorMessage("Not applicable"); - throw PhreeqcRMStop(); - }; - void BMI_GetGridSpacing(const int grid, double* spacing) - { - //throw LetItThrow("Not applicable"); - ErrorMessage("Not applicable"); - throw PhreeqcRMStop(); - }; - void GetGridOrigin(const int grid, double* origin) - { - //throw LetItThrow("Not applicable"); - ErrorMessage("Not applicable"); - throw PhreeqcRMStop(); - }; - void BMI_GetGridX(const int grid, double* x) - { - //throw LetItThrow("Not applicable"); - ErrorMessage("Not applicable"); - throw PhreeqcRMStop(); - }; - void BMI_GetGridY(const int grid, double* y) - { - //throw LetItThrow("Not applicable"); - ErrorMessage("Not applicable"); - throw PhreeqcRMStop(); - }; - void BMI_GetGridZ(const int grid, double* z) - { - //throw LetItThrow("Not applicable"); - ErrorMessage("Not applicable"); - throw PhreeqcRMStop(); - }; - - int BMI_GetGridNodeCount(const int grid) - { - //throw LetItThrow("Not applicable"); - ErrorMessage("Not applicable"); - throw PhreeqcRMStop(); - }; - int BMI_GetGridEdgeCount(const int grid) - { - //throw LetItThrow("Not applicable"); - ErrorMessage("Not applicable"); - throw PhreeqcRMStop(); - }; - int BMI_GetGridFaceCount(const int grid) - { - //throw LetItThrow("Not applicable"); - ErrorMessage("Not applicable"); - throw PhreeqcRMStop(); - }; - void BMI_GetGridEdgeNodes(const int grid, int* edge_nodes) - { - //throw LetItThrow("Not applicable"); - ErrorMessage("Not applicable"); - throw PhreeqcRMStop(); - }; - void BMI_GetGridFaceEdges(const int grid, int* face_edges) - { - //throw LetItThrow("Not applicable"); - ErrorMessage("Not applicable"); - throw PhreeqcRMStop(); - }; - void BMI_GetGridFaceNodes(const int grid, int* face_nodes) - { - //throw LetItThrow("Not applicable"); - ErrorMessage("Not applicable"); - throw PhreeqcRMStop(); - }; - void BMI_GetGridNodesPerFace(const int grid, int* nodes_per_face) - { - //throw LetItThrow("Not applicable"); - ErrorMessage("Not applicable"); - throw PhreeqcRMStop(); - }; -#endif -private: - void BMI_MakeVarMap(); -// End BMI data and methods public: // Utilities static std::string Char2TrimString(const char * str, size_t l = 0); @@ -5935,25 +5120,25 @@ Called by root. IRM_RESULT CellInitialize( int i, int n_user_new, - int *initial_conditions1, - int *initial_conditions2, + const int *initial_conditions1, + const int *initial_conditions2, double *fraction1, std::set &error_set); IRM_RESULT CheckCells(); int CheckSelectedOutput(); //void Collapse2Nchem(double *d_in, double *d_out); //void Collapse2Nchem(int *i_in, int *i_out); - IPhreeqc * Concentrations2UtilityH2O(std::vector &c_in, - std::vector &t_in, std::vector &p_in); - IPhreeqc * Concentrations2UtilityNoH2O(std::vector &c_in, - std::vector &t_in, std::vector &p_in); - void Concentrations2Solutions(int n, std::vector &c); - void Concentrations2SolutionsH2O(int n, std::vector &c); - void Concentrations2SolutionsNoH2O(int n, std::vector &c); - void cxxSolution2concentration(cxxSolution * cxxsoln_ptr, std::vector & d, double v, double dens); - void cxxSolution2concentrationH2O(cxxSolution * cxxsoln_ptr, std::vector & d, double v, double dens); - void cxxSolution2concentrationNoH2O(cxxSolution * cxxsoln_ptr, std::vector & d, double v, double dens); - void GatherNchem(std::vector &source, std::vector &destination); + IPhreeqc * Concentrations2UtilityH2O(std::vector< double > &c_in, + std::vector< double > &t_in, std::vector< double > &p_in); + IPhreeqc * Concentrations2UtilityNoH2O(std::vector< double > &c_in, + std::vector< double > &t_in, std::vector< double > &p_in); + void Concentrations2Solutions(int n, std::vector< double > &c); + void Concentrations2SolutionsH2O(int n, std::vector< double > &c); + void Concentrations2SolutionsNoH2O(int n, std::vector< double > &c); + void cxxSolution2concentration(cxxSolution * cxxsoln_ptr, std::vector< double > & d, double v, double dens); + void cxxSolution2concentrationH2O(cxxSolution * cxxsoln_ptr, std::vector< double > & d, double v, double dens); + void cxxSolution2concentrationNoH2O(cxxSolution * cxxsoln_ptr, std::vector< double > & d, double v, double dens); + void GatherNchem(std::vector< double > &source, std::vector< double > &destination); cxxStorageBin & Get_phreeqc_bin(void) {return *this->phreeqc_bin;} IRM_RESULT HandleErrorsInternal(std::vector< int > & r); void PartitionUZ(int n, int iphrq, int ihst, double new_frac); @@ -5966,8 +5151,8 @@ Called by root. void Scale_solids(int n, int iphrq, double frac); void ScatterNchem(double *d_array); void ScatterNchem(int *i_array); - void ScatterNchem(std::vector &source, std::vector &destination); - void ScatterNchem(std::vector &source, std::vector &destination); + void ScatterNchem(std::vector< double > &source, std::vector< double > &destination); + void ScatterNchem(std::vector< int > &source, std::vector< int > &destination); IRM_RESULT SetChemistryFileName(const char * prefix = NULL); IRM_RESULT SetDatabaseFileName(const char * db = NULL); void SetEndCells(void); @@ -5977,8 +5162,10 @@ Called by root. IRM_RESULT TransferCellsUZ(std::ostringstream &raw_stream, int old, int nnew); private: - //IRM_RESULT SetGeneric(std::vector &destination, int newSize, const std::vector &origin, int mpiMethod, const std::string &name, const double newValue = 0.0); - IRM_RESULT SetGeneric(const std::vector &source, std::vector &destination_root, std::vector &destination_worker, int mpiMethod, const std::string &name); + //IRM_RESULT SetGeneric(std::vector< double > &destination, int newSize, const std::vector< double > &origin, int mpiMethod, const std::string &name, const double newValue = 0.0); + IRM_RESULT SetGeneric(const std::vector< double > &source, std::vector< double > &destination_root, std::vector< double > &destination_worker, int mpiMethod, const std::string &name); +public: + protected: #if defined(_MSC_VER) @@ -6006,22 +5193,24 @@ Called by root. double time_conversion; // time conversion factor, multiply to convert to preferred time unit for output std::vector old_saturation_root; // saturation fraction from previous step std::vector old_saturation_worker; - std::vector saturation_root; // nxyz saturation fraction - std::vector saturation_worker; // nchem on workers saturation fraction - std::vector pressure_root; // nxyz on root current pressure - std::vector pressure_worker; // nchem on workers current pressure - std::vector rv_root; // nxyz on root representative volume - std::vector rv_worker; // nchem on workers representative volume - std::vector porosity_root; // nxyz porosity - std::vector porosity_worker; // nchem on workers porosity - std::vector tempc_root; // nxyz on root temperature Celsius - std::vector tempc_worker; // nchem on workers temperature Celsius - std::vector density_root; // nxyz density - std::vector density_worker; // nchem on workers density - std::vector solution_volume_root; // nxyz on root solution volume - std::vector solution_volume_worker; // nchem on workers solution_volume - std::vector print_chem_mask_root; // nxyz print flags for output file - std::vector print_chem_mask_worker; // nchem print flags for output file + std::vector< double > saturation_root; // nxyz saturation fraction + std::vector< double > saturation_worker; // nchem on workers saturation fraction + std::vector< double > pressure_root; // nxyz on root current pressure + std::vector< double > pressure_worker; // nchem on workers current pressure + std::vector< double > rv_root; // nxyz on root representative volume + std::vector< double > rv_worker; // nchem on workers representative volume + std::vector< double > porosity_root; // nxyz porosity + std::vector< double > porosity_worker; // nchem on workers porosity + std::vector< double > tempc_root; // nxyz on root temperature Celsius + std::vector< double > tempc_worker; // nchem on workers temperature Celsius + std::vector< double > density_root; // nxyz density + std::vector< double > density_worker; // nchem on workers density + std::vector< double > viscosity_root; // nxyz viscosity + std::vector< double > viscosity_worker; // nchem on workers viscosity + std::vector< double > solution_volume_root; // nxyz on root solution volume + std::vector< double > solution_volume_worker; // nchem on workers solution_volume + std::vector< int > print_chem_mask_root; // nxyz print flags for output file + std::vector< int > print_chem_mask_worker; // nchem print flags for output file bool rebalance_by_cell; // rebalance method 0 std, 1 by_cell double rebalance_fraction; // parameter for rebalancing process load for parallel int units_Solution; // 1 mg/L, 2 mol/L, 3 kg/kgs @@ -6036,7 +5225,7 @@ Called by root. bool use_solution_density_volume; // print flags - std::vector print_chemistry_on; // print flag for chemistry output file + std::vector< bool > print_chemistry_on; // print flag for chemistry output file bool selected_output_on; // create selected output int error_count; @@ -6048,8 +5237,8 @@ Called by root. // threading int nthreads; std::vector workers; - std::vector start_cell; - std::vector end_cell; + std::vector< int > start_cell; + std::vector< int > end_cell; PHRQ_io *phreeqcrm_io; bool delete_phreeqcrm_io; @@ -6068,7 +5257,7 @@ Called by root. std::vector species_d_25; std::vector species_stoichiometry; std::map s_num2rm_species_num; - std::vector standard_task_vector; // root only + std::vector< double > standard_task_vector; // root only // reactant lists std::vector ExchangeSpeciesNamesList; diff --git a/src/PhreeqcRM.i b/src/PhreeqcRM.i new file mode 100644 index 000000000..709926835 --- /dev/null +++ b/src/PhreeqcRM.i @@ -0,0 +1,49 @@ +// %module(directors="1") phreeqcrm +%module phreeqcrm + +%{ +#define SWIG_FILE_WITH_INIT +#include "BMI_Var.h" +#include "IrmResult.h" +#include "PhreeqcRM.h" +#include "bmi.hxx" +#include "BMIPhreeqcRM.h" +%} + +%ignore BMIVariant; +%ignore bmi::Bmi; +%ignore BMIPhreeqcRM::GetValue(std::string const,bool *); +%ignore BMIPhreeqcRM::GetValue(std::string const,double *); +%ignore BMIPhreeqcRM::GetValue(std::string const,int *); +%ignore BMIPhreeqcRM::SetValue(std::string,std::vector< int,std::allocator< int > >); +%ignore BMIPhreeqcRM::SetValue(std::string,std::vector< std::string,std::allocator< std::string > >); + +#if 0 +%include "numpy.i" +%init %{ +import_array(); +%} +#endif + +%include "std_string.i" +%include "std_vector.i" +%template(DoubleVector) std::vector; +%template(IntVector) std::vector; +%template(StringVector) std::vector; + +#if defined(SWIGPYTHON) +%include "swig/python/PhreeqcRM_docstrings.i" +#if defined(USE_YAML) +%include "swig/python/YAMLPhreeqcRM.i" +#endif +#endif + +// Adding (%include "IPhreeqcPhast.h") forces inclusion of the +// following classes cxxSolution, cxxExchange, cxxGasPhase, +// cxxKinetics, cxxPPassemblage, cxxSSassemblage, cxxSurface +// cxxMix, cxxReaction, cxxTemperature, cxxPressure +%include "BMI_Var.h" +%include "IrmResult.h" +%include "PhreeqcRM.h" +#include "bmi.hxx" +%include "BMIPhreeqcRM.h" diff --git a/src/RMVARS.h b/src/RMVARS.h new file mode 100644 index 000000000..4f69ab8e9 --- /dev/null +++ b/src/RMVARS.h @@ -0,0 +1,31 @@ +#if !defined(RMVARS_H) +#define RMVARS_H +enum class RMVARS { + ComponentCount, + Components, + Concentrations, + Density, + ErrorString, + FilePrefix, + Gfw, + GridCellCount, + InputVarNames, + NthSelectedOutput, + OutputVarNames, + Saturation, + SelectedOutput, + SelectedOutputColumnCount, + SelectedOutputCount, + SelectedOutputHeadings, + SelectedOutputRowCount, + SolutionVolume, + Time, + TimeStep, + CurrentSelectedOutputUserNumber, + Porosity, + Pressure, + SelectedOutputOn, + Temperature, + NotFound +}; +#endif \ No newline at end of file diff --git a/src/RM_interface.F90 b/src/RM_interface.F90 index e29310197..4aba67de9 100644 --- a/src/RM_interface.F90 +++ b/src/RM_interface.F90 @@ -1,12 +1,12 @@ -!*MODULE PhreeqcRM PHREEQC Reaction Module for Transport Codes -!> @brief Fortran Documentation for the geochemical reaction module PhreeqcRM. -!> @par "" -!> "USE PhreeqcRM" is included in Fortran source code to define the PhreeqcRM functions. -!> For Windows, define the module by including the file RM_interface.F90 in your project. -!> For Linux, configure, compile, and install the PhreeqcRM library and module file. -!> You will need installed include directory (-I) added to the project) to reference the module file. -!> You will need to link to the library to produce the executable for your code. -!> + !*MODULE PhreeqcRM PHREEQC Reaction Module for Transport Codes + !> @brief Fortran Documentation for the geochemical reaction module PhreeqcRM. + !> @par "" + !> "USE PhreeqcRM" is included in Fortran source code to define the PhreeqcRM functions. + !> For Windows, define the module by including the file RM_interface.F90 in your project. + !> For Linux, configure, compile, and install the PhreeqcRM library and module file. + !> You will need installed include directory (-I) added to the project) to reference the module file. + !> You will need to link to the library to produce the executable for your code. + !> MODULE PhreeqcRM IMPLICIT NONE !!!SAVE @@ -30,6 +30,10 @@ MODULE PhreeqcRM PRIVATE :: Chk_SetGasPhaseVolume PRIVATE :: Chk_GetSpeciesLog10Molalities PRIVATE :: Chk_GetGfw + PRIVATE :: Chk_SetPorosity + PRIVATE :: Chk_SetPressure + PRIVATE :: Chk_GetPorosity + PRIVATE :: Chk_GetPressure PRIVATE :: Chk_GetSaturation PRIVATE :: Chk_GetSelectedOutput PRIVATE :: Chk_GetSolutionVolume @@ -44,8 +48,6 @@ MODULE PhreeqcRM PRIVATE :: Chk_InitialPhreeqc2SpeciesConcentrations PRIVATE :: Chk_SetConcentrations PRIVATE :: Chk_SetDensity - PRIVATE :: Chk_SetPorosity - PRIVATE :: Chk_SetPressure PRIVATE :: Chk_SetPrintChemistryMask PRIVATE :: Chk_SetSaturation PRIVATE :: Chk_SetTemperature @@ -55,274 +57,322 @@ MODULE PhreeqcRM PRIVATE :: Chk_Integer1D PRIVATE :: Chk_Integer2D PRIVATE :: RMF_debug -#ifdef SKIP - PRIVATE :: RM_SETCONCENTRATIONS1D -#endif - + + CONTAINS - -!> Abort the program. -!> @a irm_result will be interpreted as -!> an IRM_RESULT value and decoded; @a err_str will be printed; and the reaction module -!> will be destroyed. If using MPI, an MPI_Abort message will be sent before the reaction -!> module is destroyed. If the @a id is an invalid instance, RM_Abort will return a value of -!> IRM_BADINSTANCE, otherwise the program will exit with a return code of 4. -!> @param id The instance id returned from @ref RM_Create. -!> @param irm_result Integer treated as an IRM_RESULT return code. -!> @param err_str String to be printed as an error message. -!> @retval IRM_RESULT Program will exit before returning unless @a id is an invalid reaction module id. -!> @see -!> @ref RM_Destroy, -!> @ref RM_ErrorMessage. +#ifdef USE_YAML +!> @a GetGridCellCountYAML will read a YAML file and extract the value +!> of GridCellCount, which can be used to construct a PhreeqcRM +!> instance. @ref RM_Create requires a +!> value for the number of cells. If a GUI or preprocessor is +!> used to write a YAML file to initialize PhreeqcRM, the number +!> of cells can be written to the YAML file and extracted with +!> this method. +!> @param config_file String containing the YAML file name. +!> @retval Number of grid cells specified in the YAML file; returns +!> zero if GridCellCount is not defined. +!> @see @ref bmif_initialize, @ref RM_Create, and @ref RM_InitializeYAML. !> @par Fortran Example: !> @htmlonly !> !>
-!> iphreeqc_id = RM_Concentrations2Utility(id, c_well, 1, tc, p_atm)
-!> string = "SELECTED_OUTPUT 5; -pH;RUN_CELLS; -cells 1"
-!> status = RunString(iphreeqc_id, string)
-!> if (status .ne. 0) status = RM_Abort(id, status, "IPhreeqc RunString failed")
+!> 	integer nthreads = 0
+!>  integer nxyz
+!> 	nxyz = GetGridCellCountYAML("myfile.yaml");
+!> 	status = RM_Create(nxyz, nthreads);
+!> 	status = bmif_initialize("myfile.yaml");
 !> 
!>
!> @endhtmlonly -!> @par MPI: -!> Called by root or workers. - -INTEGER FUNCTION RM_Abort(id, irm_result, err_str) +!> @par Sequence: +!> Called before RM_Create. + INTEGER FUNCTION GetGridCellCountYAML(config_file) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION RMF_GetGridCellCountYAML(config_file) & + BIND(C, NAME='RMF_GetGridCellCountYAML') + USE ISO_C_BINDING + IMPLICIT NONE + CHARACTER(KIND=C_CHAR), INTENT(in) :: config_file(*) + END FUNCTION RMF_GetGridCellCountYAML + END INTERFACE + CHARACTER(len=*), INTENT(in) :: config_file + GetGridCellCountYAML = RMF_GetGridCellCountYAML(trim(config_file)//C_NULL_CHAR) + return + END FUNCTION GetGridCellCountYAML +#endif + !> Abort the program. + !> @a irm_result will be interpreted as + !> an IRM_RESULT value and decoded; @a err_str will be printed; and the reaction module + !> will be destroyed. If using MPI, an MPI_Abort message will be sent before the reaction + !> module is destroyed. If the @a id is an invalid instance, RM_Abort will return a value of + !> IRM_BADINSTANCE, otherwise the program will exit with a return code of 4. + !> @param id The instance id returned from @ref RM_Create. + !> @param irm_result Integer treated as an IRM_RESULT return code. + !> @param err_str String to be printed as an error message. + !> @retval IRM_RESULT Program will exit before returning unless @a id is an invalid reaction module id. + !> @see + !> @ref RM_Destroy, + !> @ref RM_ErrorMessage. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> iphreeqc_id = RM_Concentrations2Utility(id, c_well, 1, tc, p_atm)
+    !> string = "SELECTED_OUTPUT 5; -pH;RUN_CELLS; -cells 1"
+    !> status = RunString(iphreeqc_id, string)
+    !> if (status .ne. 0) status = RM_Abort(id, status, "IPhreeqc RunString failed")
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root or workers. + + INTEGER FUNCTION RM_Abort(id, irm_result, err_str) USE ISO_C_BINDING - IMPLICIT NONE + IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_Abort(id, result, str) & - BIND(C, NAME='RMF_Abort') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - INTEGER(KIND=C_INT), INTENT(in) :: result - CHARACTER(KIND=C_CHAR), INTENT(in) :: str(*) - END FUNCTION RMF_Abort - END INTERFACE + INTEGER(KIND=C_INT) FUNCTION RMF_Abort(id, result, str) & + BIND(C, NAME='RMF_Abort') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + INTEGER(KIND=C_INT), INTENT(in) :: result + CHARACTER(KIND=C_CHAR), INTENT(in) :: str(*) + END FUNCTION RMF_Abort + END INTERFACE INTEGER, INTENT(in) :: id INTEGER, INTENT(in) :: irm_result CHARACTER(len=*), INTENT(in) :: err_str RM_Abort = RMF_Abort(id, irm_result, trim(err_str)//C_NULL_CHAR) - RETURN -END FUNCTION RM_Abort - -!> Close the output and log files. -!> @param id The instance @a id returned from @ref RM_Create. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_OpenFiles, -!> @ref RM_SetFilePrefix. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> status = RM_CloseFiles(id)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called only by root. - -INTEGER FUNCTION RM_CloseFiles(id) + RETURN + END FUNCTION RM_Abort + + !> Close the output and log files. + !> @param id The instance @a id returned from @ref RM_Create. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_OpenFiles, + !> @ref RM_SetFilePrefix. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> status = RM_CloseFiles(id)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called only by root. + + INTEGER FUNCTION RM_CloseFiles(id) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_CloseFiles(id) & - BIND(C, NAME='RMF_CloseFiles') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - END FUNCTION RMF_CloseFiles + INTEGER(KIND=C_INT) FUNCTION RMF_CloseFiles(id) & + BIND(C, NAME='RMF_CloseFiles') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + END FUNCTION RMF_CloseFiles END INTERFACE INTEGER, INTENT(in) :: id RM_CloseFiles = RMF_CloseFiles(id) - RETURN -END FUNCTION RM_CloseFiles - -!> @a N sets of component concentrations are converted to SOLUTIONs numbered 1-@a n in the Utility IPhreeqc. -!> The solutions can be reacted and manipulated with the methods of IPhreeqc. If solution concentration units -!> (@ref RM_SetUnitsSolution) are per liter, one liter of solution is created in the Utility instance; if solution -!> concentration units are mass fraction, one kilogram of solution is created in the Utility instance. -!> The motivation for this -!> method is the mixing of solutions in wells, where it may be necessary to calculate solution properties -!> (pH for example) or react the mixture to form scale minerals. The code fragments below make a mixture of -!> concentrations and then calculate the pH of the mixture. -!> @param id The instance @a id returned from @ref RM_Create. -!> @param c Array of concentrations to be made SOLUTIONs in Utility IPhreeqc, array size is -!> (@a n, @a ncomps) where @a ncomps is the number of components (@ref RM_GetComponentCount). -!> @param n The number of sets of concentrations. -!> @param tc Array of temperatures to apply to the SOLUTIONs, in degree C. Array of size @a n. -!> @param p_atm Array of pressures to apply to the SOLUTIONs, in atm. Array of size n. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> allocate (c_well(1,ncomps))
-!> do i = 1, ncomps
-!>   c_well(1,i) = 0.5 * c(1,i) + 0.5 * c(10,i)
-!> enddo
-!> allocate(tc(1), p_atm(1))
-!> tc(1) = 15.0
-!> p_atm(1) = 3.0
-!> iphreeqc_id = RM_Concentrations2Utility(id, c_well, 1, tc, p_atm)
-!> string = "SELECTED_OUTPUT 5; -pH; RUN_CELLS; -cells 1"
-!> status = RunString(iphreeqc_id, string)
-!> status = SetCurrentSelectedOutputUserNumber(iphreeqc_id, 5)
-!> status = GetSelectedOutputValue(iphreeqc_id, 1, 1, vtype, pH, svalue)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called only by root. - -INTEGER FUNCTION RM_Concentrations2Utility(id, c, n, tc, p_atm) + RETURN + END FUNCTION RM_CloseFiles + + !> @a N sets of component concentrations are converted to SOLUTIONs numbered 1-@a n in the Utility IPhreeqc. + !> The solutions can be reacted and manipulated with the methods of IPhreeqc. If solution concentration units + !> (@ref RM_SetUnitsSolution) are per liter, one liter of solution is created in the Utility instance; if solution + !> concentration units are mass fraction, one kilogram of solution is created in the Utility instance. + !> The motivation for this + !> method is the mixing of solutions in wells, where it may be necessary to calculate solution properties + !> (pH for example) or react the mixture to form scale minerals. The code fragments below make a mixture of + !> concentrations and then calculate the pH of the mixture. + !> @param id The instance @a id returned from @ref RM_Create. + !> @param c Array of concentrations to be made SOLUTIONs in Utility IPhreeqc, array size is + !> (@a n, @a ncomps) where @a ncomps is the number of components (@ref RM_GetComponentCount). + !> @param n The number of sets of concentrations. + !> @param tc Array of temperatures to apply to the SOLUTIONs, in degree C. Array of size @a n. + !> @param p_atm Array of pressures to apply to the SOLUTIONs, in atm. Array of size n. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> allocate (c_well(1,ncomps))
+    !> do i = 1, ncomps
+    !>   c_well(1,i) = 0.5 * c(1,i) + 0.5 * c(10,i)
+    !> enddo
+    !> allocate(tc(1), p_atm(1))
+    !> tc(1) = 15.0
+    !> p_atm(1) = 3.0
+    !> iphreeqc_id = RM_Concentrations2Utility(id, c_well, 1, tc, p_atm)
+    !> string = "SELECTED_OUTPUT 5; -pH; RUN_CELLS; -cells 1"
+    !> status = RunString(iphreeqc_id, string)
+    !> status = SetCurrentSelectedOutputUserNumber(iphreeqc_id, 5)
+    !> status = GetSelectedOutputValue(iphreeqc_id, 1, 1, vtype, pH, svalue)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called only by root. + + INTEGER FUNCTION RM_Concentrations2Utility(id, c, n, tc, p_atm) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_Concentrations2Utility(id, c, n, tc, p_atm) & - BIND(C, NAME='RMF_Concentrations2Utility') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - REAL(KIND=C_DOUBLE), INTENT(in) :: c(*) - INTEGER(KIND=C_INT), INTENT(in) :: n - REAL(KIND=C_DOUBLE), INTENT(in) :: tc(*), p_atm(*) - END FUNCTION RMF_Concentrations2Utility + INTEGER(KIND=C_INT) FUNCTION RMF_Concentrations2Utility(id, c, n, tc, p_atm) & + BIND(C, NAME='RMF_Concentrations2Utility') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + REAL(KIND=C_DOUBLE), INTENT(in) :: c(*) + INTEGER(KIND=C_INT), INTENT(in) :: n + REAL(KIND=C_DOUBLE), INTENT(in) :: tc(*), p_atm(*) + END FUNCTION RMF_Concentrations2Utility END INTERFACE INTEGER, INTENT(in) :: id - DOUBLE PRECISION, INTENT(in), DIMENSION(:,:) :: c + real(kind=8), INTENT(in), DIMENSION(:,:) :: c INTEGER, INTENT(in) :: n - DOUBLE PRECISION, INTENT(in), DIMENSION(:) :: tc, p_atm + real(kind=8), INTENT(in), DIMENSION(:) :: tc, p_atm if (rmf_debug) CALL ChK_Concentrations2Utility(id, c, n, tc, p_atm) RM_Concentrations2Utility = RMF_Concentrations2Utility(id, c, n, tc, p_atm) return -END FUNCTION RM_Concentrations2Utility + END FUNCTION RM_Concentrations2Utility -SUBROUTINE ChK_Concentrations2Utility(id, c, n, tc, p_atm) + SUBROUTINE ChK_Concentrations2Utility(id, c, n, tc, p_atm) + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION RMF_GetComponentCount(id) & + BIND(C, NAME='RMF_GetComponentCount') + USE ISO_C_BINDING IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + END FUNCTION RMF_GetComponentCount + END INTERFACE INTEGER, INTENT(in) :: id - DOUBLE PRECISION, INTENT(in), DIMENSION(:,:) :: c + real(kind=8), INTENT(in), DIMENSION(:,:) :: c INTEGER, INTENT(in) :: n - DOUBLE PRECISION, INTENT(in), DIMENSION(:) :: tc, p_atm + real(kind=8), INTENT(in), DIMENSION(:) :: tc, p_atm INTEGER :: errors errors = 0 + rmf_ncomps = RMF_GetComponentCount(id) errors = errors + Chk_Double2D(id, c, n, rmf_ncomps, "Concentration", "RM_Concentrations2Utility") errors = errors + Chk_Double1D(id, tc, n, "Temperature", "RM_Concentrations2Utility") errors = errors + Chk_Double1D(id, p_atm, n, "Pressure", "RM_Concentrations2Utility") if (errors .gt. 0) then errors = RM_Abort(id, -3, "Invalid argument(s) in RM_Concentrations2Utility") endif -END SUBROUTINE Chk_Concentrations2Utility - -!> Creates a reaction module. If the code is compiled with -!> the preprocessor directive USE_OPENMP, the reaction module is multithreaded. -!> If the code is compiled with the preprocessor directive USE_MPI, the reaction -!> module will use MPI and multiple processes. If neither preprocessor directive is used, -!> the reaction module will be serial (unparallelized). -!> @param nxyz The number of grid cells in the user's model. -!> @param nthreads (or @a comm, MPI) When using OPENMP, the argument (@a nthreads) is the number of worker threads to be used. -!> If @a nthreads <= 0, the number of threads is set equal to the number of processors of the computer. -!> When using MPI, the argument (@a comm) is the MPI communicator to use within the reaction module. -!> @retval Id of the PhreeqcRM instance, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_Destroy. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> nxyz = 40
-!> #ifdef USE_MPI
-!>   id = RM_Create(nxyz, MPI_COMM_WORLD)
-!>   call MPI_Comm_rank(MPI_COMM_WORLD, mpi_myself, status)
-!>   if (status .ne. MPI_SUCCESS) then
-!>     stop "Failed to get mpi_myself"
-!>   endif
-!>   if (mpi_myself > 0) then
-!>     status = RM_MpiWorker(id)
-!>     status = RM_Destroy(id)
-!>     return
-!>   endif
-!> #else
-!>   nthreads = 3
-!>   id = RM_Create(nxyz, nthreads)
-!> #endif
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root and workers. - -INTEGER FUNCTION RM_Create(nxyz, nthreads) + END SUBROUTINE Chk_Concentrations2Utility + + !> Creates a reaction module. If the code is compiled with + !> the preprocessor directive USE_OPENMP, the reaction module is multithreaded. + !> If the code is compiled with the preprocessor directive USE_MPI, the reaction + !> module will use MPI and multiple processes. If neither preprocessor directive is used, + !> the reaction module will be serial (unparallelized). + !> @param nxyz The number of grid cells in the user's model. + !> @param nthreads (or @a comm, MPI) When using OPENMP, the argument (@a nthreads) is the number of worker threads to be used. + !> If @a nthreads <= 0, the number of threads is set equal to the number of processors of the computer. + !> When using MPI, the argument (@a comm) is the MPI communicator to use within the reaction module. + !> @retval Id of the PhreeqcRM instance, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_Destroy. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> nxyz = 40
+    !> #ifdef USE_MPI
+    !>   id = RM_Create(nxyz, MPI_COMM_WORLD)
+    !>   call MPI_Comm_rank(MPI_COMM_WORLD, mpi_myself, status)
+    !>   if (status .ne. MPI_SUCCESS) then
+    !>     stop "Failed to get mpi_myself"
+    !>   endif
+    !>   if (mpi_myself > 0) then
+    !>     status = RM_MpiWorker(id)
+    !>     status = RM_Destroy(id)
+    !>     return
+    !>   endif
+    !> #else
+    !>   nthreads = 3
+    !>   id = RM_Create(nxyz, nthreads)
+    !> #endif
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root and workers. + + INTEGER FUNCTION RM_Create(nxyz, nthreads) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_Create(nxyz, nthreads) & - BIND(C, NAME='RMF_Create') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: nxyz - INTEGER(KIND=C_INT), INTENT(in) :: nthreads - END FUNCTION RMF_Create + INTEGER(KIND=C_INT) FUNCTION RMF_Create(nxyz, nthreads) & + BIND(C, NAME='RMF_Create') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: nxyz + INTEGER(KIND=C_INT), INTENT(in) :: nthreads + END FUNCTION RMF_Create END INTERFACE INTEGER, INTENT(in) :: nxyz INTEGER, INTENT(in) :: nthreads - RM_Create = RMF_Create(nxyz, nthreads) + RM_Create = RMF_Create(nxyz, nthreads) rmf_nxyz = nxyz - - return -END FUNCTION RM_Create - -!> Provides a mapping from grid cells in the user's model to reaction cells in PhreeqcRM. -!> The mapping is used to eliminate inactive cells and to use symmetry to decrease the number of cells for which chemistry must be run. -!> The array @a grid2chem of size @a nxyz (the number of grid cells, @ref RM_GetGridCellCount) -!> must contain the set of all integers 0 <= @a i < @a count_chemistry, -!> where @a count_chemistry is a number less than or equal to @a nxyz. -!> Inactive cells are assigned a negative integer. -!> The mapping may be many-to-one to account for symmetry. -!> Default is a one-to-one mapping--all user grid cells are reaction cells (equivalent to @a grid2chem values of 0,1,2,3,...,@a nxyz-1). -!> @param id The instance @a id returned from @ref RM_Create. -!> @param grid2chem An array of integers: Nonnegative is a reaction cell number (0 based), negative is an inactive cell. Array of size @a nxyz (number of grid cells). -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> ! For demonstation, two equivalent rows by symmetry
-!> allocate(grid2chem(nxyz))
-!> do i = 1, nxyz/2
-!>   grid2chem(i) = i - 1
-!>   grid2chem(i+nxyz/2) = i - 1
-!> enddo
-!> status = RM_CreateMapping(id, grid2chem)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root, workers must be in the loop of @ref RM_MpiWorker. -INTEGER FUNCTION RM_CreateMapping(id, grid2chem) + return + END FUNCTION RM_Create + + !> Provides a mapping from grid cells in the user's model to reaction cells in PhreeqcRM. + !> The mapping is used to eliminate inactive cells and to use symmetry to decrease the number of cells for which chemistry must be run. + !> The array @a grid2chem of size @a nxyz (the number of grid cells, @ref RM_GetGridCellCount) + !> must contain the set of all integers 0 <= @a i < @a count_chemistry, + !> where @a count_chemistry is a number less than or equal to @a nxyz. + !> Inactive cells are assigned a negative integer. + !> The mapping may be many-to-one to account for symmetry. + !> Default is a one-to-one mapping--all user grid cells are reaction cells (equivalent to @a grid2chem values of 0,1,2,3,...,@a nxyz-1). + !> @param id The instance @a id returned from @ref RM_Create. + !> @param grid2chem An array of integers: Nonnegative is a reaction cell number (0 based), negative is an inactive cell. Array of size @a nxyz (number of grid cells). + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> ! For demonstation, two equivalent rows by symmetry
+    !> allocate(grid2chem(nxyz))
+    !> do i = 1, nxyz/2
+    !>   grid2chem(i) = i - 1
+    !>   grid2chem(i+nxyz/2) = i - 1
+    !> enddo
+    !> status = RM_CreateMapping(id, grid2chem)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref RM_MpiWorker. + + INTEGER FUNCTION RM_CreateMapping(id, grid2chem) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_CreateMapping(id, grid2chem) & - BIND(C, NAME='RMF_CreateMapping') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - INTEGER(KIND=C_INT), INTENT(in) :: grid2chem(*) - END FUNCTION RMF_CreateMapping + INTEGER(KIND=C_INT) FUNCTION RMF_CreateMapping(id, grid2chem) & + BIND(C, NAME='RMF_CreateMapping') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + INTEGER(KIND=C_INT), INTENT(in) :: grid2chem(*) + END FUNCTION RMF_CreateMapping END INTERFACE INTEGER, INTENT(in) :: id INTEGER, INTENT(in), DIMENSION(:) :: grid2chem if (rmf_debug) call Chk_CreateMapping(id, grid2chem) RM_CreateMapping = RMF_CreateMapping(id, grid2chem) return -END FUNCTION RM_CreateMapping + END FUNCTION RM_CreateMapping -SUBROUTINE Chk_CreateMapping(id, grid2chem) + SUBROUTINE Chk_CreateMapping(id, grid2chem) IMPLICIT NONE INTEGER, INTENT(in) :: id INTEGER, INTENT(in), DIMENSION(:) :: grid2chem @@ -332,659 +382,708 @@ SUBROUTINE Chk_CreateMapping(id, grid2chem) if (errors .gt. 0) then errors = RM_Abort(id, -3, "Invalid argument(s) in RM_CreateMapping") endif -END SUBROUTINE Chk_CreateMapping - -!> If @a e is negative, this method prints an error message corresponding to IRM_RESULT @a e. If @a e is non-negative, no action is taken. -!> @param id The instance @a id returned from @ref RM_Create. -!> @param e An IRM_RESULT value returned by one of the reaction-module methods. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @par IRM_RESULT definition: -!> @htmlonly -!> -!>
-!> typedef enum {
-!>   IRM_OK            =  0,  //Success
-!>   IRM_OUTOFMEMORY   = -1,  //Failure, Out of memory
-!>   IRM_BADVARTYPE    = -2,  //Failure, Invalid VAR type
-!>   IRM_INVALIDARG    = -3,  //Failure, Invalid argument
-!>   IRM_INVALIDROW    = -4,  //Failure, Invalid row
-!>   IRM_INVALIDCOL    = -5,  //Failure, Invalid column
-!>   IRM_BADINSTANCE   = -6,  //Failure, Invalid rm instance id
-!>   IRM_FAIL          = -7,  //Failure, Unspecified
-!> } IRM_RESULT;
-!> 
-!>
-!> @endhtmlonly -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> status = RM_CreateMapping(id, grid2chem)
-!> if (status < 0) status = RM_DecodeError(id, status)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Can be called by root and (or) workers. - -INTEGER FUNCTION RM_DecodeError(id, e) + END SUBROUTINE Chk_CreateMapping + + !> If @a e is negative, this method prints an error message corresponding to IRM_RESULT @a e. If @a e is non-negative, no action is taken. + !> @param id The instance @a id returned from @ref RM_Create. + !> @param e An IRM_RESULT value returned by one of the reaction-module methods. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @par IRM_RESULT definition: + !> @htmlonly + !> + !>
+    !> typedef enum {
+    !>   IRM_OK            =  0,  ! Success
+    !>   IRM_OUTOFMEMORY   = -1,  ! Failure, Out of memory
+    !>   IRM_BADVARTYPE    = -2,  ! Failure, Invalid VAR type
+    !>   IRM_INVALIDARG    = -3,  ! Failure, Invalid argument
+    !>   IRM_INVALIDROW    = -4,  ! Failure, Invalid row
+    !>   IRM_INVALIDCOL    = -5,  ! Failure, Invalid column
+    !>   IRM_BADINSTANCE   = -6,  ! Failure, Invalid rm instance id
+    !>   IRM_FAIL          = -7,  ! Failure, Unspecified
+    !> } IRM_RESULT;
+    !> 
+ !>
+ !> @endhtmlonly + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> status = RM_CreateMapping(id, grid2chem)
+    !> if (status < 0) status = RM_DecodeError(id, status)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Can be called by root and (or) workers. + + INTEGER FUNCTION RM_DecodeError(id, e) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_DecodeError(id, e) & - BIND(C, NAME='RMF_DecodeError') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - INTEGER(KIND=C_INT), INTENT(in) :: e - END FUNCTION RMF_DecodeError + INTEGER(KIND=C_INT) FUNCTION RMF_DecodeError(id, e) & + BIND(C, NAME='RMF_DecodeError') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + INTEGER(KIND=C_INT), INTENT(in) :: e + END FUNCTION RMF_DecodeError END INTERFACE INTEGER, INTENT(in) :: id INTEGER, INTENT(in) :: e RM_DecodeError = RMF_DecodeError(id, e) return -END FUNCTION RM_DecodeError - -!> Destroys a reaction module. -!> @param id The instance @a id returned from @ref RM_Create. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_Create. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> status = RM_Destroy(id)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root and workers. - -INTEGER FUNCTION RM_Destroy(id) + END FUNCTION RM_DecodeError + + !> Destroys a reaction module. + !> @param id The instance @a id returned from @ref RM_Create. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_Create. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> status = RM_Destroy(id)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root and workers. + + INTEGER FUNCTION RM_Destroy(id) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_Destroy(id) & - BIND(C, NAME='RMF_Destroy') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - END FUNCTION RMF_Destroy + INTEGER(KIND=C_INT) FUNCTION RMF_Destroy(id) & + BIND(C, NAME='RMF_Destroy') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + END FUNCTION RMF_Destroy END INTERFACE INTEGER, INTENT(in) :: id RM_Destroy = RMF_Destroy(id) return -END FUNCTION RM_Destroy - -!> Writes the contents of all workers to file in _RAW formats, including SOLUTIONs and all reactants. -!> @param id The instance @a id returned from @ref RM_Create. -!> @param dump_on Signal for writing the dump file: 1 true, 0 false. -!> @param append Signal to append to the contents of the dump file: 1 true, 0 false. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_SetDumpFileName. -!> @par Fortran Example: -!> @htmlonly -!> -!>
      dump_on = 1
-!> append = 0
-!> status = RM_SetDumpFileName(id, "advection_f90.dmp")
-!> status = RM_DumpModule(id, dump_on, append)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root; workers must be in the loop of @ref RM_MpiWorker. - -INTEGER FUNCTION RM_DumpModule(id, dump_on, append) + END FUNCTION RM_Destroy + + !> Writes the contents of all workers to file in _RAW formats, including SOLUTIONs and all reactants. + !> @param id The instance @a id returned from @ref RM_Create. + !> @param dump_on Signal for writing the dump file: 1 true, 0 false. + !> @param append Signal to append to the contents of the dump file: 1 true, 0 false. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_SetDumpFileName. + !> @par Fortran Example: + !> @htmlonly + !> + !>
      
+    !> dump_on = 1
+    !> append = 0
+    !> status = RM_SetDumpFileName(id, "advection_f90.dmp")
+    !> status = RM_DumpModule(id, dump_on, append)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root; workers must be in the loop of @ref RM_MpiWorker. + + INTEGER FUNCTION RM_DumpModule(id, dump_on, append) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_DumpModule(id, dump_on, append) & - BIND(C, NAME='RMF_DumpModule') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - INTEGER(KIND=C_INT), INTENT(in) :: dump_on - INTEGER(KIND=C_INT), INTENT(in) :: append - END FUNCTION RMF_DumpModule + INTEGER(KIND=C_INT) FUNCTION RMF_DumpModule(id, dump_on, append) & + BIND(C, NAME='RMF_DumpModule') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + INTEGER(KIND=C_INT), INTENT(in) :: dump_on + INTEGER(KIND=C_INT), INTENT(in) :: append + END FUNCTION RMF_DumpModule END INTERFACE INTEGER, INTENT(in) :: id INTEGER, INTENT(in) :: dump_on INTEGER, INTENT(in) :: append RM_DumpModule = RMF_DumpModule(id, dump_on, append) return -END FUNCTION RM_DumpModule - -!> Send an error message to the screen, the output file, and the log file. -!> @param id The instance @a id returned from @ref RM_Create. -!> @param errstr String to be printed. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_LogMessage, -!> @ref RM_OpenFiles, -!> @ref RM_OutputMessage, -!> @ref RM_ScreenMessage, -!> @ref RM_WarningMessage. -!> -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> status = RM_ErrorMessage(id, "Goodbye world")
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root and (or) workers; root writes to output and log files. - -INTEGER FUNCTION RM_ErrorMessage(id, errstr) + END FUNCTION RM_DumpModule + + !> Send an error message to the screen, the output file, and the log file. + !> @param id The instance @a id returned from @ref RM_Create. + !> @param errstr String to be printed. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_LogMessage, + !> @ref RM_OpenFiles, + !> @ref RM_OutputMessage, + !> @ref RM_ScreenMessage, + !> @ref RM_WarningMessage. + !> + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> status = RM_ErrorMessage(id, "Goodbye world")
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root and (or) workers; root writes to output and log files. + + INTEGER FUNCTION RM_ErrorMessage(id, errstr) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_ErrorMessage(id, errstr) & - BIND(C, NAME='RMF_ErrorMessage') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - CHARACTER(KIND=C_CHAR), INTENT(in) :: errstr(*) - END FUNCTION RMF_ErrorMessage - END INTERFACE + INTEGER(KIND=C_INT) FUNCTION RMF_ErrorMessage(id, errstr) & + BIND(C, NAME='RMF_ErrorMessage') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + CHARACTER(KIND=C_CHAR), INTENT(in) :: errstr(*) + END FUNCTION RMF_ErrorMessage + END INTERFACE INTEGER, INTENT(in) :: id CHARACTER(len=*), INTENT(in) :: errstr RM_ErrorMessage = RMF_ErrorMessage(id, trim(errstr)//C_NULL_CHAR) return -END FUNCTION RM_ErrorMessage - -!> Returns the number of items in the list of all elements in the InitialPhreeqc instance. -!> Elements are those that have been defined in a solution or any other reactant (EQUILIBRIUM_PHASE, KINETICS, and others). -!> The method can be called multiple times and the list that is created is cummulative. -!> The list is the set of components that needs to be transported. -!> By default the list -!> includes water, excess H and excess O (the H and O not contained in water); -!> alternatively, the list may be set to contain total H and total O (@ref RM_SetComponentH2O), -!> which requires transport results to be accurate to eight or nine significant digits. -!> If multicomponent diffusion (MCD) is to be modeled, there is a capability to retrieve aqueous species concentrations -!> (@ref RM_GetSpeciesConcentrations) and to set new solution concentrations after MCD by using individual species concentrations -!> (@ref RM_SpeciesConcentrations2Module). To use these methods the save-species property needs to be turned on (@ref RM_SetSpeciesSaveOn). -!> If the save-species property is on, RM_FindComponents will generate -!> a list of aqueous species (@ref RM_GetSpeciesCount, @ref RM_GetSpeciesName), their diffusion coefficients at 25 C (@ref RM_GetSpeciesD25), -!> their charge (@ref RM_GetSpeciesZ). -!> @param id The instance @a id returned from @ref RM_Create. -!> @retval Number of components currently in the list, or IRM_RESULT error code (see @ref RM_DecodeError). -!> @see -!> @ref RM_GetComponent, -!> @ref RM_GetSpeciesConcentrations, -!> @ref RM_GetSpeciesCount, -!> @ref RM_GetSpeciesD25, -!> @ref RM_GetSpeciesLog10Gammas, -!> @ref RM_GetSpeciesLog10Molalities, -!> @ref RM_GetSpeciesName, -!> @ref RM_GetSpeciesZ, -!> @ref RM_SetComponentH2O. -!> @ref RM_SetSpeciesSaveOn, -!> @ref RM_SpeciesConcentrations2Module. -!> @par The RM_FindComponents method also generates lists of reactants--equilibrium phases, -!> exchangers, gas components, kinetic reactants, solid solution components, and surfaces. -!> The lists are cumulative, including all reactants that were -!> defined in the initial phreeqc instance at any time RM_FindComponents was called. -!> In addition, a list of phases is generated for which saturation indices may be calculated from the -!> cumulative list of components. -!> @see also -!> @ref RM_GetEquilibriumPhasesName, -!> @ref RM_GetEquilibriumPhasesCount, -!> @ref RM_GetExchangeName, -!> @ref RM_GetExchangeSpeciesName, -!> @ref RM_GetExchangeSpeciesCount, -!> @ref RM_GetGasComponentsName, -!> @ref RM_GetGasComponentsCount, -!> @ref RM_GetKineticReactionsName, -!> @ref RM_GetKineticReactionsCount, -!> @ref RM_GetSICount, -!> @ref RM_GetSIName, -!> @ref RM_GetSolidSolutionComponentsName, -!> @ref RM_GetSolidSolutionComponentsCount, -!> @ref RM_GetSolidSolutionName, -!> @ref RM_GetSurfaceName, -!> @ref RM_GetSurfaceSpeciesName, -!> @ref RM_GetSurfaceSpeciesCount, -!> @ref RM_GetSurfaceType. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> ! Get list of components
-!> ncomps = RM_FindComponents(id)
-!> allocate(components(ncomps))
-!> do i = 1, ncomps
-!>   status = RM_GetComponent(id, i, components(i))
-!> enddo
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root, workers must be in the loop of @ref RM_MpiWorker. - -INTEGER FUNCTION RM_FindComponents(id) + END FUNCTION RM_ErrorMessage + + !> Returns the number of items in the list of all elements in the InitialPhreeqc instance. + !> Elements are those that have been defined in a solution or any other reactant (EQUILIBRIUM_PHASE, KINETICS, and others). + !> The method can be called multiple times and the list that is created is cummulative. + !> The list is the set of components that needs to be transported. + !> By default the list + !> includes water, excess H and excess O (the H and O not contained in water); + !> alternatively, the list may be set to contain total H and total O (@ref RM_SetComponentH2O), + !> which requires transport results to be accurate to eight or nine significant digits. + !> If multicomponent diffusion (MCD) is to be modeled, there is a capability to retrieve aqueous species concentrations + !> (@ref RM_GetSpeciesConcentrations) and to set new solution concentrations after MCD by using individual species concentrations + !> (@ref RM_SpeciesConcentrations2Module). To use these methods the save-species property needs to be turned on (@ref RM_SetSpeciesSaveOn). + !> If the save-species property is on, RM_FindComponents will generate + !> a list of aqueous species (@ref RM_GetSpeciesCount, @ref RM_GetSpeciesName), their diffusion coefficients at 25 C (@ref RM_GetSpeciesD25), + !> their charge (@ref RM_GetSpeciesZ). + !> @param id The instance @a id returned from @ref RM_Create. + !> @retval Number of components currently in the list, or IRM_RESULT error code (see @ref RM_DecodeError). + !> @see + !> @ref RM_GetComponent, + !> @ref RM_GetSpeciesConcentrations, + !> @ref RM_GetSpeciesCount, + !> @ref RM_GetSpeciesD25, + !> @ref RM_GetSpeciesLog10Gammas, + !> @ref RM_GetSpeciesLog10Molalities, + !> @ref RM_GetSpeciesName, + !> @ref RM_GetSpeciesZ, + !> @ref RM_SetComponentH2O. + !> @ref RM_SetSpeciesSaveOn, + !> @ref RM_SpeciesConcentrations2Module. + !> @par The RM_FindComponents method also generates lists of reactants--equilibrium phases, + !> exchangers, gas components, kinetic reactants, solid solution components, and surfaces. + !> The lists are cumulative, including all reactants that were + !> defined in the initial phreeqc instance at any time RM_FindComponents was called. + !> In addition, a list of phases is generated for which saturation indices may be calculated from the + !> cumulative list of components. + !> @see also + !> @ref RM_GetEquilibriumPhasesName, + !> @ref RM_GetEquilibriumPhasesCount, + !> @ref RM_GetExchangeName, + !> @ref RM_GetExchangeSpeciesName, + !> @ref RM_GetExchangeSpeciesCount, + !> @ref RM_GetGasComponentsName, + !> @ref RM_GetGasComponentsCount, + !> @ref RM_GetKineticReactionsName, + !> @ref RM_GetKineticReactionsCount, + !> @ref RM_GetSICount, + !> @ref RM_GetSIName, + !> @ref RM_GetSolidSolutionComponentsName, + !> @ref RM_GetSolidSolutionComponentsCount, + !> @ref RM_GetSolidSolutionName, + !> @ref RM_GetSurfaceName, + !> @ref RM_GetSurfaceSpeciesName, + !> @ref RM_GetSurfaceSpeciesCount, + !> @ref RM_GetSurfaceType. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> ! Get list of components
+    !> ncomps = RM_FindComponents(id)
+    !> allocate(components(ncomps))
+    !> do i = 1, ncomps
+    !>   status = RM_GetComponent(id, i, components(i))
+    !> enddo
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref RM_MpiWorker. + + INTEGER FUNCTION RM_FindComponents(id) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_FindComponents(id) & - BIND(C, NAME='RMF_FindComponents') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - END FUNCTION RMF_FindComponents + INTEGER(KIND=C_INT) FUNCTION RMF_FindComponents(id) & + BIND(C, NAME='RMF_FindComponents') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + END FUNCTION RMF_FindComponents END INTERFACE INTEGER, INTENT(in) :: id RM_FindComponents = RMF_FindComponents(id) rmf_ncomps = RM_FindComponents return -END FUNCTION RM_FindComponents - -!> Fills an array with the cell numbers in the user's numbering sytstem that map to a cell in the -!> PhreeqcRM numbering system. The mapping is defined by @ref RM_CreateMapping. - -!> @param id The instance @a id returned from @ref RM_Create. -!> @param n A cell number in the PhreeqcRM numbering system (0 <= n < @ref RM_GetChemistryCellCount). -!> @param list Array to store the user cell numbers mapped to PhreeqcRM cell @a n. -!> @param size Input, the allocated size of @a list; it is an error if the array is too small. -!> Output, the number of cells mapped to cell @a n. -!> @retval IRM_RESULT error code (see @ref RM_DecodeError). -!> -!> @see -!> @ref RM_CreateMapping, -!> @ref RM_GetChemistryCellCount, -!> @ref RM_GetGridCellCount. -!> -!> @par C Example: -!> @htmlonly -!> -!>
-!> if (RM_GetBackwardMapping(rm_id, rm_cell_number, list, size) .eq. 0) then
-!>   if (fstr(1:l) .eq. "HYDRAULIC_K") then
-!>     my_basic_fortran_callback = K_ptr(list(1)+1) 
-!>   endif
-!> endif
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root and (or) workers. - -INTEGER FUNCTION RM_GetBackwardMapping(id, n, list, size) + END FUNCTION RM_FindComponents + + !> Fills an array with the cell numbers in the user's numbering sytstem that map to a cell in the + !> PhreeqcRM numbering system. The mapping is defined by @ref RM_CreateMapping. + + !> @param id The instance @a id returned from @ref RM_Create. + !> @param n A cell number in the PhreeqcRM numbering system (0 <= n < @ref RM_GetChemistryCellCount). + !> @param list Array to store the user cell numbers mapped to PhreeqcRM cell @a n. + !> @param size Input, the allocated size of @a list; it is an error if the array is too small. + !> Output, the number of cells mapped to cell @a n. + !> @retval IRM_RESULT error code (see @ref RM_DecodeError). + !> + !> @see + !> @ref RM_CreateMapping, + !> @ref RM_GetChemistryCellCount, + !> @ref RM_GetGridCellCount. + !> + !> @par C Example: + !> @htmlonly + !> + !>
+    !> if (RM_GetBackwardMapping(rm_id, rm_cell_number, list, size) .eq. 0) then
+    !>   if (fstr(1:l) .eq. "HYDRAULIC_K") then
+    !>     my_basic_fortran_callback = K_ptr(list(1)+1)
+    !>   endif
+    !> endif
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root and (or) workers. + + INTEGER FUNCTION RM_GetBackwardMapping(id, n, list, size) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_GetBackwardMapping(id, n, list, size) & - BIND(C, NAME='RMF_GetBackwardMapping') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id, n - INTEGER(KIND=C_INT), INTENT(in) :: list(*) - INTEGER(KIND=C_INT), INTENT(inout) :: size - END FUNCTION RMF_GetBackwardMapping + INTEGER(KIND=C_INT) FUNCTION RMF_GetBackwardMapping(id, n, list, size) & + BIND(C, NAME='RMF_GetBackwardMapping') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id, n + INTEGER(KIND=C_INT), INTENT(in) :: list(*) + INTEGER(KIND=C_INT), INTENT(inout) :: size + END FUNCTION RMF_GetBackwardMapping END INTERFACE INTEGER, INTENT(in) :: id, n INTEGER, INTENT(in) :: list(*) INTEGER, INTENT(inout) :: size RM_GetBackwardMapping = RMF_GetBackwardMapping(id, n, list, size) return -END FUNCTION RM_GetBackwardMapping - -!> Returns the number of chemistry cells in the reaction module. The number of chemistry cells is defined by -!> the set of non-negative integers in the mapping from user grid cells (@ref RM_CreateMapping). -!> The number of chemistry cells is less than or equal to the number of cells in the user's model. -!> @param id The instance @a id returned from @ref RM_Create. -!> @retval Number of chemistry cells, or IRM_RESULT error code (see @ref RM_DecodeError). -!> @see -!> @ref RM_CreateMapping, -!> @ref RM_GetGridCellCount. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> status = RM_CreateMapping(id, grid2chem)
-!> nchem = RM_GetChemistryCellCount(id)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root and (or) workers. - -INTEGER FUNCTION RM_GetChemistryCellCount(id) + END FUNCTION RM_GetBackwardMapping + + !> Returns the number of chemistry cells in the reaction module. The number of chemistry cells is defined by + !> the set of non-negative integers in the mapping from user grid cells (@ref RM_CreateMapping). + !> The number of chemistry cells is less than or equal to the number of cells in the user's model. + !> @param id The instance @a id returned from @ref RM_Create. + !> @retval Number of chemistry cells, or IRM_RESULT error code (see @ref RM_DecodeError). + !> @see + !> @ref RM_CreateMapping, + !> @ref RM_GetGridCellCount. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> status = RM_CreateMapping(id, grid2chem)
+    !> nchem = RM_GetChemistryCellCount(id)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root and (or) workers. + + INTEGER FUNCTION RM_GetChemistryCellCount(id) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_GetChemistryCellCount(id) & - BIND(C, NAME='RMF_GetChemistryCellCount') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - END FUNCTION RMF_GetChemistryCellCount + INTEGER(KIND=C_INT) FUNCTION RMF_GetChemistryCellCount(id) & + BIND(C, NAME='RMF_GetChemistryCellCount') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + END FUNCTION RMF_GetChemistryCellCount END INTERFACE INTEGER, INTENT(in) :: id RM_GetChemistryCellCount = RMF_GetChemistryCellCount(id) return -END FUNCTION RM_GetChemistryCellCount - -!> Retrieves an item from the reaction-module component list that was generated by calls to @ref RM_FindComponents. -!> @param id The instance @a id returned from @ref RM_Create. -!> @param num The number of the component to be retrieved. Fortran, 1 based. -!> @param comp_name The string value associated with component @a num. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_FindComponents, -!> @ref RM_GetComponentCount. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> ! Get list of components
-!> ncomps = RM_FindComponents(id)
-!> allocate(components(ncomps))
-!> do i = 1, ncomps
-!>   status = RM_GetComponent(id, i, components(i))
-!> enddo
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root and (or) workers. - -INTEGER FUNCTION RM_GetComponent(id, num, comp_name) + END FUNCTION RM_GetChemistryCellCount + + !> Retrieves an item from the reaction-module component list that was generated by calls to @ref RM_FindComponents. + !> @param id The instance @a id returned from @ref RM_Create. + !> @param num The number of the component to be retrieved. Fortran, 1 based. + !> @param comp_name The string value associated with component @a num. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_FindComponents, + !> @ref RM_GetComponentCount. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> ! Get list of components
+    !> ncomps = RM_FindComponents(id)
+    !> allocate(components(ncomps))
+    !> do i = 1, ncomps
+    !>   status = RM_GetComponent(id, i, components(i))
+    !> enddo
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root and (or) workers. + + INTEGER FUNCTION RM_GetComponent(id, num, comp_name) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_GetComponent(id, num, comp_name, l) & - BIND(C, NAME='RMF_GetComponent') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id, num, l - CHARACTER(KIND=C_CHAR), INTENT(out) :: comp_name(*) - END FUNCTION RMF_GetComponent + INTEGER(KIND=C_INT) FUNCTION RMF_GetComponent(id, num, comp_name, l) & + BIND(C, NAME='RMF_GetComponent') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id, num, l + CHARACTER(KIND=C_CHAR), INTENT(out) :: comp_name(*) + END FUNCTION RMF_GetComponent END INTERFACE INTEGER, INTENT(in) :: id, num CHARACTER(len=*), INTENT(inout) :: comp_name RM_GetComponent = RMF_GetComponent(id, num, comp_name, len(comp_name)) return -END FUNCTION RM_GetComponent - -!> Returns the number of components in the reaction-module component list. -!> The component list is generated by calls to @ref RM_FindComponents. -!> The return value from the last call to @ref RM_FindComponents is equal to the return value from RM_GetComponentCount. -!> @param id The instance @a id returned from @ref RM_Create. -!> @retval The number of components in the reaction-module component list, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_FindComponents, -!> @ref RM_GetComponent. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> ncomps1 = RM_GetComponentCount(id)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root. - -INTEGER FUNCTION RM_GetComponentCount(id) + END FUNCTION RM_GetComponent + + !> Returns a list of the names of the components identified by PhreeqcRM. + !> The list contains all components (elements) found in solutions and reactants in the + !> InitialPhreeqc instance by call(s) to @ref RM_FindComponents. + !> @param id The instance @a id returned from @ref RM_Create. + !> @param components A deferred length, allocatable, 1D character variable. + !> to receive the component names. Character length and dimension will be allocated as needed. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref bmif_get_value, + !> @ref bmif_set_value + !> @ref RM_GetComponent, + !> @ref RM_FindComponents. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> character(len=:), allocatable, dimension(:) :: components
+    !> status = RM_GetComponents(id, components)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root. + + !INTEGER FUNCTION RM_GetComponents(id, components) + !USE ISO_C_BINDING + !IMPLICIT NONE + !INTEGER, INTENT(in) :: id + !CHARACTER(len=:), allocatable, INTENT(out) :: components(:) + !RM_GetComponents = bmif_get_value(id, "Components", components) + !END FUNCTION RM_GetComponents + + INTEGER FUNCTION RM_GetComponents(id, dest) + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER, INTENT(in) :: id + CHARACTER(len=:), allocatable, dimension(:), INTENT(inout) :: dest + character(1024) :: comp + integer :: dim, itemsize, status, l, i + dim = RM_GetComponentCount(id) + itemsize = 0 + do i = 1, dim + status = RM_GetComponent(id, i, comp) + l = len(trim(comp)) + if (l > itemsize) itemsize = l + enddo + if(allocated(dest)) deallocate(dest) + allocate(character(len=itemsize) :: dest(dim)) + do i = 1, dim + status = RM_GetComponent(id, i, comp) + dest(i) = trim(comp) + enddo + RM_GetComponents = status + return + END FUNCTION RM_GetComponents + + !> Returns the number of components in the reaction-module component list. + !> The component list is generated by calls to @ref RM_FindComponents. + !> The return value from the last call to @ref RM_FindComponents is equal to the return value from RM_GetComponentCount. + !> @param id The instance @a id returned from @ref RM_Create. + !> @retval The number of components in the reaction-module component list, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_FindComponents, + !> @ref RM_GetComponent. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> ncomps1 = RM_GetComponentCount(id)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root. + + INTEGER FUNCTION RM_GetComponentCount(id) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_GetComponentCount(id) & - BIND(C, NAME='RMF_GetComponentCount') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - END FUNCTION RMF_GetComponentCount + INTEGER(KIND=C_INT) FUNCTION RMF_GetComponentCount(id) & + BIND(C, NAME='RMF_GetComponentCount') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + END FUNCTION RMF_GetComponentCount END INTERFACE INTEGER, INTENT(in) :: id RM_GetComponentCount = RMF_GetComponentCount(id) -END FUNCTION RM_GetComponentCount - -!> Transfer solution concentrations from each reaction cell -!> to the concentration array given in the argument list (@a c). -!> Units of concentration for @a c are defined by @ref RM_SetUnitsSolution. -!> For concentration units of per liter, -!> the solution volume is used to calculate the concentrations for @a c. -!> For mass fraction concentration units, -!> the solution mass is used to calculate concentrations for @a c. -!> Two options are available for the volume and mass of solution -!> that are used in converting to transport concentrations: (1) the volume and mass of solution are -!> calculated by PHREEQC, or -!> (2) the volume of solution is the product of saturation (@ref RM_SetSaturation), -!> porosity (@ref RM_SetPorosity), and representative volume (@ref RM_SetRepresentativeVolume), -!> and the mass of solution is volume times density as defined by @ref RM_SetDensity. -!> @ref RM_UseSolutionDensityVolume determines which option is used. -!> For option 1, the databases that have partial molar volume definitions needed -!> to accurately calculate solution volume are -!> phreeqc.dat, Amm.dat, and pitzer.dat. -!> -!> @param id The instance @a id returned from @ref RM_Create. -!> @param c Array to receive the concentrations. Dimension of the array is (@a nxyz, @a ncomps), -!> where @a nxyz is the number of user grid cells and @a ncomps is the result of @ref RM_FindComponents or @ref RM_GetComponentCount. -!> Values for inactive cells are set to 1e30. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> -!> @see -!> @ref RM_FindComponents, -!> @ref RM_GetComponentCount, -!> @ref RM_GetSaturation, -!> @ref RM_SetConcentrations, -!> @ref RM_SetDensity, -!> @ref RM_SetRepresentativeVolume, -!> @ref RM_SetSaturation, -!> @ref RM_SetUnitsSolution, -!> @ref RM_UseSolutionDensityVolume. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> allocate(c(nxyz, ncomps))
-!> status = RM_RunCells(id)
-!> status = RM_GetConcentrations(id, c)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root, workers must be in the loop of @ref RM_MpiWorker. - -INTEGER FUNCTION RM_GetConcentrations(id, c) - USE ISO_C_BINDING + END FUNCTION RM_GetComponentCount + + !> Transfer solution concentrations from each reaction cell + !> to the concentration array given in the argument list (@a c). + !> Units of concentration for @a c are defined by @ref RM_SetUnitsSolution. + !> For concentration units of per liter, + !> the solution volume is used to calculate the concentrations for @a c. + !> For mass fraction concentration units, + !> the solution mass is used to calculate concentrations for @a c. + !> Two options are available for the volume and mass of solution + !> that are used in converting to transport concentrations: (1) the volume and mass of solution are + !> calculated by PHREEQC, or + !> (2) the volume of solution is the product of saturation (@ref RM_SetSaturation), + !> porosity (@ref RM_SetPorosity), and representative volume (@ref RM_SetRepresentativeVolume), + !> and the mass of solution is volume times density as defined by @ref RM_SetDensity. + !> @ref RM_UseSolutionDensityVolume determines which option is used. + !> For option 1, the databases that have partial molar volume definitions needed + !> to accurately calculate solution volume are + !> phreeqc.dat, Amm.dat, and pitzer.dat. + !> + !> @param id The instance @a id returned from @ref RM_Create. + !> @param c Array to receive the concentrations. Dimension of the array is (@a nxyz, @a ncomps), + !> where @a nxyz is the number of user grid cells and @a ncomps is the result of @ref RM_FindComponents or @ref RM_GetComponentCount. + !> Values for inactive cells are set to 1e30. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> + !> @see + !> @ref RM_FindComponents, + !> @ref RM_GetComponentCount, + !> @ref RM_GetSaturation, + !> @ref RM_SetConcentrations, + !> @ref RM_SetDensity, + !> @ref RM_SetRepresentativeVolume, + !> @ref RM_SetSaturation, + !> @ref RM_SetUnitsSolution, + !> @ref RM_UseSolutionDensityVolume. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> allocate(c(nxyz, ncomps))
+    !> status = RM_RunCells(id)
+    !> status = RM_GetConcentrations(id, c)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref RM_MpiWorker. + + INTEGER FUNCTION RM_GetConcentrations(id, c) + USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_GetConcentrations(id, c) & - BIND(C, NAME='RMF_GetConcentrations') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - REAL(KIND=C_DOUBLE), INTENT(out) :: c(*) - END FUNCTION RMF_GetConcentrations + INTEGER(KIND=C_INT) FUNCTION RMF_GetConcentrations(id, c) & + BIND(C, NAME='RMF_GetConcentrations') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + REAL(KIND=C_DOUBLE), INTENT(out) :: c(*) + END FUNCTION RMF_GetConcentrations END INTERFACE INTEGER, INTENT(in) :: id - DOUBLE PRECISION, INTENT(out), DIMENSION(:,:) :: c - if (rmf_debug) call Chk_GetConcentrations(id, c) - RM_GetConcentrations = RMF_GetConcentrations(id, c) + real(kind=8), INTENT(out), DIMENSION(:,:) :: c + if (rmf_debug) call Chk_GetConcentrations(id, c) + RM_GetConcentrations = RMF_GetConcentrations(id, c) return -END FUNCTION RM_GetConcentrations + END FUNCTION RM_GetConcentrations -SUBROUTINE Chk_GetConcentrations(id, c) + SUBROUTINE Chk_GetConcentrations(id, c) IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION RMF_GetComponentCount(id) & + BIND(C, NAME='RMF_GetComponentCount') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + END FUNCTION RMF_GetComponentCount + END INTERFACE INTEGER, INTENT(in) :: id - DOUBLE PRECISION, INTENT(in), DIMENSION(:,:) :: c + real(kind=8), INTENT(in), DIMENSION(:,:) :: c INTEGER :: errors errors = 0 + rmf_ncomps = RMF_GetComponentCount(id) errors = errors + Chk_Double2D(id, c, rmf_nxyz, rmf_ncomps, "concentration", "RM_GetConcentrations") if (errors .gt. 0) then errors = RM_Abort(id, -3, "Invalid argument(s) in RM_GetConcentrations") endif -END SUBROUTINE Chk_GetConcentrations -#ifdef SKIP -INTEGER FUNCTION RM_GetConcentrations1D(id, c) - USE ISO_C_BINDING + END SUBROUTINE Chk_GetConcentrations + + !> Returns the user number of the current selected-output definition. + !> @ref RM_SetCurrentSelectedOutputUserNumber or @ref RM_SetNthSelectedOutput specifies which of the + !> selected-output definitions is used. + !> @retval User number of the the current selected-output definition, + !> negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_GetNthSelectedOutputUserNumber, + !> @ref RM_GetSelectedOutput, + !> @ref RM_GetSelectedOutputColumnCount, + !> @ref RM_GetSelectedOutputCount, + !> @ref RM_GetSelectedOutputHeading, + !> @ref RM_GetSelectedOutputRowCount, + !> @ref RM_SetCurrentSelectedOutputUserNumber, + !> @ref RM_SetNthSelectedOutput, + !> @ref RM_SetSelectedOutputOn. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> do isel = 1, RM_GetSelectedOutputCount(id)
+    !>   status = RM_SetNthSelectedOutput(id, isel)
+    !>   n_user = RM_GetCurrentSelectedOutputUserNumber(id)
+    !>   col = RM_GetSelectedOutputColumnCount(id)
+    !>   allocate(selected_out(nxyz,col))
+    !>   status = RM_GetSelectedOutput(id, selected_out)
+    !>   ! Process results here
+    !>   deallocate(selected_out)
+    !> enddo
+    !> 	
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root. + INTEGER FUNCTION RM_GetCurrentSelectedOutputUserNumber(id) + USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_GetConcentrations(id, c) & - BIND(C, NAME='RMF_GetConcentrations') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - REAL(KIND=C_DOUBLE), INTENT(out) :: c(*) - END FUNCTION RMF_GetConcentrations - END INTERFACE - INTEGER, INTENT(in) :: id - DOUBLE PRECISION, INTENT(out), DIMENSION(:,:) :: c - RM_GetConcentrations1D = RMF_GetConcentrations(id, c) - return -END FUNCTION RM_GetConcentrations1D -#endif -!> Returns the user number of the current selected-output definition. -!> @ref RM_SetCurrentSelectedOutputUserNumber or @ref RM_SetNthSelectedOutput specifies which of the -!> selected-output definitions is used. -!> @retval User number of the the current selected-output definition, -!> negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_GetNthSelectedOutputUserNumber, -!> @ref RM_GetSelectedOutput, -!> @ref RM_GetSelectedOutputColumnCount, -!> @ref RM_GetSelectedOutputCount, -!> @ref RM_GetSelectedOutputHeading, -!> @ref RM_GetSelectedOutputRowCount, -!> @ref RM_SetCurrentSelectedOutputUserNumber, -!> @ref RM_SetNthSelectedOutput, -!> @ref RM_SetSelectedOutputOn. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> do isel = 1, RM_GetSelectedOutputCount(id)
-!>   status = RM_SetNthSelectedOutput(id, isel)
-!>   n_user = RM_GetCurrentSelectedOutputUserNumber(id)
-!>   col = RM_GetSelectedOutputColumnCount(id)
-!>   allocate(selected_out(nxyz,col))
-!>   status = RM_GetSelectedOutput(id, selected_out)
-!>   ! Process results here
-!>   deallocate(selected_out)
-!> enddo
-!> 	
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root. -INTEGER FUNCTION RM_GetCurrentSelectedOutputUserNumber(id) - USE ISO_C_BINDING - IMPLICIT NONE - INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_GetCurrentSelectedOutputUserNumber(id) & - BIND(C, NAME='RMF_GetCurrentSelectedOutputUserNumber') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - END FUNCTION RMF_GetCurrentSelectedOutputUserNumber + INTEGER(KIND=C_INT) FUNCTION RMF_GetCurrentSelectedOutputUserNumber(id) & + BIND(C, NAME='RMF_GetCurrentSelectedOutputUserNumber') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + END FUNCTION RMF_GetCurrentSelectedOutputUserNumber END INTERFACE INTEGER, INTENT(in) :: id RM_GetCurrentSelectedOutputUserNumber = RMF_GetCurrentSelectedOutputUserNumber(id) -END FUNCTION RM_GetCurrentSelectedOutputUserNumber -!> Transfer solution densities from the reaction cells to the array given in the argument list (@a density). -!> Densities are those calculated by the reaction module. -!> Only the following databases distributed with PhreeqcRM have molar volume information needed to accurately calculate density: -!> phreeqc.dat, Amm.dat, and pitzer.dat. -!> -!> @param id The instance @a id returned from @ref RM_Create. -!> @param density Array to receive the densities. Dimension of the array is @a nxyz, -!> where @a nxyz is the number of user grid cells (@ref RM_GetGridCellCount). Values for inactive cells are set to 1e30. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> allocate(density(nxyz))
-!> status = RM_RunCells(id)
-!> status = RM_GetDensity(id, density)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root, workers must be in the loop of @ref RM_MpiWorker. - -INTEGER FUNCTION RM_GetDensity(id, density) + END FUNCTION RM_GetCurrentSelectedOutputUserNumber + !> Transfer solution densities from the reaction cells to the array given in the argument list (@a density). + !> Densities are those calculated by the reaction module. This method always + !> returns the calculated densities; @ref RM_SetDensity does not affect the result. + !> Only the following databases distributed with PhreeqcRM have molar volume information needed to accurately calculate density: + !> phreeqc.dat, Amm.dat, and pitzer.dat. + !> + !> @param id The instance @a id returned from @ref RM_Create. + !> @param density Array to receive the densities. Dimension of the array is @a nxyz, + !> where @a nxyz is the number of user grid cells (@ref RM_GetGridCellCount). Values for inactive cells are set to 1e30. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> allocate(density(nxyz))
+    !> status = RM_RunCells(id)
+    !> status = RM_GetDensity(id, density)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref RM_MpiWorker. + + INTEGER FUNCTION RM_GetDensity(id, density) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_GetDensity(id, density) & - BIND(C, NAME='RMF_GetDensity') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - REAL(KIND=C_DOUBLE), INTENT(out) :: density(*) - END FUNCTION RMF_GetDensity + INTEGER(KIND=C_INT) FUNCTION RMF_GetDensity(id, density) & + BIND(C, NAME='RMF_GetDensity') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + REAL(KIND=C_DOUBLE), INTENT(out) :: density(*) + END FUNCTION RMF_GetDensity END INTERFACE INTEGER, INTENT(in) :: id - DOUBLE PRECISION, INTENT(out), dimension(:) :: density + real(kind=8), INTENT(out), dimension(:) :: density if (rmf_debug) call Chk_GetDensity(id, density) - RM_GetDensity = RMF_GetDensity(id, density) + RM_GetDensity = RMF_GetDensity(id, density) return -END FUNCTION RM_GetDensity + END FUNCTION RM_GetDensity -SUBROUTINE Chk_GetDensity(id, density) + SUBROUTINE Chk_GetDensity(id, density) IMPLICIT NONE INTEGER, INTENT(in) :: id - DOUBLE PRECISION, INTENT(in), DIMENSION(:) :: density + real(kind=8), INTENT(in), DIMENSION(:) :: density INTEGER :: errors errors = 0 errors = errors + Chk_Double1D(id, density, rmf_nxyz, "density", "RM_GetDensity") if (errors .gt. 0) then errors = RM_Abort(id, -3, "Invalid argument in RM_GetDensity") endif -END SUBROUTINE Chk_GetDensity - -!> Returns an array with the ending cell numbers from the range of cell numbers assigned to each worker. -!> @param id The instance @a id returned from @ref RM_Create. -!> @param ec Array to receive the ending cell numbers. Dimension of the array is -!> the number of threads (OpenMP) or the number of processes (MPI). -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_Create, -!> @ref RM_GetMpiTasks, -!> @ref RM_GetStartCell, -!> @ref RM_GetThreadCount. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> n = RM_GetThreadCount(id) * RM_GetMpiTasks(id)
-!> allocate(ec(n))
-!> status = RM_GetEndCell(id, ec)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root and (or) workers. - -INTEGER FUNCTION RM_GetEndCell(id, ec) + END SUBROUTINE Chk_GetDensity + + !> Returns an array with the ending cell numbers from the range of cell numbers assigned to each worker. + !> @param id The instance @a id returned from @ref RM_Create. + !> @param ec Array to receive the ending cell numbers. Dimension of the array is + !> the number of threads (OpenMP) or the number of processes (MPI). + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_Create, + !> @ref RM_GetMpiTasks, + !> @ref RM_GetStartCell, + !> @ref RM_GetThreadCount. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> n = RM_GetThreadCount(id) * RM_GetMpiTasks(id)
+    !> allocate(ec(n))
+    !> status = RM_GetEndCell(id, ec)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root and (or) workers. + + INTEGER FUNCTION RM_GetEndCell(id, ec) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_GetEndCell(id, ec) & - BIND(C, NAME='RMF_GetEndCell') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - INTEGER(KIND=C_INT), INTENT(out):: ec(*) - END FUNCTION RMF_GetEndCell + INTEGER(KIND=C_INT) FUNCTION RMF_GetEndCell(id, ec) & + BIND(C, NAME='RMF_GetEndCell') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + INTEGER(KIND=C_INT), INTENT(out):: ec(*) + END FUNCTION RMF_GetEndCell END INTERFACE INTEGER, INTENT(in) :: id INTEGER, INTENT(out), DIMENSION(:) :: ec if (rmf_debug) call Chk_GetEndCell(id, ec) RM_GetEndCell = RMF_GetEndCell(id, ec) RETURN -END FUNCTION RM_GetEndCell + END FUNCTION RM_GetEndCell -SUBROUTINE Chk_GetEndCell(id, ec) + SUBROUTINE Chk_GetEndCell(id, ec) IMPLICIT NONE INTEGER, INTENT(in) :: id INTEGER, INTENT(in), DIMENSION(:) :: ec @@ -995,1180 +1094,1295 @@ SUBROUTINE Chk_GetEndCell(id, ec) if (errors .gt. 0) then errors = RM_Abort(id, -3, "Invalid argument in RM_GetEndCell") endif -END SUBROUTINE Chk_GetEndCell - -!> Returns the number of equilibrium phases in the initial-phreeqc module. -!> @ref RM_FindComponents must be called before @ref RM_GetEquilibriumPhasesCount. -!> This method may be useful when generating selected output definitions related to -!> equilibrium phases. -!> @param id The instance @a id returned from @ref RM_Create. -!> @retval The number of equilibrium phases in the initial-phreeqc module. -!> @see -!> @ref RM_FindComponents, -!> @ref RM_GetEquilibriumPhasesName. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> input = trim(input) // "  -equilibrium_phases " // new_line(c)
-!> do i = 1, RM_GetEquilibriumPhasesCount(id)
-!>   status = RM_GetEquilibriumPhasesName(id, i, line)
-!>   input = trim(input) // "    " // line // new_line(c)
-!> enddo
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root. - -INTEGER FUNCTION RM_GetEquilibriumPhasesCount(id) + END SUBROUTINE Chk_GetEndCell + + !> Returns the number of equilibrium phases in the initial-phreeqc module. + !> @ref RM_FindComponents must be called before @ref RM_GetEquilibriumPhasesCount. + !> This method may be useful when generating selected output definitions related to + !> equilibrium phases. + !> @param id The instance @a id returned from @ref RM_Create. + !> @retval The number of equilibrium phases in the initial-phreeqc module. + !> @see + !> @ref RM_FindComponents, + !> @ref RM_GetEquilibriumPhasesName. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> input = trim(input) // "  -equilibrium_phases " // new_line(c)
+    !> do i = 1, RM_GetEquilibriumPhasesCount(id)
+    !>   status = RM_GetEquilibriumPhasesName(id, i, line)
+    !>   input = trim(input) // "    " // line // new_line(c)
+    !> enddo
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root. + + INTEGER FUNCTION RM_GetEquilibriumPhasesCount(id) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_GetEquilibriumPhasesCount(id) & - BIND(C, NAME='RMF_GetEquilibriumPhasesCount') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - END FUNCTION RMF_GetEquilibriumPhasesCount + INTEGER(KIND=C_INT) FUNCTION RMF_GetEquilibriumPhasesCount(id) & + BIND(C, NAME='RMF_GetEquilibriumPhasesCount') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + END FUNCTION RMF_GetEquilibriumPhasesCount END INTERFACE INTEGER, INTENT(in) :: id RM_GetEquilibriumPhasesCount = RMF_GetEquilibriumPhasesCount(id) -END FUNCTION RM_GetEquilibriumPhasesCount - -!> Retrieves an item from the equilibrium phase list. -!> The list includes all phases included in any EQUILIBRIUM_PHASES definitions in -!> the initial-phreeqc module. -!> @ref RM_FindComponents must be called before @ref RM_GetEquilibriumPhasesName. -!> This method may be useful when generating selected output definitions related to equilibrium phases. -!> @param id The instance @a id returned from @ref RM_Create. -!> @param num The number of the equilibrium phase name to be retrieved. Fortran, 1 based. -!> @param name The equilibrium phase name at number @a num. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_FindComponents, -!> @ref RM_GetEquilibriumPhasesCount. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> input = trim(input) // "  -equilibrium_phases " // new_line(c)
-!> do i = 1, RM_GetEquilibriumPhasesCount(id)
-!>   status = RM_GetEquilibriumPhasesName(id, i, line)
-!>   input = trim(input) // "    " // line // new_line(c)
-!> enddo
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root. - -INTEGER FUNCTION RM_GetEquilibriumPhasesName(id, num, name) + END FUNCTION RM_GetEquilibriumPhasesCount + + !> Retrieves an item from the equilibrium phase list. + !> The list includes all phases included in any EQUILIBRIUM_PHASES definitions in + !> the initial-phreeqc module. + !> @ref RM_FindComponents must be called before @ref RM_GetEquilibriumPhasesName. + !> This method may be useful when generating selected output definitions related to equilibrium phases. + !> @param id The instance @a id returned from @ref RM_Create. + !> @param num The number of the equilibrium phase name to be retrieved. Fortran, 1 based. + !> @param name The equilibrium phase name at number @a num. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_FindComponents, + !> @ref RM_GetEquilibriumPhasesCount. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> input = trim(input) // "  -equilibrium_phases " // new_line(c)
+    !> do i = 1, RM_GetEquilibriumPhasesCount(id)
+    !>   status = RM_GetEquilibriumPhasesName(id, i, line)
+    !>   input = trim(input) // "    " // line // new_line(c)
+    !> enddo
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root. + + INTEGER FUNCTION RM_GetEquilibriumPhasesName(id, num, name) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_GetEquilibriumPhasesName(id, num, name, l) & - BIND(C, NAME='RMF_GetEquilibriumPhasesName') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id, num, l - CHARACTER(KIND=C_CHAR), INTENT(out) :: name(*) - END FUNCTION RMF_GetEquilibriumPhasesName + INTEGER(KIND=C_INT) FUNCTION RMF_GetEquilibriumPhasesName(id, num, name, l) & + BIND(C, NAME='RMF_GetEquilibriumPhasesName') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id, num, l + CHARACTER(KIND=C_CHAR), INTENT(out) :: name(*) + END FUNCTION RMF_GetEquilibriumPhasesName END INTERFACE INTEGER, INTENT(in) :: id, num CHARACTER(len=*), INTENT(inout) :: name RM_GetEquilibriumPhasesName = RMF_GetEquilibriumPhasesName(id, num, name, len(name)) return -END FUNCTION RM_GetEquilibriumPhasesName -!> Returns a string containing error messages related to the last call to a PhreeqcRM method to -!> the character argument (@a errstr). -!> -!> @param id The instance @a id returned from @ref RM_Create. -!> @param errstr The error string related to the last call to a PhreeqcRM method. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> character(len=:), allocatable :: errstr
-!> integer l
-!> if (status .ne. 0) then
-!>   l = RM_GetErrorStringLength(id)
-!>   allocate (character(len=l) :: errstr)
-!>   status = RM_GetErrorString(id, errstr)
-!>   write(*,"(A)") errstr
-!>   deallocate(errstr)
-!>   status = RM_Destroy(id)
-!>   stop
-!> endif 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root, workers must be in the loop of @ref RM_MpiWorker. - -INTEGER FUNCTION RM_GetErrorString(id, errstr) - USE ISO_C_BINDING + END FUNCTION RM_GetEquilibriumPhasesName + !> Returns a string containing error messages related to the last call to a PhreeqcRM method to + !> the character argument (@a errstr). + !> + !> @param id The instance @a id returned from @ref RM_Create. + !> @param errstr The error string related to the last call to a PhreeqcRM method. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> character(len=:), allocatable :: errstr
+    !> integer l
+    !> if (status .ne. 0) then
+    !>   l = RM_GetErrorStringLength(id)
+    !>   allocate (character(len=l) :: errstr)
+    !>   status = RM_GetErrorString(id, errstr)
+    !>   write(*,"(A)") errstr
+    !>   deallocate(errstr)
+    !>   status = RM_Destroy(id)
+    !>   stop
+    !> endif 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref RM_MpiWorker. + + INTEGER FUNCTION RM_GetErrorString(id, errstr) + USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_GetErrorString(id, errstr, l) & - BIND(C, NAME='RMF_GetErrorString') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - INTEGER(KIND=C_INT), INTENT(in) :: l - CHARACTER(KIND=C_CHAR), INTENT(out) :: errstr(*) - END FUNCTION RMF_GetErrorString + INTEGER(KIND=C_INT) FUNCTION RMF_GetErrorString(id, errstr, l) & + BIND(C, NAME='RMF_GetErrorString') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + INTEGER(KIND=C_INT), INTENT(in) :: l + CHARACTER(KIND=C_CHAR), INTENT(out) :: errstr(*) + END FUNCTION RMF_GetErrorString END INTERFACE INTEGER, INTENT(in) :: id CHARACTER(len=*), INTENT(out) :: errstr - RM_GetErrorString = RMF_GetErrorString(id, errstr, len(errstr)) -END FUNCTION RM_GetErrorString - -!> Returns the length of the string that contains error messages related to the last call to a PhreeqcRM method. -!> @param id The instance @a id returned from @ref RM_Create. -!> @retval int Length of the error message string. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> character(len=:), allocatable :: errstr
-!> integer l
-!> if (status .ne. 0) then
-!>   l = RM_GetErrorStringLength(id)
-!>   allocate (character(len=l) :: errstr)
-!>   status = RM_GetErrorString(id, errstr)
-!>   write(*,"(A)") errstr
-!>   deallocate(errstr)
-!>   status = RM_Destroy(id)
-!>   stop
-!> endif 
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root, workers must be in the loop of @ref RM_MpiWorker. - -INTEGER FUNCTION RM_GetErrorStringLength(id) - USE ISO_C_BINDING - IMPLICIT NONE - INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_GetErrorStringLength(id) & - BIND(C, NAME='RMF_GetErrorStringLength') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - END FUNCTION RMF_GetErrorStringLength - END INTERFACE - INTEGER, INTENT(in) :: id - RM_GetErrorStringLength = RMF_GetErrorStringLength(id) -END FUNCTION RM_GetErrorStringLength - -!> Retrieves an item from the exchange name list. -!> @ref RM_FindComponents must be called before @ref RM_GetExchangeName. -!> The exchange names vector is the same length as the exchange species names vector -!> and provides the corresponding exchange site (for example, X corresponing to NaX). -!> This method may be useful when generating selected output definitions related to exchangers. -!> @param id The instance @a id returned from @ref RM_Create. -!> @param num The number of the exchange name to be retrieved. Fortran, 1 based. -!> @param name The exchange name associated with exchange species @a num. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_FindComponents, -!> @ref RM_GetExchangeSpeciesCount, @ref RM_GetExchangeSpeciesName. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> do i = 1, RM_GetExchangeSpeciesCount(id)
-!>   status = RM_GetExchangeSpeciesName(id, i, line)
-!>   status = RM_GetExchangeName(id, i, line1)
-!>   input = trim(input) // "    " // line // " # " // line1 // new_line(c)
-!> enddo 
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root. - -INTEGER FUNCTION RM_GetExchangeName(id, num, name) + RM_GetErrorString = RMF_GetErrorString(id, errstr, len(errstr)) + END FUNCTION RM_GetErrorString + + !> Returns the length of the string that contains error messages related to the last call to a PhreeqcRM method. + !> @param id The instance @a id returned from @ref RM_Create. + !> @retval int Length of the error message string. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> character(len=:), allocatable :: errstr
+    !> integer l
+    !> if (status .ne. 0) then
+    !>   l = RM_GetErrorStringLength(id)
+    !>   allocate (character(len=l) :: errstr)
+    !>   status = RM_GetErrorString(id, errstr)
+    !>   write(*,"(A)") errstr
+    !>   deallocate(errstr)
+    !>   status = RM_Destroy(id)
+    !>   stop
+    !> endif
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref RM_MpiWorker. + + INTEGER FUNCTION RM_GetErrorStringLength(id) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_GetExchangeName(id, num, name, l) & - BIND(C, NAME='RMF_GetExchangeName') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id, num, l - CHARACTER(KIND=C_CHAR), INTENT(out) :: name(*) - END FUNCTION RMF_GetExchangeName + INTEGER(KIND=C_INT) FUNCTION RMF_GetErrorStringLength(id) & + BIND(C, NAME='RMF_GetErrorStringLength') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + END FUNCTION RMF_GetErrorStringLength + END INTERFACE + INTEGER, INTENT(in) :: id + RM_GetErrorStringLength = RMF_GetErrorStringLength(id) + END FUNCTION RM_GetErrorStringLength + + !> Retrieves an item from the exchange name list. + !> @ref RM_FindComponents must be called before @ref RM_GetExchangeName. + !> The exchange names vector is the same length as the exchange species names vector + !> and provides the corresponding exchange site (for example, X corresponing to NaX). + !> This method may be useful when generating selected output definitions related to exchangers. + !> @param id The instance @a id returned from @ref RM_Create. + !> @param num The number of the exchange name to be retrieved. Fortran, 1 based. + !> @param name The exchange name associated with exchange species @a num. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_FindComponents, + !> @ref RM_GetExchangeSpeciesCount, @ref RM_GetExchangeSpeciesName. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> do i = 1, RM_GetExchangeSpeciesCount(id)
+    !>   status = RM_GetExchangeSpeciesName(id, i, line)
+    !>   status = RM_GetExchangeName(id, i, line1)
+    !>   input = trim(input) // "    " // line // " # " // line1 // new_line(c)
+    !> enddo
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root. + + INTEGER FUNCTION RM_GetExchangeName(id, num, name) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION RMF_GetExchangeName(id, num, name, l) & + BIND(C, NAME='RMF_GetExchangeName') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id, num, l + CHARACTER(KIND=C_CHAR), INTENT(out) :: name(*) + END FUNCTION RMF_GetExchangeName END INTERFACE INTEGER, INTENT(in) :: id, num CHARACTER(len=*), INTENT(inout) :: name RM_GetExchangeName = RMF_GetExchangeName(id, num, name, len(name)) return -END FUNCTION RM_GetExchangeName -!> Returns the number of exchange species in the initial-phreeqc module. -!> @ref RM_FindComponents must be called before @ref RM_GetExchangeSpeciesCount. -!> This method may be useful when generating selected output definitions related to exchangers. -!> @param id The instance @a id returned from @ref RM_Create. -!> @retval The number of exchange species in the initial-phreeqc module. -!> @see -!> @ref RM_FindComponents, -!> @ref RM_GetExchangeSpeciesName, @ref RM_GetExchangeName. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> do i = 1, RM_GetExchangeSpeciesCount(id)
-!>   status = RM_GetExchangeSpeciesName(id, i, line)
-!>   status = RM_GetExchangeName(id, i, line1)
-!>   input = trim(input) // "    " // line // " # " // line1 // new_line(c)
-!> enddo
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root. - -INTEGER FUNCTION RM_GetExchangeSpeciesCount(id) + END FUNCTION RM_GetExchangeName + !> Returns the number of exchange species in the initial-phreeqc module. + !> @ref RM_FindComponents must be called before @ref RM_GetExchangeSpeciesCount. + !> This method may be useful when generating selected output definitions related to exchangers. + !> @param id The instance @a id returned from @ref RM_Create. + !> @retval The number of exchange species in the initial-phreeqc module. + !> @see + !> @ref RM_FindComponents, + !> @ref RM_GetExchangeSpeciesName, @ref RM_GetExchangeName. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> do i = 1, RM_GetExchangeSpeciesCount(id)
+    !>   status = RM_GetExchangeSpeciesName(id, i, line)
+    !>   status = RM_GetExchangeName(id, i, line1)
+    !>   input = trim(input) // "    " // line // " # " // line1 // new_line(c)
+    !> enddo
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root. + + INTEGER FUNCTION RM_GetExchangeSpeciesCount(id) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_GetExchangeSpeciesCount(id) & - BIND(C, NAME='RMF_GetExchangeSpeciesCount') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - END FUNCTION RMF_GetExchangeSpeciesCount + INTEGER(KIND=C_INT) FUNCTION RMF_GetExchangeSpeciesCount(id) & + BIND(C, NAME='RMF_GetExchangeSpeciesCount') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + END FUNCTION RMF_GetExchangeSpeciesCount END INTERFACE INTEGER, INTENT(in) :: id RM_GetExchangeSpeciesCount = RMF_GetExchangeSpeciesCount(id) -END FUNCTION RM_GetExchangeSpeciesCount - -!> Retrieves an item from the exchange species list. -!> The list of exchange species (such as "NaX") is derived from the list of components -!> (@ref RM_FindComponents) and the list of all exchange names (such as "X") -!> that are included in EXCHANGE definitions in the initial-phreeqc module. -!> @ref RM_FindComponents must be called before @ref RM_GetExchangeSpeciesName. -!> This method may be useful when generating selected output definitions related to exchangers. -!> @param id The instance @a id returned from @ref RM_Create. -!> @param num The number of the exchange species to be retrieved. Fortran, 1 based. -!> @param name The exchange species name at number @a num. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_FindComponents, -!> @ref RM_GetExchangeSpeciesCount, @ref RM_GetExchangeName. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> do i = 1, RM_GetExchangeSpeciesCount(id)
-!>   status = RM_GetExchangeSpeciesName(id, i, line)
-!>   status = RM_GetExchangeName(id, i, line1)
-!>   input = trim(input) // "    " // line // " # " // line1 // new_line(c)
-!> enddo 
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root. - -INTEGER FUNCTION RM_GetExchangeSpeciesName(id, num, name) + END FUNCTION RM_GetExchangeSpeciesCount + + !> Retrieves an item from the exchange species list. + !> The list of exchange species (such as "NaX") is derived from the list of components + !> (@ref RM_FindComponents) and the list of all exchange names (such as "X") + !> that are included in EXCHANGE definitions in the initial-phreeqc module. + !> @ref RM_FindComponents must be called before @ref RM_GetExchangeSpeciesName. + !> This method may be useful when generating selected output definitions related to exchangers. + !> @param id The instance @a id returned from @ref RM_Create. + !> @param num The number of the exchange species to be retrieved. Fortran, 1 based. + !> @param name The exchange species name at number @a num. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_FindComponents, + !> @ref RM_GetExchangeSpeciesCount, @ref RM_GetExchangeName. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> do i = 1, RM_GetExchangeSpeciesCount(id)
+    !>   status = RM_GetExchangeSpeciesName(id, i, line)
+    !>   status = RM_GetExchangeName(id, i, line1)
+    !>   input = trim(input) // "    " // line // " # " // line1 // new_line(c)
+    !> enddo
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root. + + INTEGER FUNCTION RM_GetExchangeSpeciesName(id, num, name) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_GetExchangeSpeciesName(id, num, name, l) & - BIND(C, NAME='RMF_GetExchangeSpeciesName') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id, num, l - CHARACTER(KIND=C_CHAR), INTENT(out) :: name(*) - END FUNCTION RMF_GetExchangeSpeciesName + INTEGER(KIND=C_INT) FUNCTION RMF_GetExchangeSpeciesName(id, num, name, l) & + BIND(C, NAME='RMF_GetExchangeSpeciesName') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id, num, l + CHARACTER(KIND=C_CHAR), INTENT(out) :: name(*) + END FUNCTION RMF_GetExchangeSpeciesName END INTERFACE INTEGER, INTENT(in) :: id, num CHARACTER(len=*), INTENT(inout) :: name RM_GetExchangeSpeciesName = RMF_GetExchangeSpeciesName(id, num, name, len(name)) return -END FUNCTION RM_GetExchangeSpeciesName - -!> Returns the reaction-module file prefix to the character argument (@a prefix). -!> @param id The instance @a id returned from @ref RM_Create. -!> @param prefix Character string where the prefix is written. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_SetFilePrefix. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> character(100) :: string
-!> character(200) :: string1
-!> status = RM_GetFilePrefix(id, string)
-!> string1 = "File prefix: "//string
-!> status = RM_OutputMessage(id, string1)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root and (or) workers. - -INTEGER FUNCTION RM_GetFilePrefix(id, prefix) + END FUNCTION RM_GetExchangeSpeciesName + + !> Returns the reaction-module file prefix to the character argument (@a prefix). + !> @param id The instance @a id returned from @ref RM_Create. + !> @param prefix Character string where the prefix is written. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_SetFilePrefix. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> character(100) :: string
+    !> character(200) :: string1
+    !> status = RM_GetFilePrefix(id, string)
+    !> string1 = "File prefix: "//string
+    !> status = RM_OutputMessage(id, string1)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root and (or) workers. + + INTEGER FUNCTION RM_GetFilePrefix(id, prefix) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_GetFilePrefix(id, prefix, l) & - BIND(C, NAME='RMF_GetFilePrefix') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - INTEGER(KIND=C_INT), INTENT(in) :: l - CHARACTER(KIND=C_CHAR), INTENT(out) :: prefix(*) - END FUNCTION RMF_GetFilePrefix + INTEGER(KIND=C_INT) FUNCTION RMF_GetFilePrefix(id, prefix, l) & + BIND(C, NAME='RMF_GetFilePrefix') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + INTEGER(KIND=C_INT), INTENT(in) :: l + CHARACTER(KIND=C_CHAR), INTENT(out) :: prefix(*) + END FUNCTION RMF_GetFilePrefix END INTERFACE INTEGER, INTENT(in) :: id CHARACTER(len=*), INTENT(inout) :: prefix integer l l = len(prefix) RM_GetFilePrefix = RMF_GetFilePrefix(id, prefix, l) -END FUNCTION RM_GetFilePrefix - -!> Returns the number of gas phase components in the initial-phreeqc module. -!> @ref RM_FindComponents must be called before @ref RM_GetGasComponentsCount. -!> This method may be useful when generating selected output definitions related to -!> gas phases. -!> @param id The instance @a id returned from @ref RM_Create. -!> @retval The number of gas phase components in the initial-phreeqc module. -!> @see -!> @ref RM_FindComponents, -!> @ref RM_GetGasComponentsName. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> input = trim(input) // "  -gas " // new_line(c)
-!> do i = 1, RM_GetGasComponentsCount(id)
-!>   status = RM_GetGasComponentsName(id, i, line)
-!>   input = trim(input) // "    " // line // new_line(c)
-!> enddo
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root. - -INTEGER FUNCTION RM_GetGasComponentsCount(id) + END FUNCTION RM_GetFilePrefix + + !> Returns the number of gas phase components in the initial-phreeqc module. + !> @ref RM_FindComponents must be called before @ref RM_GetGasComponentsCount. + !> This method may be useful when generating selected output definitions related to + !> gas phases. + !> @param id The instance @a id returned from @ref RM_Create. + !> @retval The number of gas phase components in the initial-phreeqc module. + !> @see + !> @ref RM_FindComponents, + !> @ref RM_GetGasComponentsName. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> input = trim(input) // "  -gas " // new_line(c)
+    !> do i = 1, RM_GetGasComponentsCount(id)
+    !>   status = RM_GetGasComponentsName(id, i, line)
+    !>   input = trim(input) // "    " // line // new_line(c)
+    !> enddo
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root. + + INTEGER FUNCTION RM_GetGasComponentsCount(id) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_GetGasComponentsCount(id) & - BIND(C, NAME='RMF_GetGasComponentsCount') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - END FUNCTION RMF_GetGasComponentsCount + INTEGER(KIND=C_INT) FUNCTION RMF_GetGasComponentsCount(id) & + BIND(C, NAME='RMF_GetGasComponentsCount') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + END FUNCTION RMF_GetGasComponentsCount END INTERFACE INTEGER, INTENT(in) :: id RM_GetGasComponentsCount = RMF_GetGasComponentsCount(id) -END FUNCTION RM_GetGasComponentsCount - -!> Retrieves an item from the gas components list. -!> The list includes all gas components included in any GAS_PHASE definitions in -!> the initial-phreeqc module. -!> @ref RM_FindComponents must be called before @ref RM_GetGasComponentsName. -!> This method may be useful when generating selected output definitions related to gas phases. -!> @param id The instance @a id returned from @ref RM_Create. -!> @param num The number of the gas component name to be retrieved. Fortran, 1 based. -!> @param name The gas component name at number @a num. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_FindComponents, -!> @ref RM_GetGasComponentsCount. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> input = trim(input) // "  -gas " // new_line(c)
-!> do i = 1, RM_GetGasComponentsCount(id)
-!>   status = RM_GetGasComponentsName(id, i, line)
-!>   input = trim(input) // "    " // line // new_line(c)
-!> enddo
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root. - -INTEGER FUNCTION RM_GetGasComponentsName(id, num, name) + END FUNCTION RM_GetGasComponentsCount + + !> Retrieves an item from the gas components list. + !> The list includes all gas components included in any GAS_PHASE definitions in + !> the initial-phreeqc module. + !> @ref RM_FindComponents must be called before @ref RM_GetGasComponentsName. + !> This method may be useful when generating selected output definitions related to gas phases. + !> @param id The instance @a id returned from @ref RM_Create. + !> @param num The number of the gas component name to be retrieved. Fortran, 1 based. + !> @param name The gas component name at number @a num. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_FindComponents, + !> @ref RM_GetGasComponentsCount. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> input = trim(input) // "  -gas " // new_line(c)
+    !> do i = 1, RM_GetGasComponentsCount(id)
+    !>   status = RM_GetGasComponentsName(id, i, line)
+    !>   input = trim(input) // "    " // line // new_line(c)
+    !> enddo
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root. + + INTEGER FUNCTION RM_GetGasComponentsName(id, num, name) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_GetGasComponentsName(id, num, name, l) & - BIND(C, NAME='RMF_GetGasComponentsName') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id, num, l - CHARACTER(KIND=C_CHAR), INTENT(out) :: name(*) - END FUNCTION RMF_GetGasComponentsName + INTEGER(KIND=C_INT) FUNCTION RMF_GetGasComponentsName(id, num, name, l) & + BIND(C, NAME='RMF_GetGasComponentsName') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id, num, l + CHARACTER(KIND=C_CHAR), INTENT(out) :: name(*) + END FUNCTION RMF_GetGasComponentsName END INTERFACE INTEGER, INTENT(in) :: id, num CHARACTER(len=*), INTENT(inout) :: name RM_GetGasComponentsName = RMF_GetGasComponentsName(id, num, name, len(name)) return -END FUNCTION RM_GetGasComponentsName - -!> Transfer moles of gas components from each reaction cell -!> to the array given in the argument list (@a gas_moles). -!> -!> @param id The instance @a id returned from @ref RM_Create. -!> @param gas_moles Array to receive the moles of gas components for each cell. -!> Dimension of the array is (@a nxyz, @a ngas_comps), -!> where @a nxyz is the number of user grid cells and @a ngas_comps is the result -!> of @ref RM_GetGasComponentsCount. If a gas component is not defined for a cell, -!> the number of moles is set to -1. Values for inactive cells are set to 1e30. -!> -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> -!> @see -!> @ref RM_FindComponents, -!> @ref RM_GetGasComponentsCount, -!> @ref RM_GetGasCompPressures, -!> @ref RM_GetGasCompPhi, -!> @ref RM_GetGasPhaseVolume, -!> @ref RM_SetGasCompMoles, -!> @ref RM_SetGasPhaseVolume. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> ngas_comps = RM_GetGasComponentsCount(id)
-!> allocate(gas_moles(nxyz, ngas_comps))
-!> status = RM_RunCells(id)
-!> status = RM_GetGasCompMoles(id, gas_moles)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root, workers must be in the loop of @ref RM_MpiWorker. - -INTEGER FUNCTION RM_GetGasCompMoles(id, gas_moles) - USE ISO_C_BINDING + END FUNCTION RM_GetGasComponentsName + + !> Transfer moles of gas components from each reaction cell + !> to the array given in the argument list (@a gas_moles). + !> + !> @param id The instance @a id returned from @ref RM_Create. + !> @param gas_moles Array to receive the moles of gas components for each cell. + !> Dimension of the array is (@a nxyz, @a ngas_comps), + !> where @a nxyz is the number of user grid cells and @a ngas_comps is the result + !> of @ref RM_GetGasComponentsCount. If a gas component is not defined for a cell, + !> the number of moles is set to -1. Values for inactive cells are set to 1e30. + !> + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> + !> @see + !> @ref RM_FindComponents, + !> @ref RM_GetGasComponentsCount, + !> @ref RM_GetGasCompPressures, + !> @ref RM_GetGasCompPhi, + !> @ref RM_GetGasPhaseVolume, + !> @ref RM_SetGasCompMoles, + !> @ref RM_SetGasPhaseVolume. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> ngas_comps = RM_GetGasComponentsCount(id)
+    !> allocate(gas_moles(nxyz, ngas_comps))
+    !> status = RM_RunCells(id)
+    !> status = RM_GetGasCompMoles(id, gas_moles)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref RM_MpiWorker. + + INTEGER FUNCTION RM_GetGasCompMoles(id, gas_moles) + USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_GetGasCompMoles(id, gas_moles) & - BIND(C, NAME='RMF_GetGasCompMoles') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - REAL(KIND=C_DOUBLE), INTENT(out) :: gas_moles(*) - END FUNCTION RMF_GetGasCompMoles + INTEGER(KIND=C_INT) FUNCTION RMF_GetGasCompMoles(id, gas_moles) & + BIND(C, NAME='RMF_GetGasCompMoles') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + REAL(KIND=C_DOUBLE), INTENT(out) :: gas_moles(*) + END FUNCTION RMF_GetGasCompMoles END INTERFACE INTEGER, INTENT(in) :: id - DOUBLE PRECISION, INTENT(out), DIMENSION(:,:), TARGET :: gas_moles - if (rmf_debug) call Chk_GetGasCompMoles(id, gas_moles) - RM_GetGasCompMoles = RMF_GetGasCompMoles(id, gas_moles) + real(kind=8), INTENT(out), DIMENSION(:,:), TARGET :: gas_moles + if (rmf_debug) call Chk_GetGasCompMoles(id, gas_moles) + RM_GetGasCompMoles = RMF_GetGasCompMoles(id, gas_moles) return -END FUNCTION RM_GetGasCompMoles + END FUNCTION RM_GetGasCompMoles -SUBROUTINE Chk_GetGasCompMoles(id, gas_moles) + SUBROUTINE Chk_GetGasCompMoles(id, gas_moles) IMPLICIT NONE INTEGER, INTENT(in) :: id - DOUBLE PRECISION, INTENT(in), DIMENSION(:,:) :: gas_moles + real(kind=8), INTENT(in), DIMENSION(:,:) :: gas_moles INTEGER :: errors, rmf_ngas_comps errors = 0 - rmf_ngas_comps = RM_GetGasComponentsCount(id) + rmf_ngas_comps = RM_GetGasComponentsCount(id) errors = errors + Chk_Double2D(id, gas_moles, rmf_nxyz, rmf_ngas_comps, "gas_moles", "RM_GetGasCompMoles") if (errors .gt. 0) then errors = RM_Abort(id, -3, "Invalid argument(s) in RM_GetGasCompMoles") endif -END SUBROUTINE Chk_GetGasCompMoles - -!> Transfer pressures of gas components from each reaction cell -!> to the array given in the argument list (@a gas_p). -!> -!> @param id The instance @a id returned from @ref RM_Create. -!> @param gas_p Array to receive the moles of gas components for each cell. -!> Dimension of the array is (@a nxyz, @a ngas_comps), -!> where @a nxyz is the number of user grid cells and @a ngas_comps is the result -!> of @ref RM_GetGasComponentsCount. If a gas component is not defined for a cell, -!> the pressure is set to -1. Values for inactive cells are set to 1e30. -!> Values for inactive cells are set to 1e30. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> -!> @see -!> @ref RM_FindComponents, -!> @ref RM_GetGasComponentsCount, -!> @ref RM_GetGasCompMoles, -!> @ref RM_GetGasCompPhi, -!> @ref RM_GetGasPhaseVolume, -!> @ref RM_SetGasCompMoles, -!> @ref RM_SetGasPhaseVolume. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> ngas_comps = RM_GetGasComponentsCount(id)
-!> allocate(gas_p(nxyz, ngas_comps))
-!> status = RM_RunCells(id)
-!> status = RM_GetGasCompPressures(id, gas_p)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root, workers must be in the loop of @ref RM_MpiWorker. - -INTEGER FUNCTION RM_GetGasCompPressures(id, gas_p) - USE ISO_C_BINDING + END SUBROUTINE Chk_GetGasCompMoles + + !> Transfer pressures of gas components from each reaction cell + !> to the array given in the argument list (@a gas_p). + !> + !> @param id The instance @a id returned from @ref RM_Create. + !> @param gas_p Array to receive the moles of gas components for each cell. + !> Dimension of the array is (@a nxyz, @a ngas_comps), + !> where @a nxyz is the number of user grid cells and @a ngas_comps is the result + !> of @ref RM_GetGasComponentsCount. If a gas component is not defined for a cell, + !> the pressure is set to -1. Values for inactive cells are set to 1e30. + !> Values for inactive cells are set to 1e30. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> + !> @see + !> @ref RM_FindComponents, + !> @ref RM_GetGasComponentsCount, + !> @ref RM_GetGasCompMoles, + !> @ref RM_GetGasCompPhi, + !> @ref RM_GetGasPhaseVolume, + !> @ref RM_SetGasCompMoles, + !> @ref RM_SetGasPhaseVolume. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> ngas_comps = RM_GetGasComponentsCount(id)
+    !> allocate(gas_p(nxyz, ngas_comps))
+    !> status = RM_RunCells(id)
+    !> status = RM_GetGasCompPressures(id, gas_p)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref RM_MpiWorker. + + INTEGER FUNCTION RM_GetGasCompPressures(id, gas_p) + USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_GetGasCompPressures(id, gas_p) & - BIND(C, NAME='RMF_GetGasCompPressures') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - REAL(KIND=C_DOUBLE), INTENT(out) :: gas_p(*) - END FUNCTION RMF_GetGasCompPressures + INTEGER(KIND=C_INT) FUNCTION RMF_GetGasCompPressures(id, gas_p) & + BIND(C, NAME='RMF_GetGasCompPressures') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + REAL(KIND=C_DOUBLE), INTENT(out) :: gas_p(*) + END FUNCTION RMF_GetGasCompPressures END INTERFACE INTEGER, INTENT(in) :: id - DOUBLE PRECISION, INTENT(out), DIMENSION(:,:), TARGET :: gas_p - if (rmf_debug) call Chk_GetGasCompPressures(id, gas_p) - RM_GetGasCompPressures = RMF_GetGasCompPressures(id, gas_p ) + real(kind=8), INTENT(out), DIMENSION(:,:), TARGET :: gas_p + if (rmf_debug) call Chk_GetGasCompPressures(id, gas_p) + RM_GetGasCompPressures = RMF_GetGasCompPressures(id, gas_p ) return -END FUNCTION RM_GetGasCompPressures + END FUNCTION RM_GetGasCompPressures -SUBROUTINE Chk_GetGasCompPressures(id, gas_p) + SUBROUTINE Chk_GetGasCompPressures(id, gas_p) IMPLICIT NONE INTEGER, INTENT(in) :: id - DOUBLE PRECISION, INTENT(in), DIMENSION(:,:) :: gas_p + real(kind=8), INTENT(in), DIMENSION(:,:) :: gas_p INTEGER :: errors, rmf_ngas_comps errors = 0 - rmf_ngas_comps = RM_GetGasComponentsCount(id) + rmf_ngas_comps = RM_GetGasComponentsCount(id) errors = errors + Chk_Double2D(id, gas_p, rmf_nxyz, rmf_ngas_comps, "gas_pressure", "RM_GetGasCompPressures") if (errors .gt. 0) then errors = RM_Abort(id, -3, "Invalid argument(s) in RM_GetGasCompPressures") endif -END SUBROUTINE Chk_GetGasCompPressures - -!> Transfer fugacity coefficients (phi) of gas components from each reaction cell -!> to the array given in the argument list (@a gas_phi). Fugacity of a gas component -!> is equal to the pressure of the component times the fugacity coefficient. -!> -!> @param id The instance @a id returned from @ref RM_Create. -!> @param gas_phi Array to receive the fugacity coefficients -!> of gas components for each cell. -!> Dimension of the array is (@a nxyz, @a ngas_comps), -!> where @a nxyz is the number of user grid cells and @a ngas_comps is the result -!> of @ref RM_GetGasComponentsCount. If a gas component is not defined for a cell, -!> the fugacity coefficient is set to -1. Values for inactive cells are set to 1e30. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> -!> @see -!> @ref RM_FindComponents, -!> @ref RM_GetGasComponentsCount, -!> @ref RM_GetGasCompMoles, -!> @ref RM_GetGasCompPressures, -!> @ref RM_GetGasPhaseVolume, -!> @ref RM_SetGasCompMoles, -!> @ref RM_SetGasPhaseVolume. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> ngas_comps = RM_GetGasComponentsCount(id)
-!> allocate(gas_phi(nxyz, ngas_comps))
-!> status = RM_RunCells(id)
-!> status = RM_GetGasCompPhi(id, gas_phi)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root, workers must be in the loop of @ref RM_MpiWorker. - -INTEGER FUNCTION RM_GetGasCompPhi(id, gas_phi) - USE ISO_C_BINDING + END SUBROUTINE Chk_GetGasCompPressures + + !> Transfer fugacity coefficients (phi) of gas components from each reaction cell + !> to the array given in the argument list (@a gas_phi). Fugacity of a gas component + !> is equal to the pressure of the component times the fugacity coefficient. + !> + !> @param id The instance @a id returned from @ref RM_Create. + !> @param gas_phi Array to receive the fugacity coefficients + !> of gas components for each cell. + !> Dimension of the array is (@a nxyz, @a ngas_comps), + !> where @a nxyz is the number of user grid cells and @a ngas_comps is the result + !> of @ref RM_GetGasComponentsCount. If a gas component is not defined for a cell, + !> the fugacity coefficient is set to -1. Values for inactive cells are set to 1e30. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> + !> @see + !> @ref RM_FindComponents, + !> @ref RM_GetGasComponentsCount, + !> @ref RM_GetGasCompMoles, + !> @ref RM_GetGasCompPressures, + !> @ref RM_GetGasPhaseVolume, + !> @ref RM_SetGasCompMoles, + !> @ref RM_SetGasPhaseVolume. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> ngas_comps = RM_GetGasComponentsCount(id)
+    !> allocate(gas_phi(nxyz, ngas_comps))
+    !> status = RM_RunCells(id)
+    !> status = RM_GetGasCompPhi(id, gas_phi)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref RM_MpiWorker. + + INTEGER FUNCTION RM_GetGasCompPhi(id, gas_phi) + USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_GetGasCompPhi(id, gas_phi) & - BIND(C, NAME='RMF_GetGasCompPhi') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - REAL(KIND=C_DOUBLE), INTENT(out) :: gas_phi(*) - END FUNCTION RMF_GetGasCompPhi + INTEGER(KIND=C_INT) FUNCTION RMF_GetGasCompPhi(id, gas_phi) & + BIND(C, NAME='RMF_GetGasCompPhi') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + REAL(KIND=C_DOUBLE), INTENT(out) :: gas_phi(*) + END FUNCTION RMF_GetGasCompPhi END INTERFACE INTEGER, INTENT(in) :: id - DOUBLE PRECISION, INTENT(out), DIMENSION(:,:), TARGET :: gas_phi - if (rmf_debug) call Chk_GetGasCompPhi(id, gas_phi) - RM_GetGasCompPhi = RMF_GetGasCompPhi(id, gas_phi) + real(kind=8), INTENT(out), DIMENSION(:,:), TARGET :: gas_phi + if (rmf_debug) call Chk_GetGasCompPhi(id, gas_phi) + RM_GetGasCompPhi = RMF_GetGasCompPhi(id, gas_phi) return -END FUNCTION RM_GetGasCompPhi + END FUNCTION RM_GetGasCompPhi -SUBROUTINE Chk_GetGasCompPhi(id, gas_phi) + SUBROUTINE Chk_GetGasCompPhi(id, gas_phi) IMPLICIT NONE INTEGER, INTENT(in) :: id - DOUBLE PRECISION, INTENT(in), DIMENSION(:,:) :: gas_phi + real(kind=8), INTENT(in), DIMENSION(:,:) :: gas_phi INTEGER :: errors, rmf_ngas_comps errors = 0 - rmf_ngas_comps = RM_GetGasComponentsCount(id) + rmf_ngas_comps = RM_GetGasComponentsCount(id) errors = errors + Chk_Double2D(id, gas_phi, rmf_nxyz, rmf_ngas_comps, "gas_phi", "RM_GetGasCompPhi") if (errors .gt. 0) then errors = RM_Abort(id, -3, "Invalid argument(s) in RM_GetGasCompPhi") endif -END SUBROUTINE Chk_GetGasCompPhi - -!> Transfer volume of gas from each reaction cell -!> to the vector given in the argument list (@a gas_volume). -!> -!> @param id The instance @a id returned from @ref RM_Create. -!> @param gas_volume Array to receive the gas phase volumes. -!> Dimension of the array must be @a nxyz, -!> where @a nxyz is the number of user grid cells (@ref RM_GetGridCellCount). -!> If a gas phase is not defined for a cell, the volume is set to -1. -!> Values for inactive cells are set to 1e30. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> -!> @see -!> @ref RM_FindComponents, -!> @ref RM_GetGasComponentsCount, -!> @ref RM_GetGasCompMoles, -!> @ref RM_GetGasCompPhi, -!> @ref RM_GetGasCompPressures, -!> @ref RM_SetGasCompMoles -!> @ref RM_SetGasPhaseVolume. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> ngas_comps = RM_GetGasComponentsCount(id)
-!> allocate(gas_volume(nxyz, ngas_comps))
-!> status = RM_RunCells(id)
-!> status = RM_GetGasPhaseVolume(id, gas_volume)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root, workers must be in the loop of @ref RM_MpiWorker. - -INTEGER FUNCTION RM_GetGasPhaseVolume(id, gas_volume) - USE ISO_C_BINDING + END SUBROUTINE Chk_GetGasCompPhi + + !> Transfer volume of gas from each reaction cell + !> to the vector given in the argument list (@a gas_volume). + !> + !> @param id The instance @a id returned from @ref RM_Create. + !> @param gas_volume Array to receive the gas phase volumes. + !> Dimension of the array must be @a nxyz, + !> where @a nxyz is the number of user grid cells (@ref RM_GetGridCellCount). + !> If a gas phase is not defined for a cell, the volume is set to -1. + !> Values for inactive cells are set to 1e30. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> + !> @see + !> @ref RM_FindComponents, + !> @ref RM_GetGasComponentsCount, + !> @ref RM_GetGasCompMoles, + !> @ref RM_GetGasCompPhi, + !> @ref RM_GetGasCompPressures, + !> @ref RM_SetGasCompMoles + !> @ref RM_SetGasPhaseVolume. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> ngas_comps = RM_GetGasComponentsCount(id)
+    !> allocate(gas_volume(nxyz, ngas_comps))
+    !> status = RM_RunCells(id)
+    !> status = RM_GetGasPhaseVolume(id, gas_volume)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref RM_MpiWorker. + + INTEGER FUNCTION RM_GetGasPhaseVolume(id, gas_volume) + USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_GetGasPhaseVolume(id, gas_volume) & - BIND(C, NAME='RMF_GetGasPhaseVolume') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - REAL(KIND=C_DOUBLE), INTENT(out) :: gas_volume(*) - END FUNCTION RMF_GetGasPhaseVolume + INTEGER(KIND=C_INT) FUNCTION RMF_GetGasPhaseVolume(id, gas_volume) & + BIND(C, NAME='RMF_GetGasPhaseVolume') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + REAL(KIND=C_DOUBLE), INTENT(out) :: gas_volume(*) + END FUNCTION RMF_GetGasPhaseVolume END INTERFACE INTEGER, INTENT(in) :: id - DOUBLE PRECISION, INTENT(out), DIMENSION(:), TARGET :: gas_volume - if (rmf_debug) call Chk_GetGasPhaseVolume(id, gas_volume) - RM_GetGasPhaseVolume = RMF_GetGasPhaseVolume(id, gas_volume) + real(kind=8), INTENT(out), DIMENSION(:), TARGET :: gas_volume + if (rmf_debug) call Chk_GetGasPhaseVolume(id, gas_volume) + RM_GetGasPhaseVolume = RMF_GetGasPhaseVolume(id, gas_volume) return -END FUNCTION RM_GetGasPhaseVolume + END FUNCTION RM_GetGasPhaseVolume -SUBROUTINE Chk_GetGasPhaseVolume(id, gas_volume) + SUBROUTINE Chk_GetGasPhaseVolume(id, gas_volume) IMPLICIT NONE INTEGER, INTENT(in) :: id - DOUBLE PRECISION, INTENT(in), DIMENSION(:) :: gas_volume + real(kind=8), INTENT(in), DIMENSION(:) :: gas_volume INTEGER :: errors, rmf_ngas_comps errors = 0 - rmf_ngas_comps = RM_GetGasComponentsCount(id) + rmf_ngas_comps = RM_GetGasComponentsCount(id) errors = errors + Chk_Double1D(id, gas_volume, rmf_nxyz, "gas_volume", "RM_GetGasPhaseVolume") if (errors .gt. 0) then errors = RM_Abort(id, -3, "Invalid argument(s) in RM_GetGasPhaseVolume") endif -END SUBROUTINE Chk_GetGasPhaseVolume - -!> Returns the gram formula weights (g/mol) for the components in the reaction-module component list. -!> @param id The instance id returned from @ref RM_Create. -!> @param gfw Array to receive the gram formula weights. Dimension of the array is @a ncomps, -!> where @a ncomps is the number of components in the component list. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_FindComponents, -!> @ref RM_GetComponent, -!> @ref RM_GetComponentCount. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> character(100),   dimension(:), allocatable   :: components
-!> double precision, dimension(:), allocatable   :: gfw
-!> ncomps = RM_FindComponents(id)
-!> allocate(components(ncomps))
-!> allocate(gfw(ncomps))
-!> status = RM_GetGfw(id, gfw)
-!> do i = 1, ncomps
-!>   status = RM_GetComponent(id, i, components(i))
-!>   write(string,"(A10, F15.4)") components(i), gfw(i)
-!>   status = RM_OutputMessage(id, string)
-!> enddo
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root. - -INTEGER FUNCTION RM_GetGfw(id, gfw) + END SUBROUTINE Chk_GetGasPhaseVolume + + !> Returns the gram formula weights (g/mol) for the components in the reaction-module component list. + !> @param id The instance id returned from @ref RM_Create. + !> @param gfw Array to receive the gram formula weights. Dimension of the array is @a ncomps, + !> where @a ncomps is the number of components in the component list. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_FindComponents, + !> @ref RM_GetComponent, + !> @ref RM_GetComponentCount. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> character(100),   dimension(:), allocatable   :: components
+    !> real(kind=8), dimension(:), allocatable   :: gfw
+    !> ncomps = RM_FindComponents(id)
+    !> allocate(components(ncomps))
+    !> allocate(gfw(ncomps))
+    !> status = RM_GetGfw(id, gfw)
+    !> do i = 1, ncomps
+    !>   status = RM_GetComponent(id, i, components(i))
+    !>   write(string,"(A10, F15.4)") components(i), gfw(i)
+    !>   status = RM_OutputMessage(id, string)
+    !> enddo
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root. + + INTEGER FUNCTION RM_GetGfw(id, gfw) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_GetGfw(id, gfw) & - BIND(C, NAME='RMF_GetGfw') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - REAL(KIND=C_DOUBLE), INTENT(out) :: gfw(*) - END FUNCTION RMF_GetGfw + INTEGER(KIND=C_INT) FUNCTION RMF_GetGfw(id, gfw) & + BIND(C, NAME='RMF_GetGfw') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + REAL(KIND=C_DOUBLE), INTENT(out) :: gfw(*) + END FUNCTION RMF_GetGfw END INTERFACE INTEGER, INTENT(in) :: id - DOUBLE PRECISION, DIMENSION(:), INTENT(out) :: gfw - if (rmf_debug) call Chk_GetGfw(id, gfw) - RM_GetGfw = RMF_GetGfw(id, gfw) -END FUNCTION RM_GetGfw + real(kind=8), DIMENSION(:), INTENT(out) :: gfw + if (rmf_debug) call Chk_GetGfw(id, gfw) + RM_GetGfw = RMF_GetGfw(id, gfw) + END FUNCTION RM_GetGfw -SUBROUTINE Chk_GetGfw(id, gfw) + SUBROUTINE Chk_GetGfw(id, gfw) + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION RMF_GetComponentCount(id) & + BIND(C, NAME='RMF_GetComponentCount') + USE ISO_C_BINDING IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + END FUNCTION RMF_GetComponentCount + END INTERFACE INTEGER, INTENT(in) :: id - DOUBLE PRECISION, INTENT(in), DIMENSION(:) :: gfw + real(kind=8), INTENT(in), DIMENSION(:) :: gfw INTEGER :: errors errors = 0 + rmf_ncomps = RMF_GetComponentCount(id) errors = errors + Chk_Double1D(id, gfw, rmf_ncomps, "gfw", "RM_GetGfw") if (errors .gt. 0) then errors = RM_Abort(id, -3, "Invalid argument in RM_GetGfw") endif -END SUBROUTINE Chk_GetGfw - -!> Returns the number of grid cells in the user's model, which is defined in the call to @ref RM_Create. -!> The mapping from grid cells to reaction cells is defined by @ref RM_CreateMapping. -!> The number of reaction cells may be less than the number of grid cells if -!> there are inactive regions or symmetry in the model definition. -!> @param id The instance @a id returned from @ref RM_Create. -!> @retval Number of grid cells in the user's model, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_Create, -!> @ref RM_CreateMapping. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> nxyz = RM_GetGridCellCount(id)
-!> write(string1, "(A,I)") "Number of grid cells in the user's model: ", nxyz
-!> status = RM_OutputMessage(id, trim(string1))
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root and (or) workers. - -INTEGER FUNCTION RM_GetGridCellCount(id) + END SUBROUTINE Chk_GetGfw + + !> Returns the number of grid cells in the user's model, which is defined in the call to @ref RM_Create. + !> The mapping from grid cells to reaction cells is defined by @ref RM_CreateMapping. + !> The number of reaction cells may be less than the number of grid cells if + !> there are inactive regions or symmetry in the model definition. + !> @param id The instance @a id returned from @ref RM_Create. + !> @retval Number of grid cells in the user's model, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_Create, + !> @ref RM_CreateMapping. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> nxyz = RM_GetGridCellCount(id)
+    !> write(string1, "(A,I)") "Number of grid cells in the user's model: ", nxyz
+    !> status = RM_OutputMessage(id, trim(string1))
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root and (or) workers. + INTEGER FUNCTION RM_GetGridCellCount(id) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_GetGridCellCount(id) & - BIND(C, NAME='RMF_GetGridCellCount') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - END FUNCTION RMF_GetGridCellCount + INTEGER(KIND=C_INT) FUNCTION RMF_GetGridCellCount(id) & + BIND(C, NAME='RMF_GetGridCellCount') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + END FUNCTION RMF_GetGridCellCount END INTERFACE INTEGER, INTENT(in) :: id RM_GetGridCellCount = RMF_GetGridCellCount(id) -END FUNCTION RM_GetGridCellCount - -!> Returns an IPhreeqc id for the @a ith IPhreeqc instance in the reaction module. -!> For the threaded version, there are @a nthreads + 2 IPhreeqc instances, where -!> @a nthreads is defined in the constructor (@ref RM_Create). -!> The number of threads can be determined by @ref RM_GetThreadCount. -!> The first @a nthreads (0 based) instances will be the workers, the -!> next (@a nthreads) is the InitialPhreeqc instance, and the next (@a nthreads + 1) is the Utility instance. -!> Getting the IPhreeqc pointer for one of these instances allows the user to use any of the IPhreeqc methods -!> on that instance. -!> For MPI, each process has exactly three IPhreeqc instances, one worker (number 0), -!> one InitialPhreeqc instance (number 1), and one Utility instance (number 2). -!> -!> @param id The instance @a id returned from @ref RM_Create. -!> @param i The number of the IPhreeqc instance to be retrieved (0 based). -!> @retval IPhreeqc id for the @a ith IPhreeqc instance, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_Create, -!> @ref RM_GetThreadCount. -!> See IPhreeqc documentation for descriptions of IPhreeqc methods. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> ! Utility pointer is worker number nthreads + 1
-!> iphreeqc_id1 = RM_GetIPhreeqcId(id, RM_GetThreadCount(id) + 1)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root and (or) workers. - -INTEGER FUNCTION RM_GetIPhreeqcId(id, i) + END FUNCTION RM_GetGridCellCount + + !> Returns an IPhreeqc id for the @a ith IPhreeqc instance in the reaction module. + !> For the threaded version, there are @a nthreads + 2 IPhreeqc instances, where + !> @a nthreads is defined in the constructor (@ref RM_Create). + !> The number of threads can be determined by @ref RM_GetThreadCount. + !> The first @a nthreads (0 based) instances will be the workers, the + !> next (@a nthreads) is the InitialPhreeqc instance, and the next (@a nthreads + 1) is the Utility instance. + !> Getting the IPhreeqc pointer for one of these instances allows the user to use any of the IPhreeqc methods + !> on that instance. + !> For MPI, each process has exactly three IPhreeqc instances, one worker (number 0), + !> one InitialPhreeqc instance (number 1), and one Utility instance (number 2). + !> + !> @param id The instance @a id returned from @ref RM_Create. + !> @param i The number of the IPhreeqc instance to be retrieved (0 based). + !> @retval IPhreeqc id for the @a ith IPhreeqc instance, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_Create, + !> @ref RM_GetThreadCount. + !> See IPhreeqc documentation for descriptions of IPhreeqc methods. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> ! Utility pointer is worker number nthreads + 1
+    !> iphreeqc_id1 = RM_GetIPhreeqcId(id, RM_GetThreadCount(id) + 1)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root and (or) workers. + + INTEGER FUNCTION RM_GetIPhreeqcId(id, i) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_GetIPhreeqcId(id, i) & - BIND(C, NAME='RMF_GetIPhreeqcId') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - INTEGER(KIND=C_INT), INTENT(in) :: i - END FUNCTION RMF_GetIPhreeqcId + INTEGER(KIND=C_INT) FUNCTION RMF_GetIPhreeqcId(id, i) & + BIND(C, NAME='RMF_GetIPhreeqcId') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + INTEGER(KIND=C_INT), INTENT(in) :: i + END FUNCTION RMF_GetIPhreeqcId END INTERFACE INTEGER, INTENT(in) :: id INTEGER, INTENT(in) :: i RM_GetIPhreeqcId = RMF_GetIPhreeqcId(id, i) -END FUNCTION RM_GetIPhreeqcId - -!> Returns the number of kinetic reactions in the initial-phreeqc module. -!> @ref RM_FindComponents must be called before @ref RM_GetKineticReactionsCount. -!> This method may be useful when generating selected output definitions related to -!> kinetic reactions. -!> @param id The instance @a id returned from @ref RM_Create. -!> @retval The number of kinetic reactions in the initial-phreeqc module. -!> @see -!> @ref RM_FindComponents, -!> @ref RM_GetKineticReactionsName. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> input = trim(input) // "  -kinetics " // new_line(c)
-!> do i = 1, RM_GetKineticReactionsCount(id)
-!>   status = RM_GetKineticReactionsName(id, i, line)
-!>   input = trim(input) // "    " // line // new_line(c)
-!> enddo
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root. - -INTEGER FUNCTION RM_GetKineticReactionsCount(id) + END FUNCTION RM_GetIPhreeqcId + + !> Returns the number of kinetic reactions in the initial-phreeqc module. + !> @ref RM_FindComponents must be called before @ref RM_GetKineticReactionsCount. + !> This method may be useful when generating selected output definitions related to + !> kinetic reactions. + !> @param id The instance @a id returned from @ref RM_Create. + !> @retval The number of kinetic reactions in the initial-phreeqc module. + !> @see + !> @ref RM_FindComponents, + !> @ref RM_GetKineticReactionsName. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> input = trim(input) // "  -kinetics " // new_line(c)
+    !> do i = 1, RM_GetKineticReactionsCount(id)
+    !>   status = RM_GetKineticReactionsName(id, i, line)
+    !>   input = trim(input) // "    " // line // new_line(c)
+    !> enddo
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root. + + INTEGER FUNCTION RM_GetKineticReactionsCount(id) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_GetGetKineticReactionsCount(id) & - BIND(C, NAME='RMF_GetKineticReactionsCount') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - END FUNCTION RMF_GetGetKineticReactionsCount + INTEGER(KIND=C_INT) FUNCTION RMF_GetGetKineticReactionsCount(id) & + BIND(C, NAME='RMF_GetKineticReactionsCount') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + END FUNCTION RMF_GetGetKineticReactionsCount END INTERFACE INTEGER, INTENT(in) :: id RM_GetKineticReactionsCount = RMF_GetGetKineticReactionsCount(id) -END FUNCTION RM_GetKineticReactionsCount - -!> Retrieves an item from the kinetic reactions list. -!> The list includes all kinetic reactions included in any KINETICS definitions in -!> the initial-phreeqc module. -!> @ref RM_FindComponents must be called before @ref RM_GetKineticReactionsName. -!> This method may be useful when generating selected output definitions related to kinetic reactions. -!> @param id The instance @a id returned from @ref RM_Create. -!> @param num The number of the kinetic reaction name to be retrieved. Fortran, 1 based. -!> @param name The kinetic reaction name at number @a num. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_FindComponents, -!> @ref RM_GetKineticReactionsCount. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> input = trim(input) // "  -kinetics " // new_line(c)
-!> do i = 1, RM_GetKineticReactionsCount(id)
-!>   status = RM_GetKineticReactionsName(id, i, line)
-!>   input = trim(input) // "    " // line // new_line(c)
-!> enddo
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root. - -INTEGER FUNCTION RM_GetKineticReactionsName(id, num, name) + END FUNCTION RM_GetKineticReactionsCount + + !> Retrieves an item from the kinetic reactions list. + !> The list includes all kinetic reactions included in any KINETICS definitions in + !> the initial-phreeqc module. + !> @ref RM_FindComponents must be called before @ref RM_GetKineticReactionsName. + !> This method may be useful when generating selected output definitions related to kinetic reactions. + !> @param id The instance @a id returned from @ref RM_Create. + !> @param num The number of the kinetic reaction name to be retrieved. Fortran, 1 based. + !> @param name The kinetic reaction name at number @a num. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_FindComponents, + !> @ref RM_GetKineticReactionsCount. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> input = trim(input) // "  -kinetics " // new_line(c)
+    !> do i = 1, RM_GetKineticReactionsCount(id)
+    !>   status = RM_GetKineticReactionsName(id, i, line)
+    !>   input = trim(input) // "    " // line // new_line(c)
+    !> enddo
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root. + + INTEGER FUNCTION RM_GetKineticReactionsName(id, num, name) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_GetKineticReactionsName(id, num, name, l) & - BIND(C, NAME='RMF_GetKineticReactionsName') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id, num, l - CHARACTER(KIND=C_CHAR), INTENT(out) :: name(*) - END FUNCTION RMF_GetKineticReactionsName + INTEGER(KIND=C_INT) FUNCTION RMF_GetKineticReactionsName(id, num, name, l) & + BIND(C, NAME='RMF_GetKineticReactionsName') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id, num, l + CHARACTER(KIND=C_CHAR), INTENT(out) :: name(*) + END FUNCTION RMF_GetKineticReactionsName END INTERFACE INTEGER, INTENT(in) :: id, num CHARACTER(len=*), INTENT(inout) :: name RM_GetKineticReactionsName = RMF_GetKineticReactionsName(id, num, name, len(name)) return -END FUNCTION RM_GetKineticReactionsName - -!> Returns the MPI task number. For the OPENMP version, the task number is always -!> zero and the result of @ref RM_GetMpiTasks is one. For the MPI version, -!> the root task number is zero, and all workers have a task number greater than zero. -!> The number of tasks can be obtained with @ref RM_GetMpiTasks. The number of -!> tasks and computer hosts are determined at run time by the mpiexec command, and the -!> number of reaction-module processes is defined by the communicator used in -!> constructing the reaction modules (@ref RM_Create). -!> @param id The instance @a id returned from @ref RM_Create. -!> @retval The MPI task number for a process, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_GetMpiTasks. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> write(string1, "(A,I)") "MPI task number: ", RM_GetMpiMyself(id)
-!> status = RM_OutputMessage(id, string1)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root and (or) workers. - -INTEGER FUNCTION RM_GetMpiMyself(id) + END FUNCTION RM_GetKineticReactionsName + + !> Returns the MPI task number. For the OPENMP version, the task number is always + !> zero and the result of @ref RM_GetMpiTasks is one. For the MPI version, + !> the root task number is zero, and all workers have a task number greater than zero. + !> The number of tasks can be obtained with @ref RM_GetMpiTasks. The number of + !> tasks and computer hosts are determined at run time by the mpiexec command, and the + !> number of reaction-module processes is defined by the communicator used in + !> constructing the reaction modules (@ref RM_Create). + !> @param id The instance @a id returned from @ref RM_Create. + !> @retval The MPI task number for a process, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_GetMpiTasks. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> write(string1, "(A,I)") "MPI task number: ", RM_GetMpiMyself(id)
+    !> status = RM_OutputMessage(id, string1)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root and (or) workers. + + INTEGER FUNCTION RM_GetMpiMyself(id) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_GetMpiMyself(id) & - BIND(C, NAME='RMF_GetMpiMyself') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - END FUNCTION RMF_GetMpiMyself + INTEGER(KIND=C_INT) FUNCTION RMF_GetMpiMyself(id) & + BIND(C, NAME='RMF_GetMpiMyself') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + END FUNCTION RMF_GetMpiMyself END INTERFACE INTEGER, INTENT(in) :: id RM_GetMpiMyself = RMF_GetMpiMyself(id) -END FUNCTION RM_GetMpiMyself - -!> Returns the number of MPI processes (tasks) assigned to the reaction module. -!> For the OPENMP version, the number of tasks is always -!> one (although there may be multiple threads, @ref RM_GetThreadCount), -!> and the task number returned by @ref RM_GetMpiMyself is zero. For the MPI version, the number of -!> tasks and computer hosts are determined at run time by the mpiexec command. An MPI communicator -!> is used in constructing reaction modules for MPI. The communicator may define a subset of the -!> total number of MPI processes. -!> The root task number is zero, and all workers have a task number greater than zero. -!> @param id The instance @a id returned from @ref RM_Create. -!> @retval The number of MPI processes assigned to the reaction module, -!> negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_GetMpiMyself, -!> @ref RM_Create. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> mpi_tasks = RM_GetMpiTasks(id)
-!> write(string1, "(A,I)") "Number of MPI processes: ", mpi_tasks
-!> status = RM_OutputMessage(id, string1)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root and (or) workers. - -INTEGER FUNCTION RM_GetMpiTasks(id) + END FUNCTION RM_GetMpiMyself + + !> Returns the number of MPI processes (tasks) assigned to the reaction module. + !> For the OPENMP version, the number of tasks is always + !> one (although there may be multiple threads, @ref RM_GetThreadCount), + !> and the task number returned by @ref RM_GetMpiMyself is zero. For the MPI version, the number of + !> tasks and computer hosts are determined at run time by the mpiexec command. An MPI communicator + !> is used in constructing reaction modules for MPI. The communicator may define a subset of the + !> total number of MPI processes. + !> The root task number is zero, and all workers have a task number greater than zero. + !> @param id The instance @a id returned from @ref RM_Create. + !> @retval The number of MPI processes assigned to the reaction module, + !> negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_GetMpiMyself, + !> @ref RM_Create. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> mpi_tasks = RM_GetMpiTasks(id)
+    !> write(string1, "(A,I)") "Number of MPI processes: ", mpi_tasks
+    !> status = RM_OutputMessage(id, string1)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root and (or) workers. + + INTEGER FUNCTION RM_GetMpiTasks(id) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_GetMpiTasks(id) & - BIND(C, NAME='RMF_GetMpiTasks') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - END FUNCTION RMF_GetMpiTasks + INTEGER(KIND=C_INT) FUNCTION RMF_GetMpiTasks(id) & + BIND(C, NAME='RMF_GetMpiTasks') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + END FUNCTION RMF_GetMpiTasks END INTERFACE INTEGER, INTENT(in) :: id RM_GetMpiTasks = RMF_GetMpiTasks(id) -END FUNCTION RM_GetMpiTasks - -!> Returns the user number for the @a nth selected-output definition. -!> Definitions are sorted by user number. Phreeqc allows multiple selected-output -!> definitions, each of which is assigned a nonnegative integer identifier by the -!> user. The number of definitions can be obtained by @ref RM_GetSelectedOutputCount. -!> To cycle through all of the definitions, RM_GetNthSelectedOutputUserNumber -!> can be used to identify the user number for each selected-output definition -!> in sequence. @ref RM_SetCurrentSelectedOutputUserNumber is then used to select -!> that user number for selected-output processing. -!> @param id The instance @a id returned from @ref RM_Create. -!> @param n The sequence number of the selected-output definition for which the user number will be returned. -!> Fortran, 1 based. -!> @retval The user number of the @a nth selected-output definition, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_GetCurrentSelectedOutputUserNumber, -!> @ref RM_GetSelectedOutput, -!> @ref RM_GetSelectedOutputColumnCount, -!> @ref RM_GetSelectedOutputCount, -!> @ref RM_GetSelectedOutputHeading, -!> @ref RM_GetSelectedOutputRowCount, -!> @ref RM_SetCurrentSelectedOutputUserNumber, -!> @ref RM_SetNthSelectedOutput, -!> @ref RM_SetSelectedOutputOn. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> do isel = 1, RM_GetSelectedOutputCount(id)
-!>   n_user = RM_GetNthSelectedOutputUserNumber(id, isel)
-!>   status = RM_SetCurrentSelectedOutputUserNumber(id, n_user)
-!>   write(*,*) "Selected output sequence number: ", isel)
-!>   write(*,*) "Selected output user number:     ", n_user)
-!>   col = RM_GetSelectedOutputColumnCount(id)
-!>   allocate(selected_out(nxyz,col))
-!>   status = RM_GetSelectedOutput(id, selected_out)
-!>   ! Process results here
-!>   deallocate(selected_out)
-!> enddo
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root. - -INTEGER FUNCTION RM_GetNthSelectedOutputUserNumber(id, n) + END FUNCTION RM_GetMpiTasks + + !> Returns the user number for the @a nth selected-output definition. + !> Definitions are sorted by user number. Phreeqc allows multiple selected-output + !> definitions, each of which is assigned a nonnegative integer identifier by the + !> user. The number of definitions can be obtained by @ref RM_GetSelectedOutputCount. + !> To cycle through all of the definitions, RM_GetNthSelectedOutputUserNumber + !> can be used to identify the user number for each selected-output definition + !> in sequence. @ref RM_SetCurrentSelectedOutputUserNumber is then used to select + !> that user number for selected-output processing. + !> @param id The instance @a id returned from @ref RM_Create. + !> @param n The sequence number of the selected-output definition for which the user number will be returned. + !> Fortran, 1 based. + !> @retval The user number of the @a nth selected-output definition, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_GetCurrentSelectedOutputUserNumber, + !> @ref RM_GetSelectedOutput, + !> @ref RM_GetSelectedOutputColumnCount, + !> @ref RM_GetSelectedOutputCount, + !> @ref RM_GetSelectedOutputHeading, + !> @ref RM_GetSelectedOutputRowCount, + !> @ref RM_SetCurrentSelectedOutputUserNumber, + !> @ref RM_SetNthSelectedOutput, + !> @ref RM_SetSelectedOutputOn. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> do isel = 1, RM_GetSelectedOutputCount(id)
+    !>   n_user = RM_GetNthSelectedOutputUserNumber(id, isel)
+    !>   status = RM_SetCurrentSelectedOutputUserNumber(id, n_user)
+    !>   write(*,*) "Selected output sequence number: ", isel)
+    !>   write(*,*) "Selected output user number:     ", n_user)
+    !>   col = RM_GetSelectedOutputColumnCount(id)
+    !>   allocate(selected_out(nxyz,col))
+    !>   status = RM_GetSelectedOutput(id, selected_out)
+    !>   ! Process results here
+    !>   deallocate(selected_out)
+    !> enddo
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root. + + INTEGER FUNCTION RM_GetNthSelectedOutputUserNumber(id, n) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_GetNthSelectedOutputUserNumber(id, n) & - BIND(C, NAME='RMF_GetNthSelectedOutputUserNumber') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id, n - END FUNCTION RMF_GetNthSelectedOutputUserNumber + INTEGER(KIND=C_INT) FUNCTION RMF_GetNthSelectedOutputUserNumber(id, n) & + BIND(C, NAME='RMF_GetNthSelectedOutputUserNumber') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id, n + END FUNCTION RMF_GetNthSelectedOutputUserNumber END INTERFACE INTEGER, INTENT(in) :: id, n - RM_GetNthSelectedOutputUserNumber = RMF_GetNthSelectedOutputUserNumber(id, n) -END FUNCTION RM_GetNthSelectedOutputUserNumber - -!> Returns a vector of saturations (@a sat_calc) as calculated by the reaction module. -!> Reactions will change the volume of solution in a cell. -!> The transport code must decide whether to ignore or account for this change in solution volume due to reactions. -!> Following reactions, the cell saturation is calculated as solution volume (@ref RM_GetSolutionVolume) -!> divided by the product of representative volume (@ref RM_SetRepresentativeVolume) and the porosity (@ref RM_SetPorosity). -!> The cell saturation returned by @a RM_GetSaturation may be less than or greater than the saturation set by the transport code -!> (@ref RM_SetSaturation), and may be greater than or less than 1.0, even in fully saturated simulations. -!> Only the following databases distributed with PhreeqcRM have molar volume information needed -!> to accurately calculate solution volume and saturation: phreeqc.dat, Amm.dat, and pitzer.dat. -!> -!> @param id The instance @a id returned from @ref RM_Create. -!> @param sat_calc Vector to receive the saturations. Dimension of the array is set to @a nxyz, -!> where @a nxyz is the number of user grid cells (@ref RM_GetGridCellCount). -!> Values for inactive cells are set to 1e30. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> -!> @see -!> @ref RM_GetSolutionVolume, -!> @ref RM_SetPorosity, -!> @ref RM_SetRepresentativeVolume, -!> @ref RM_SetSaturation. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> allocate(sat_calc(nxyz))
-!> status = RM_RunCells(id)
-!> status = RM_GetSaturation(id, sat_calc)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root, workers must be in the loop of @ref RM_MpiWorker. + RM_GetNthSelectedOutputUserNumber = RMF_GetNthSelectedOutputUserNumber(id, n-1) + END FUNCTION RM_GetNthSelectedOutputUserNumber + + !> Transfer current porosities to the array given in the argument list (@a porosity). + !> Porosity is not changed by PhreeqcRM; the values are either the default values + !> or the values set by the last call to @ref RM_SetPorosity. + !> + !> @param id The instance @a id returned from @ref RM_Create. + !> @param porosity Array to receive the porosities. Dimension of the array is @a nxyz, + !> where @a nxyz is the number of user grid cells (@ref RM_GetGridCellCount). Values for inactive cells are set to 1e30. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> allocate(porosity(nxyz))
+    !> status = RM_GetPorosity(id, porosity)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root. + + INTEGER FUNCTION RM_GetPorosity(id, porosity) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION RMF_GetPorosity(id, porosity) & + BIND(C, NAME='RMF_GetPorosity') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + REAL(KIND=C_DOUBLE), INTENT(out) :: porosity(*) + END FUNCTION RMF_GetPorosity + END INTERFACE + INTEGER, INTENT(in) :: id + real(kind=8), INTENT(out), dimension(:) :: porosity + if (rmf_debug) call Chk_GetPorosity(id, porosity) + RM_GetPorosity = RMF_GetPorosity(id, porosity) + return + END FUNCTION RM_GetPorosity + + !> Transfer current pressures to the array given in the argument list (@a pressure). + !> Pressure is not usually calculated by PhreeqcRM; the values are either the default values + !> or the values set by the last call to @ref RM_SetPressure. Pressures can be calculated + !> by PhreeqcRM if a fixed-volume GAS_PHASE is used. + !> + !> @param id The instance @a id returned from @ref RM_Create. + !> @param pressure Array to receive the porosities. Dimension of the array is @a nxyz, + !> where @a nxyz is the number of user grid cells (@ref RM_GetGridCellCount). Values for inactive cells are set to 1e30. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> allocate(pressure(nxyz))
+    !> status = RM_GetPressure(id, pressure)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root. + + INTEGER FUNCTION RM_GetPressure(id, pressure) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION RMF_GetPressure(id, pressure) & + BIND(C, NAME='RMF_GetPressure') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + REAL(KIND=C_DOUBLE), INTENT(out) :: pressure(*) + END FUNCTION RMF_GetPressure + END INTERFACE + INTEGER, INTENT(in) :: id + real(kind=8), INTENT(out), dimension(:) :: pressure + if (rmf_debug) call Chk_GetPressure(id, pressure) + RM_GetPressure = RMF_GetPressure(id, pressure) + return + END FUNCTION RM_GetPressure -INTEGER FUNCTION RM_GetSaturation(id, sat_calc) + SUBROUTINE Chk_GetPressure(id, pressure) + IMPLICIT NONE + INTEGER, INTENT(in) :: id + real(kind=8), INTENT(in), DIMENSION(:) :: pressure + INTEGER :: errors + errors = 0 + errors = errors + Chk_Double1D(id, pressure, rmf_nxyz, "pressure", "RM_GetPressure") + if (errors .gt. 0) then + errors = RM_Abort(id, -3, "Invalid argument in RM_GetPressure") + endif + END SUBROUTINE Chk_GetPressure + + SUBROUTINE Chk_GetPorosity(id, porosity) + IMPLICIT NONE + INTEGER, INTENT(in) :: id + real(kind=8), INTENT(in), DIMENSION(:) :: porosity + INTEGER :: errors + errors = 0 + errors = errors + Chk_Double1D(id, porosity, rmf_nxyz, "porosity", "RM_GetPorosity") + if (errors .gt. 0) then + errors = RM_Abort(id, -3, "Invalid argument in RM_GetPorosity") + endif + END SUBROUTINE Chk_GetPorosity + + !> Returns a vector of saturations (@a sat_calc) as calculated by the reaction module. + !> Reactions will change the volume of solution in a cell. + !> This method always returns solution_volume/(rv * porosity); the method + !> @ref RM_SetSaturation has no effect on the values returned. + !> The transport code must decide whether to ignore or account for this change in solution volume due to reactions. + !> Following reactions, the cell saturation is calculated as solution volume (@ref RM_GetSolutionVolume) + !> divided by the product of representative volume (@ref RM_SetRepresentativeVolume) and the porosity (@ref RM_SetPorosity). + !> The cell saturation returned by @a RM_GetSaturation may be less than or greater than the saturation set by the transport code + !> (@ref RM_SetSaturation), and may be greater than or less than 1.0, even in fully saturated simulations. + !> Only the following databases distributed with PhreeqcRM have molar volume information needed + !> to accurately calculate solution volume and saturation: phreeqc.dat, Amm.dat, and pitzer.dat. + !> + !> @param id The instance @a id returned from @ref RM_Create. + !> @param sat_calc Vector to receive the saturations. Dimension of the array is set to @a nxyz, + !> where @a nxyz is the number of user grid cells (@ref RM_GetGridCellCount). + !> Values for inactive cells are set to 1e30. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> + !> @see + !> @ref RM_GetSolutionVolume, + !> @ref RM_SetPorosity, + !> @ref RM_SetRepresentativeVolume, + !> @ref RM_SetSaturation. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> allocate(sat_calc(nxyz))
+    !> status = RM_RunCells(id)
+    !> status = RM_GetSaturation(id, sat_calc)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref RM_MpiWorker. + + INTEGER FUNCTION RM_GetSaturation(id, sat_calc) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_GetSaturation(id, sat_calc) & - BIND(C, NAME='RMF_GetSaturation') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - REAL(KIND=C_DOUBLE), INTENT(out) :: sat_calc(*) - END FUNCTION RMF_GetSaturation + INTEGER(KIND=C_INT) FUNCTION RMF_GetSaturation(id, sat_calc) & + BIND(C, NAME='RMF_GetSaturation') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + REAL(KIND=C_DOUBLE), INTENT(out) :: sat_calc(*) + END FUNCTION RMF_GetSaturation END INTERFACE INTEGER, INTENT(in) :: id - DOUBLE PRECISION, INTENT(out), DIMENSION(:) :: sat_calc + real(kind=8), INTENT(out), DIMENSION(:) :: sat_calc if (rmf_debug) call Chk_GetSaturation(id, sat_calc) RM_GetSaturation = RMF_GetSaturation(id, sat_calc) -END FUNCTION RM_GetSaturation + END FUNCTION RM_GetSaturation -SUBROUTINE Chk_GetSaturation(id, sat) + SUBROUTINE Chk_GetSaturation(id, sat) IMPLICIT NONE INTEGER, INTENT(in) :: id - DOUBLE PRECISION, INTENT(in), DIMENSION(:) :: sat + real(kind=8), INTENT(in), DIMENSION(:) :: sat INTEGER :: errors errors = 0 errors = errors + Chk_Double1D(id, sat, rmf_nxyz, "saturation", "RM_GetSaturation") if (errors .gt. 0) then errors = RM_Abort(id, -3, "Invalid argument in RM_GetSaturation") endif -END SUBROUTINE Chk_GetSaturation - -!> Populates an array with values from the current selected-output definition. @ref RM_SetCurrentSelectedOutputUserNumber -!> determines which of the selected-output definitions is used to populate the array. -!> @param id The instance @a id returned from @ref RM_Create. -!> @param so An array to contain the selected-output values. Size of the array is (@a nxyz, @a col), -!> where @a nxyz is the number of grid cells in the user's model (@ref RM_GetGridCellCount), and @a col is the number of -!> columns in the selected-output definition (@ref RM_GetSelectedOutputColumnCount). -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_GetCurrentSelectedOutputUserNumber, -!> @ref RM_GetNthSelectedOutputUserNumber, -!> @ref RM_GetSelectedOutputColumnCount, -!> @ref RM_GetSelectedOutputCount, -!> @ref RM_GetSelectedOutputHeading, -!> @ref RM_GetSelectedOutputRowCount, -!> @ref RM_SetCurrentSelectedOutputUserNumber, -!> @ref RM_SetNthSelectedOutput, -!> @ref RM_SetSelectedOutputOn. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> do isel = 1, RM_GetSelectedOutputCount(id)
-!>   n_user = RM_GetNthSelectedOutputUserNumber(id, isel)
-!>   status = RM_SetCurrentSelectedOutputUserNumber(id, n_user)
-!>   col = RM_GetSelectedOutputColumnCount(id)
-!>   allocate(selected_out(nxyz,col))
-!>   status = RM_GetSelectedOutput(id, selected_out)
-!>   ! Process results here
-!>   deallocate(selected_out)
-!> enddo
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root, workers must be in the loop of @ref RM_MpiWorker. - -INTEGER FUNCTION RM_GetSelectedOutput(id, so) + END SUBROUTINE Chk_GetSaturation + + !> Populates an array with values from the current selected-output definition. @ref RM_SetCurrentSelectedOutputUserNumber + !> determines which of the selected-output definitions is used to populate the array. + !> @param id The instance @a id returned from @ref RM_Create. + !> @param so An array to contain the selected-output values. Size of the array is (@a nxyz, @a col), + !> where @a nxyz is the number of grid cells in the user's model (@ref RM_GetGridCellCount), and @a col is the number of + !> columns in the selected-output definition (@ref RM_GetSelectedOutputColumnCount). + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_GetCurrentSelectedOutputUserNumber, + !> @ref RM_GetNthSelectedOutputUserNumber, + !> @ref RM_GetSelectedOutputColumnCount, + !> @ref RM_GetSelectedOutputCount, + !> @ref RM_GetSelectedOutputHeading, + !> @ref RM_GetSelectedOutputRowCount, + !> @ref RM_SetCurrentSelectedOutputUserNumber, + !> @ref RM_SetNthSelectedOutput, + !> @ref RM_SetSelectedOutputOn. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> do isel = 1, RM_GetSelectedOutputCount(id)
+    !>   n_user = RM_GetNthSelectedOutputUserNumber(id, isel)
+    !>   status = RM_SetCurrentSelectedOutputUserNumber(id, n_user)
+    !>   col = RM_GetSelectedOutputColumnCount(id)
+    !>   allocate(selected_out(nxyz,col))
+    !>   status = RM_GetSelectedOutput(id, selected_out)
+    !>   ! Process results here
+    !>   deallocate(selected_out)
+    !> enddo
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref RM_MpiWorker. + + INTEGER FUNCTION RM_GetSelectedOutput(id, so) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_GetSelectedOutput(id, so) & - BIND(C, NAME='RMF_GetSelectedOutput') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - REAL(KIND=C_DOUBLE), INTENT(out) :: so(*) - END FUNCTION RMF_GetSelectedOutput + INTEGER(KIND=C_INT) FUNCTION RMF_GetSelectedOutput(id, so) & + BIND(C, NAME='RMF_GetSelectedOutput') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + REAL(KIND=C_DOUBLE), INTENT(out) :: so(*) + END FUNCTION RMF_GetSelectedOutput END INTERFACE INTEGER, INTENT(in) :: id - DOUBLE PRECISION, DIMENSION(:,:), INTENT(out) :: so + real(kind=8), DIMENSION(:,:), INTENT(out) :: so if (rmf_debug) call Chk_GetSelectedOutput(id, so) RM_GetSelectedOutput = RMF_GetSelectedOutput(id, so) -END FUNCTION RM_GetSelectedOutput - -SUBROUTINE Chk_GetSelectedOutput(id, so) + END FUNCTION RM_GetSelectedOutput + + SUBROUTINE Chk_GetSelectedOutput(id, so) IMPLICIT NONE INTEGER, INTENT(in) :: id - DOUBLE PRECISION, INTENT(in), DIMENSION(:,:) :: so + real(kind=8), INTENT(in), DIMENSION(:,:) :: so INTEGER :: errors, ncol ncol = RM_GetSelectedOutputColumnCount(id) errors = 0 @@ -2176,560 +2390,619 @@ SUBROUTINE Chk_GetSelectedOutput(id, so) if (errors .gt. 0) then errors = RM_Abort(id, -3, "Invalid argument in RM_GetSelectedOutput") endif -END SUBROUTINE Chk_GetSelectedOutput - -!> Returns the number of columns in the current selected-output definition. @ref RM_SetCurrentSelectedOutputUserNumber -!> determines which of the selected-output definitions is used. -!> @param id The instance @a id returned from @ref RM_Create. -!> @retval Number of columns in the current selected-output definition, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_GetCurrentSelectedOutputUserNumber, -!> @ref RM_GetNthSelectedOutputUserNumber, -!> @ref RM_GetSelectedOutput, -!> @ref RM_GetSelectedOutputCount, -!> @ref RM_GetSelectedOutputHeading, -!> @ref RM_GetSelectedOutputRowCount, -!> @ref RM_SetCurrentSelectedOutputUserNumber, -!> @ref RM_SetNthSelectedOutput, -!> @ref RM_SetSelectedOutputOn. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> do isel = 1, RM_GetSelectedOutputCount(id)
-!>   n_user = RM_GetNthSelectedOutputUserNumber(id, isel)
-!>   status = RM_SetCurrentSelectedOutputUserNumber(id, n_user)
-!>   col = RM_GetSelectedOutputColumnCount(id)
-!>   allocate(selected_out(nxyz,col))
-!>   status = RM_GetSelectedOutput(id, selected_out)
-!>   ! Process results here
-!>   deallocate(selected_out)
-!> enddo
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root. - -INTEGER FUNCTION RM_GetSelectedOutputColumnCount(id) + END SUBROUTINE Chk_GetSelectedOutput + + !> Returns the number of columns in the current selected-output definition. @ref RM_SetCurrentSelectedOutputUserNumber + !> determines which of the selected-output definitions is used. + !> @param id The instance @a id returned from @ref RM_Create. + !> @retval Number of columns in the current selected-output definition, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_GetCurrentSelectedOutputUserNumber, + !> @ref RM_GetNthSelectedOutputUserNumber, + !> @ref RM_GetSelectedOutput, + !> @ref RM_GetSelectedOutputCount, + !> @ref RM_GetSelectedOutputHeading, + !> @ref RM_GetSelectedOutputRowCount, + !> @ref RM_SetCurrentSelectedOutputUserNumber, + !> @ref RM_SetNthSelectedOutput, + !> @ref RM_SetSelectedOutputOn. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> do isel = 1, RM_GetSelectedOutputCount(id)
+    !>   n_user = RM_GetNthSelectedOutputUserNumber(id, isel)
+    !>   status = RM_SetCurrentSelectedOutputUserNumber(id, n_user)
+    !>   col = RM_GetSelectedOutputColumnCount(id)
+    !>   allocate(selected_out(nxyz,col))
+    !>   status = RM_GetSelectedOutput(id, selected_out)
+    !>   ! Process results here
+    !>   deallocate(selected_out)
+    !> enddo
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root. + + INTEGER FUNCTION RM_GetSelectedOutputColumnCount(id) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_GetSelectedOutputColumnCount(id) & - BIND(C, NAME='RMF_GetSelectedOutputColumnCount') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - END FUNCTION RMF_GetSelectedOutputColumnCount + INTEGER(KIND=C_INT) FUNCTION RMF_GetSelectedOutputColumnCount(id) & + BIND(C, NAME='RMF_GetSelectedOutputColumnCount') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + END FUNCTION RMF_GetSelectedOutputColumnCount END INTERFACE INTEGER, INTENT(in) :: id RM_GetSelectedOutputColumnCount = RMF_GetSelectedOutputColumnCount(id) -END FUNCTION RM_GetSelectedOutputColumnCount - -!> Returns the number of selected-output definitions. @ref RM_SetCurrentSelectedOutputUserNumber -!> determines which of the selected-output definitions is used. -!> @param id The instance @a id returned from @ref RM_Create. -!> @retval Number of selected-output definitions, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_GetCurrentSelectedOutputUserNumber, -!> @ref RM_GetNthSelectedOutputUserNumber, -!> @ref RM_GetSelectedOutput, -!> @ref RM_GetSelectedOutputColumnCount, -!> @ref RM_GetSelectedOutputHeading, -!> @ref RM_GetSelectedOutputRowCount, -!> @ref RM_SetCurrentSelectedOutputUserNumber, -!> @ref RM_SetNthSelectedOutput, -!> @ref RM_SetSelectedOutputOn. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> do isel = 1, RM_GetSelectedOutputCount(id)
-!>   n_user = RM_GetNthSelectedOutputUserNumber(id, isel)
-!>   status = RM_SetCurrentSelectedOutputUserNumber(id, n_user)
-!>   col = RM_GetSelectedOutputColumnCount(id)
-!>   allocate(selected_out(nxyz,col))
-!>   status = RM_GetSelectedOutput(id, selected_out)
-!>   ! Process results here
-!>   deallocate(selected_out)
-!> enddo
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root. - -INTEGER FUNCTION RM_GetSelectedOutputCount(id) + END FUNCTION RM_GetSelectedOutputColumnCount + + !> Returns the number of selected-output definitions. @ref RM_SetCurrentSelectedOutputUserNumber + !> determines which of the selected-output definitions is used. + !> @param id The instance @a id returned from @ref RM_Create. + !> @retval Number of selected-output definitions, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_GetCurrentSelectedOutputUserNumber, + !> @ref RM_GetNthSelectedOutputUserNumber, + !> @ref RM_GetSelectedOutput, + !> @ref RM_GetSelectedOutputColumnCount, + !> @ref RM_GetSelectedOutputHeading, + !> @ref RM_GetSelectedOutputRowCount, + !> @ref RM_SetCurrentSelectedOutputUserNumber, + !> @ref RM_SetNthSelectedOutput, + !> @ref RM_SetSelectedOutputOn. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> do isel = 1, RM_GetSelectedOutputCount(id)
+    !>   n_user = RM_GetNthSelectedOutputUserNumber(id, isel)
+    !>   status = RM_SetCurrentSelectedOutputUserNumber(id, n_user)
+    !>   col = RM_GetSelectedOutputColumnCount(id)
+    !>   allocate(selected_out(nxyz,col))
+    !>   status = RM_GetSelectedOutput(id, selected_out)
+    !>   ! Process results here
+    !>   deallocate(selected_out)
+    !> enddo
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root. + + INTEGER FUNCTION RM_GetSelectedOutputCount(id) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_GetSelectedOutputCount(id) & - BIND(C, NAME='RMF_GetSelectedOutputCount') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - END FUNCTION RMF_GetSelectedOutputCount + INTEGER(KIND=C_INT) FUNCTION RMF_GetSelectedOutputCount(id) & + BIND(C, NAME='RMF_GetSelectedOutputCount') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + END FUNCTION RMF_GetSelectedOutputCount END INTERFACE INTEGER, INTENT(in) :: id RM_GetSelectedOutputCount = RMF_GetSelectedOutputCount(id) -END FUNCTION RM_GetSelectedOutputCount - -!> Returns a selected output heading. The number of headings is determined by @ref RM_GetSelectedOutputColumnCount. -!> @ref RM_SetCurrentSelectedOutputUserNumber -!> determines which of the selected-output definitions is used. -!> @param id The instance @a id returned from @ref RM_Create. -!> @param icol The sequence number of the heading to be retrieved. Fortran, 1 based. -!> @param heading A string buffer to receive the heading. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_GetCurrentSelectedOutputUserNumber, -!> @ref RM_GetNthSelectedOutputUserNumber, -!> @ref RM_GetSelectedOutput, -!> @ref RM_GetSelectedOutputColumnCount, -!> @ref RM_GetSelectedOutputCount, -!> @ref RM_GetSelectedOutputRowCount, -!> @ref RM_SetCurrentSelectedOutputUserNumber, -!> @ref RM_SetNthSelectedOutput, -!> @ref RM_SetSelectedOutputOn. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> do isel = 1, RM_GetSelectedOutputCount(id)
-!>   n_user = RM_GetNthSelectedOutputUserNumber(id, isel)
-!>   status = RM_SetCurrentSelectedOutputUserNumber(id, n_user)
-!>   col = RM_GetSelectedOutputColumnCount(id)
-!>   do j = 1, col
-!>     status = RM_GetSelectedOutputHeading(id, j, heading)
-!>     write(*,'(10x,i2,A2,A10,A2,f10.4)') j, " ", trim(heading)
-!>   enddo
-!> enddo
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root. - -INTEGER FUNCTION RM_GetSelectedOutputHeading(id, icol, heading) + END FUNCTION RM_GetSelectedOutputCount + + !> Returns a selected output heading. The number of headings is determined by @ref RM_GetSelectedOutputColumnCount. + !> @ref RM_SetCurrentSelectedOutputUserNumber + !> determines which of the selected-output definitions is used. + !> @param id The instance @a id returned from @ref RM_Create. + !> @param icol The sequence number of the heading to be retrieved. Fortran, 1 based. + !> @param heading A string buffer to receive the heading. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_GetCurrentSelectedOutputUserNumber, + !> @ref RM_GetNthSelectedOutputUserNumber, + !> @ref RM_GetSelectedOutput, + !> @ref RM_GetSelectedOutputColumnCount, + !> @ref RM_GetSelectedOutputCount, + !> @ref RM_GetSelectedOutputRowCount, + !> @ref RM_SetCurrentSelectedOutputUserNumber, + !> @ref RM_SetNthSelectedOutput, + !> @ref RM_SetSelectedOutputOn. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> do isel = 1, RM_GetSelectedOutputCount(id)
+    !>   n_user = RM_GetNthSelectedOutputUserNumber(id, isel)
+    !>   status = RM_SetCurrentSelectedOutputUserNumber(id, n_user)
+    !>   col = RM_GetSelectedOutputColumnCount(id)
+    !>   do j = 1, col
+    !>     status = RM_GetSelectedOutputHeading(id, j, heading)
+    !>     write(*,'(10x,i2,A2,A10,A2,f10.4)') j, " ", trim(heading)
+    !>   enddo
+    !> enddo
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root. + + INTEGER FUNCTION RM_GetSelectedOutputHeading(id, icol, heading) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_GetSelectedOutputHeading(id, icol, heading, l) & - BIND(C, NAME='RMF_GetSelectedOutputHeading') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id, icol, l - CHARACTER(KIND=C_CHAR), INTENT(out) :: heading(*) - END FUNCTION RMF_GetSelectedOutputHeading + INTEGER(KIND=C_INT) FUNCTION RMF_GetSelectedOutputHeading(id, icol, heading, l) & + BIND(C, NAME='RMF_GetSelectedOutputHeading') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id, icol, l + CHARACTER(KIND=C_CHAR), INTENT(out) :: heading(*) + END FUNCTION RMF_GetSelectedOutputHeading END INTERFACE INTEGER, INTENT(in) :: id, icol CHARACTER(len=*), INTENT(out) :: heading RM_GetSelectedOutputHeading = RMF_GetSelectedOutputHeading(id, icol, heading, len(heading)) -END FUNCTION RM_GetSelectedOutputHeading - -!> Returns the number of rows in the current selected-output definition. However, the method -!> is included only for convenience; the number of rows is always equal to the number of -!> grid cells in the user's model, and is equal to @ref RM_GetGridCellCount. -!> @param id The instance @a id returned from @ref RM_Create. -!> @retval Number of rows in the current selected-output definition, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_GetCurrentSelectedOutputUserNumber, -!> @ref RM_GetNthSelectedOutputUserNumber, -!> @ref RM_GetSelectedOutput, -!> @ref RM_GetSelectedOutputColumnCount, -!> @ref RM_GetSelectedOutputCount, -!> @ref RM_GetSelectedOutputHeading, -!> @ref RM_SetCurrentSelectedOutputUserNumber, -!> @ref RM_SetNthSelectedOutput, -!> @ref RM_SetSelectedOutputOn. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> do isel = 1, RM_GetSelectedOutputCount(id)
-!>   n_user = RM_GetNthSelectedOutputUserNumber(id, isel)
-!>   status = RM_SetCurrentSelectedOutputUserNumber(id, n_user)
-!>   col = RM_GetSelectedOutputColumnCount(id)
-!>   allocate(selected_out(nxyz,col))
-!>   status = RM_GetSelectedOutput(id, selected_out)
-!>   ! Print results
-!>   do i = 1, RM_GetSelectedOutputRowCount(id)
-!>     write(*,*) "Cell number ", i
-!>     write(*,*) "     Selected output: "
-!>     do j = 1, col
-!>       status = RM_GetSelectedOutputHeading(id, j, heading)
-!>       write(*,'(10x,i2,A2,A10,A2,f10.4)') j, " ", trim(heading),": ", selected_out(i,j)
-!>     enddo
-!>   enddo
-!>   deallocate(selected_out)
-!> enddo
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root. - -INTEGER FUNCTION RM_GetSelectedOutputRowCount(id) + END FUNCTION RM_GetSelectedOutputHeading + + !> Returns the selected-output headings for the current selected-output file. + !> @ref RM_SetCurrentSelectedOutputUserNumber or @ref RM_SetNthSelectedOutput + !> determine which of the selected-output definitions is used. + !> @param id The instance @a id returned from @ref RM_Create. + !> @param headings A deferred length, allocatable, 1D character variable. + !> to receive the headings. Character length and dimension will be allocated as needed. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref bmif_get_value, + !> @ref bmif_set_value, + !> @ref RM_GetCurrentSelectedOutputUserNumber, + !> @ref RM_GetNthSelectedOutputUserNumber, + !> @ref RM_GetSelectedOutput, + !> @ref RM_GetSelectedOutputColumnCount, + !> @ref RM_GetSelectedOutputCount, + !> @ref RM_GetSelectedOutputHeading, + !> @ref RM_GetSelectedOutputRowCount, + !> @ref RM_SetCurrentSelectedOutputUserNumber, + !> @ref RM_SetNthSelectedOutput, + !> @ref RM_SetSelectedOutputOn. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> character(len=:), allocatable, dimension(:) :: headings
+    !> do isel = 1, RM_GetSelectedOutputCount(id)
+    !>   status = RM_SetNthSelectedOutput(id, isel)
+    !>   status = RM_GetSelectedOutputHeadings(id, headings)
+    !> enddo
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root. + + INTEGER FUNCTION RM_GetSelectedOutputHeadings(id, dest) + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER, INTENT(in) :: id + CHARACTER(len=:), allocatable, dimension(:), INTENT(inout) :: dest + character(1024) :: head + integer :: dim, itemsize, status, l, i + dim = RM_GetSelectedOutputColumnCount(id) + itemsize = 0 + do i = 1, dim + status = RM_GetSelectedOutputHeading(id, i, head) + l = len(trim(head)) + if (l > itemsize) itemsize = l + enddo + if(allocated(dest)) deallocate(dest) + allocate(character(len=itemsize) :: dest(dim)) + do i = 1, dim + status = RM_GetSelectedOutputHeading(id, i, head) + dest(i) = trim(head) + enddo + RM_GetSelectedOutputHeadings = status + return + END FUNCTION RM_GetSelectedOutputHeadings + + !> Returns the number of rows in the current selected-output definition. However, the method + !> is included only for convenience; the number of rows is always equal to the number of + !> grid cells in the user's model, and is equal to @ref RM_GetGridCellCount. + !> @param id The instance @a id returned from @ref RM_Create. + !> @retval Number of rows in the current selected-output definition, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_GetCurrentSelectedOutputUserNumber, + !> @ref RM_GetNthSelectedOutputUserNumber, + !> @ref RM_GetSelectedOutput, + !> @ref RM_GetSelectedOutputColumnCount, + !> @ref RM_GetSelectedOutputCount, + !> @ref RM_GetSelectedOutputHeading, + !> @ref RM_SetCurrentSelectedOutputUserNumber, + !> @ref RM_SetNthSelectedOutput, + !> @ref RM_SetSelectedOutputOn. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> do isel = 1, RM_GetSelectedOutputCount(id)
+    !>   n_user = RM_GetNthSelectedOutputUserNumber(id, isel)
+    !>   status = RM_SetCurrentSelectedOutputUserNumber(id, n_user)
+    !>   col = RM_GetSelectedOutputColumnCount(id)
+    !>   allocate(selected_out(nxyz,col))
+    !>   status = RM_GetSelectedOutput(id, selected_out)
+    !>   ! Print results
+    !>   do i = 1, RM_GetSelectedOutputRowCount(id)
+    !>     write(*,*) "Cell number ", i
+    !>     write(*,*) "     Selected output: "
+    !>     do j = 1, col
+    !>       status = RM_GetSelectedOutputHeading(id, j, heading)
+    !>       write(*,'(10x,i2,A2,A10,A2,f10.4)') j, " ", trim(heading),": ", selected_out(i,j)
+    !>     enddo
+    !>   enddo
+    !>   deallocate(selected_out)
+    !> enddo
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root. + + INTEGER FUNCTION RM_GetSelectedOutputRowCount(id) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_GetSelectedOutputRowCount(id) & - BIND(C, NAME='RMF_GetSelectedOutputRowCount') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - END FUNCTION RMF_GetSelectedOutputRowCount + INTEGER(KIND=C_INT) FUNCTION RMF_GetSelectedOutputRowCount(id) & + BIND(C, NAME='RMF_GetSelectedOutputRowCount') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + END FUNCTION RMF_GetSelectedOutputRowCount END INTERFACE INTEGER, INTENT(in) :: id RM_GetSelectedOutputRowCount = RMF_GetSelectedOutputRowCount(id) -END FUNCTION RM_GetSelectedOutputRowCount -!> Returns the number of phases in the initial-phreeqc module for which saturation indices can be calculated. -!> @ref RM_FindComponents must be called before @ref RM_GetSICount. -!> This method may be useful when generating selected output definitions related to -!> saturation indices. -!> @param id The instance @a id returned from @ref RM_Create. -!> @retval The number of phases in the initial-phreeqc module for which saturation indices -!> could be calculated. -!> @see -!> @ref RM_FindComponents, -!> @ref RM_GetSIName. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> input = trim(input) // "  -si "// new_line(c)
-!> do i = 1, RM_GetSICount(id)
-!>   status = RM_GetSIName(id, i, line)
-!>   input = trim(input) // "    " // line // new_line(c)
-!> enddo 
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root. - -INTEGER FUNCTION RM_GetSICount(id) + END FUNCTION RM_GetSelectedOutputRowCount + !> Returns the number of phases in the initial-phreeqc module for which saturation indices can be calculated. + !> @ref RM_FindComponents must be called before @ref RM_GetSICount. + !> This method may be useful when generating selected output definitions related to + !> saturation indices. + !> @param id The instance @a id returned from @ref RM_Create. + !> @retval The number of phases in the initial-phreeqc module for which saturation indices + !> could be calculated. + !> @see + !> @ref RM_FindComponents, + !> @ref RM_GetSIName. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> input = trim(input) // "  -si "// new_line(c)
+    !> do i = 1, RM_GetSICount(id)
+    !>   status = RM_GetSIName(id, i, line)
+    !>   input = trim(input) // "    " // line // new_line(c)
+    !> enddo
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root. + + INTEGER FUNCTION RM_GetSICount(id) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_GetSICount(id) & - BIND(C, NAME='RMF_GetSICount') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - END FUNCTION RMF_GetSICount + INTEGER(KIND=C_INT) FUNCTION RMF_GetSICount(id) & + BIND(C, NAME='RMF_GetSICount') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + END FUNCTION RMF_GetSICount END INTERFACE INTEGER, INTENT(in) :: id RM_GetSICount = RMF_GetSICount(id) -END FUNCTION RM_GetSICount - -!> Retrieves an item from the list of all phases for which saturation indices can be calculated. -!> The list includes all phases that contain only elements included in the components in -!> the initial-phreeqc module. -!> The list assumes that all components are present to be able to calculate the entire list of SIs; -!> it may be that one or more components are missing in any specific cell. -!> @ref RM_FindComponents must be called before @ref RM_GetSIName. -!> This method may be useful when generating selected output definitions related to saturation indices. -!> @param id The instance @a id returned from @ref RM_Create. -!> @param num The number of the saturation-index-phase name to be retrieved. Fortran, 1 based. -!> @param name The saturation-index-phase name at number @a num. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_FindComponents, -!> @ref RM_GetSICount. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> input = trim(input) // "  -si "// new_line(c)
-!> do i = 1, RM_GetSICount(id)
-!>   status = RM_GetSIName(id, i, line)
-!>   input = trim(input) // "    " // line // new_line(c)
-!> enddo  
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root. - -INTEGER FUNCTION RM_GetSIName(id, num, name) + END FUNCTION RM_GetSICount + + !> Retrieves an item from the list of all phases for which saturation indices can be calculated. + !> The list includes all phases that contain only elements included in the components in + !> the initial-phreeqc module. + !> The list assumes that all components are present to be able to calculate the entire list of SIs; + !> it may be that one or more components are missing in any specific cell. + !> @ref RM_FindComponents must be called before @ref RM_GetSIName. + !> This method may be useful when generating selected output definitions related to saturation indices. + !> @param id The instance @a id returned from @ref RM_Create. + !> @param num The number of the saturation-index-phase name to be retrieved. Fortran, 1 based. + !> @param name The saturation-index-phase name at number @a num. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_FindComponents, + !> @ref RM_GetSICount. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> input = trim(input) // "  -si "// new_line(c)
+    !> do i = 1, RM_GetSICount(id)
+    !>   status = RM_GetSIName(id, i, line)
+    !>   input = trim(input) // "    " // line // new_line(c)
+    !> enddo
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root. + + INTEGER FUNCTION RM_GetSIName(id, num, name) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_GetSIName(id, num, name, l) & - BIND(C, NAME='RMF_GetSIName') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id, num, l - CHARACTER(KIND=C_CHAR), INTENT(out) :: name(*) - END FUNCTION RMF_GetSIName + INTEGER(KIND=C_INT) FUNCTION RMF_GetSIName(id, num, name, l) & + BIND(C, NAME='RMF_GetSIName') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id, num, l + CHARACTER(KIND=C_CHAR), INTENT(out) :: name(*) + END FUNCTION RMF_GetSIName END INTERFACE INTEGER, INTENT(in) :: id, num CHARACTER(len=*), INTENT(inout) :: name RM_GetSIName = RMF_GetSIName(id, num, name, len(name)) return -END FUNCTION RM_GetSIName - -!> Returns the number of solid solution components in the initial-phreeqc module. -!> @ref RM_FindComponents must be called before @ref RM_GetSolidSolutionComponentsCount. -!> This method may be useful when generating selected output definitions related to solid solutions. -!> @param id The instance @a id returned from @ref RM_Create. -!> @retval The number of solid solution components in the initial-phreeqc module. -!> @see -!> @ref RM_FindComponents, -!> @ref RM_GetSolidSolutionComponentsName, @ref RM_GetSolidSolutionName. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> input = trim(input) // "  -solid_solutions " // new_line(c)
-!> do i = 1, RM_GetSolidSolutionComponentsCount(id)
-!>   status = RM_GetSolidSolutionComponentsName(id, i, line)
-!>   status = RM_GetSolidSolutionName(id, i, line1)
-!>   input = trim(input) // "    " // line // " # " // line1 // new_line(c)
-!> enddo
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root. - -INTEGER FUNCTION RM_GetSolidSolutionComponentsCount(id) + END FUNCTION RM_GetSIName + + !> Returns the number of solid solution components in the initial-phreeqc module. + !> @ref RM_FindComponents must be called before @ref RM_GetSolidSolutionComponentsCount. + !> This method may be useful when generating selected output definitions related to solid solutions. + !> @param id The instance @a id returned from @ref RM_Create. + !> @retval The number of solid solution components in the initial-phreeqc module. + !> @see + !> @ref RM_FindComponents, + !> @ref RM_GetSolidSolutionComponentsName, @ref RM_GetSolidSolutionName. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> input = trim(input) // "  -solid_solutions " // new_line(c)
+    !> do i = 1, RM_GetSolidSolutionComponentsCount(id)
+    !>   status = RM_GetSolidSolutionComponentsName(id, i, line)
+    !>   status = RM_GetSolidSolutionName(id, i, line1)
+    !>   input = trim(input) // "    " // line // " # " // line1 // new_line(c)
+    !> enddo
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root. + + INTEGER FUNCTION RM_GetSolidSolutionComponentsCount(id) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_GetSolidSolutionComponentsCount(id) & - BIND(C, NAME='RMF_GetSolidSolutionComponentsCount') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - END FUNCTION RMF_GetSolidSolutionComponentsCount + INTEGER(KIND=C_INT) FUNCTION RMF_GetSolidSolutionComponentsCount(id) & + BIND(C, NAME='RMF_GetSolidSolutionComponentsCount') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + END FUNCTION RMF_GetSolidSolutionComponentsCount END INTERFACE INTEGER, INTENT(in) :: id RM_GetSolidSolutionComponentsCount = RMF_GetSolidSolutionComponentsCount(id) -END FUNCTION RM_GetSolidSolutionComponentsCount - -!> Retrieves an item from the solid solution components list. -!> The list includes all solid solution components included in any SOLID_SOLUTIONS definitions in -!> the initial-phreeqc module. -!> @ref RM_FindComponents must be called before @ref RM_GetSolidSolutionComponentsName. -!> This method may be useful when generating selected output definitions related to solid solutions. -!> @param id The instance @a id returned from @ref RM_Create. -!> @param num The number of the solid solution components name to be retrieved. Fortran, 1 based. -!> @param name The solid solution compnent name at number @a num. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_FindComponents, -!> @ref RM_GetSolidSolutionComponentsCount, @ref RM_GetSolidSolutionName. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> input = trim(input) // "  -solid_solutions " // new_line(c)
-!> do i = 1, RM_GetSolidSolutionComponentsCount(id)
-!>   status = RM_GetSolidSolutionComponentsName(id, i, line)
-!>   status = RM_GetSolidSolutionName(id, i, line1)
-!>   input = trim(input) // "    " // line // " # " // line1 // new_line(c)
-!> enddo
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root. - -INTEGER FUNCTION RM_GetSolidSolutionComponentsName(id, num, name) + END FUNCTION RM_GetSolidSolutionComponentsCount + + !> Retrieves an item from the solid solution components list. + !> The list includes all solid solution components included in any SOLID_SOLUTIONS definitions in + !> the initial-phreeqc module. + !> @ref RM_FindComponents must be called before @ref RM_GetSolidSolutionComponentsName. + !> This method may be useful when generating selected output definitions related to solid solutions. + !> @param id The instance @a id returned from @ref RM_Create. + !> @param num The number of the solid solution components name to be retrieved. Fortran, 1 based. + !> @param name The solid solution compnent name at number @a num. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_FindComponents, + !> @ref RM_GetSolidSolutionComponentsCount, @ref RM_GetSolidSolutionName. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> input = trim(input) // "  -solid_solutions " // new_line(c)
+    !> do i = 1, RM_GetSolidSolutionComponentsCount(id)
+    !>   status = RM_GetSolidSolutionComponentsName(id, i, line)
+    !>   status = RM_GetSolidSolutionName(id, i, line1)
+    !>   input = trim(input) // "    " // line // " # " // line1 // new_line(c)
+    !> enddo
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root. + + INTEGER FUNCTION RM_GetSolidSolutionComponentsName(id, num, name) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_GetSolidSolutionComponentsName(id, num, name, l) & - BIND(C, NAME='RMF_GetSolidSolutionComponentsName') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id, num, l - CHARACTER(KIND=C_CHAR), INTENT(out) :: name(*) - END FUNCTION RMF_GetSolidSolutionComponentsName + INTEGER(KIND=C_INT) FUNCTION RMF_GetSolidSolutionComponentsName(id, num, name, l) & + BIND(C, NAME='RMF_GetSolidSolutionComponentsName') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id, num, l + CHARACTER(KIND=C_CHAR), INTENT(out) :: name(*) + END FUNCTION RMF_GetSolidSolutionComponentsName END INTERFACE INTEGER, INTENT(in) :: id, num CHARACTER(len=*), INTENT(inout) :: name RM_GetSolidSolutionComponentsName = RMF_GetSolidSolutionComponentsName(id, num, name, len(name)) return -END FUNCTION RM_GetSolidSolutionComponentsName - -!> Retrieves an item from the solid solution names list. -!> The list includes solid solution names included in SOLID_SOLUTIONS definitions in -!> the initial-phreeqc module. -!> The solid solution names vector is the same length as the solid solution components vector -!> and provides the corresponding name of solid solution containing the component. -!> @ref RM_FindComponents must be called before @ref RM_GetSolidSolutionName. -!> This method may be useful when generating selected output definitions related to solid solutions. -!> @param id The instance @a id returned from @ref RM_Create. -!> @param num The number of the solid solution name to be retrieved. Fortran, 1 based. -!> @param name The solid solution name at number @a num. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_FindComponents, -!> @ref RM_GetSolidSolutionComponentsCount, @ref RM_GetSolidSolutionComponentsName. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> input = trim(input) // "  -solid_solutions " // new_line(c)
-!> do i = 1, RM_GetSolidSolutionComponentsCount(id)
-!>   status = RM_GetSolidSolutionComponentsName(id, i, line)
-!>   status = RM_GetSolidSolutionName(id, i, line1)
-!>   input = trim(input) // "    " // line // " # " // line1 // new_line(c)
-!> enddo
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root. - -INTEGER FUNCTION RM_GetSolidSolutionName(id, num, name) + END FUNCTION RM_GetSolidSolutionComponentsName + + !> Retrieves an item from the solid solution names list. + !> The list includes solid solution names included in SOLID_SOLUTIONS definitions in + !> the initial-phreeqc module. + !> The solid solution names vector is the same length as the solid solution components vector + !> and provides the corresponding name of solid solution containing the component. + !> @ref RM_FindComponents must be called before @ref RM_GetSolidSolutionName. + !> This method may be useful when generating selected output definitions related to solid solutions. + !> @param id The instance @a id returned from @ref RM_Create. + !> @param num The number of the solid solution name to be retrieved. Fortran, 1 based. + !> @param name The solid solution name at number @a num. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_FindComponents, + !> @ref RM_GetSolidSolutionComponentsCount, @ref RM_GetSolidSolutionComponentsName. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> input = trim(input) // "  -solid_solutions " // new_line(c)
+    !> do i = 1, RM_GetSolidSolutionComponentsCount(id)
+    !>   status = RM_GetSolidSolutionComponentsName(id, i, line)
+    !>   status = RM_GetSolidSolutionName(id, i, line1)
+    !>   input = trim(input) // "    " // line // " # " // line1 // new_line(c)
+    !> enddo
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root. + + INTEGER FUNCTION RM_GetSolidSolutionName(id, num, name) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_GetSolidSolutionName(id, num, name, l) & - BIND(C, NAME='RMF_GetSolidSolutionName') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id, num, l - CHARACTER(KIND=C_CHAR), INTENT(out) :: name(*) - END FUNCTION RMF_GetSolidSolutionName + INTEGER(KIND=C_INT) FUNCTION RMF_GetSolidSolutionName(id, num, name, l) & + BIND(C, NAME='RMF_GetSolidSolutionName') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id, num, l + CHARACTER(KIND=C_CHAR), INTENT(out) :: name(*) + END FUNCTION RMF_GetSolidSolutionName END INTERFACE INTEGER, INTENT(in) :: id, num CHARACTER(len=*), INTENT(inout) :: name RM_GetSolidSolutionName = RMF_GetSolidSolutionName(id, num, name, len(name)) return -END FUNCTION RM_GetSolidSolutionName - - -!> Transfer solution volumes from the reaction cells to the array given in the argument list (@a vol). -!> Solution volumes are those calculated by the reaction module. -!> Only the following databases distributed with PhreeqcRM have molar volume information -!> needed to accurately calculate solution volume: -!> phreeqc.dat, Amm.dat, and pitzer.dat. -!> -!> @param id The instance @a id returned from @ref RM_Create. -!> @param vol Array to receive the solution volumes. Dimension of the array is (@a nxyz), -!> where @a nxyz is the number of user grid cells. Values for inactive cells are set to 1e30. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_GetSaturation. -!> -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> allocate(volume(nxyz))
-!> status = RM_RunCells(id)
-!> status = RM_GetSolutionVolume(id, volume)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root, workers must be in the loop of @ref RM_MpiWorker. - -INTEGER FUNCTION RM_GetSolutionVolume(id, vol) + END FUNCTION RM_GetSolidSolutionName + + + !> Transfer solution volumes from the reaction cells to the array given in the argument list (@a vol). + !> Solution volumes are those calculated by the reaction module. + !> Only the following databases distributed with PhreeqcRM have molar volume information + !> needed to accurately calculate solution volume: + !> phreeqc.dat, Amm.dat, and pitzer.dat. + !> + !> @param id The instance @a id returned from @ref RM_Create. + !> @param vol Array to receive the solution volumes. Dimension of the array is (@a nxyz), + !> where @a nxyz is the number of user grid cells. Values for inactive cells are set to 1e30. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_GetSaturation. + !> + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> allocate(volume(nxyz))
+    !> status = RM_RunCells(id)
+    !> status = RM_GetSolutionVolume(id, volume)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref RM_MpiWorker. + + INTEGER FUNCTION RM_GetSolutionVolume(id, vol) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_GetSolutionVolume(id, vol) & - BIND(C, NAME='RMF_GetSolutionVolume') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - REAL(KIND=C_DOUBLE), INTENT(out) :: vol(*) - END FUNCTION RMF_GetSolutionVolume + INTEGER(KIND=C_INT) FUNCTION RMF_GetSolutionVolume(id, vol) & + BIND(C, NAME='RMF_GetSolutionVolume') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + REAL(KIND=C_DOUBLE), INTENT(out) :: vol(*) + END FUNCTION RMF_GetSolutionVolume END INTERFACE INTEGER, INTENT(in) :: id - DOUBLE PRECISION, INTENT(out), DIMENSION(:) :: vol + real(kind=8), INTENT(out), DIMENSION(:) :: vol if (rmf_debug) call Chk_GetDensity(id, vol) - RM_GetSolutionVolume = RMF_GetSolutionVolume(id, vol) -END FUNCTION RM_GetSolutionVolume + RM_GetSolutionVolume = RMF_GetSolutionVolume(id, vol) + END FUNCTION RM_GetSolutionVolume -SUBROUTINE Chk_GetSolutionVolume(id, vol) + SUBROUTINE Chk_GetSolutionVolume(id, vol) IMPLICIT NONE INTEGER, INTENT(in) :: id - DOUBLE PRECISION, INTENT(in), DIMENSION(:) :: vol + real(kind=8), INTENT(in), DIMENSION(:) :: vol INTEGER :: errors errors = 0 errors = errors + Chk_Double1D(id, vol, rmf_nxyz, "vol", "RM_GetSolutionVolume") if (errors .gt. 0) then errors = RM_Abort(id, -3, "Invalid argument in RM_GetSolutionVolume") endif -END SUBROUTINE Chk_GetSolutionVolume - -!> Transfer concentrations of aqueous species to the array argument (@a species_conc) -!> This method is intended for use with multicomponent-diffusion transport calculations, -!> and @ref RM_SetSpeciesSaveOn must be set to @a true. -!> The list of aqueous -!> species is determined by @ref RM_FindComponents and includes all -!> aqueous species that can be made from the set of components. -!> Solution volumes used to calculate mol/L are calculated by the reaction module. -!> Only the following databases distributed with PhreeqcRM have molar volume information -!> needed to accurately calculate solution volume: -!> phreeqc.dat, Amm.dat, and pitzer.dat. -!> -!> @param id The instance @a id returned from @ref RM_Create. -!> @param species_conc Array to receive the aqueous species concentrations. -!> Dimension of the array is (@a nxyz, @a nspecies), -!> where @a nxyz is the number of user grid cells (@ref RM_GetGridCellCount), -!> and @a nspecies is the number of aqueous species (@ref RM_GetSpeciesCount). -!> Concentrations are moles per liter. -!> Values for inactive cells are set to 1e30. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_FindComponents, -!> @ref RM_GetSpeciesCount, -!> @ref RM_GetSpeciesD25, -!> @ref RM_GetSpeciesLog10Gammas, -!> @ref RM_GetSpeciesLog10Molalities, -!> @ref RM_GetSpeciesName, -!> @ref RM_GetSpeciesSaveOn, -!> @ref RM_GetSpeciesZ, -!> @ref RM_SetSpeciesSaveOn, -!> @ref RM_SpeciesConcentrations2Module. -!> -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> status = RM_SetSpeciesSaveOn(id, 1)
-!> ncomps = RM_FindComponents(id)
-!> nspecies = RM_GetSpeciesCount(id)
-!> nxyz = RM_GetGridCellCount(id)
-!> allocate(species_c(nxyz, nspecies))
-!> status = RM_RunCells(id)
-!> status = RM_GetSpeciesConcentrations(id, species_c)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root, workers must be in the loop of @ref RM_MpiWorker. - -INTEGER FUNCTION RM_GetSpeciesConcentrations(id, species_conc) - USE ISO_C_BINDING + END SUBROUTINE Chk_GetSolutionVolume + + !> Transfer concentrations of aqueous species to the array argument (@a species_conc) + !> This method is intended for use with multicomponent-diffusion transport calculations, + !> and @ref RM_SetSpeciesSaveOn must be set to @a true. + !> The list of aqueous + !> species is determined by @ref RM_FindComponents and includes all + !> aqueous species that can be made from the set of components. + !> Solution volumes used to calculate mol/L are calculated by the reaction module. + !> Only the following databases distributed with PhreeqcRM have molar volume information + !> needed to accurately calculate solution volume: + !> phreeqc.dat, Amm.dat, and pitzer.dat. + !> + !> @param id The instance @a id returned from @ref RM_Create. + !> @param species_conc Array to receive the aqueous species concentrations. + !> Dimension of the array is (@a nxyz, @a nspecies), + !> where @a nxyz is the number of user grid cells (@ref RM_GetGridCellCount), + !> and @a nspecies is the number of aqueous species (@ref RM_GetSpeciesCount). + !> Concentrations are moles per liter. + !> Values for inactive cells are set to 1e30. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_FindComponents, + !> @ref RM_GetSpeciesCount, + !> @ref RM_GetSpeciesD25, + !> @ref RM_GetSpeciesLog10Gammas, + !> @ref RM_GetSpeciesLog10Molalities, + !> @ref RM_GetSpeciesName, + !> @ref RM_GetSpeciesSaveOn, + !> @ref RM_GetSpeciesZ, + !> @ref RM_SetSpeciesSaveOn, + !> @ref RM_SpeciesConcentrations2Module. + !> + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> status = RM_SetSpeciesSaveOn(id, 1)
+    !> ncomps = RM_FindComponents(id)
+    !> nspecies = RM_GetSpeciesCount(id)
+    !> nxyz = RM_GetGridCellCount(id)
+    !> allocate(species_c(nxyz, nspecies))
+    !> status = RM_RunCells(id)
+    !> status = RM_GetSpeciesConcentrations(id, species_c)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref RM_MpiWorker. + + INTEGER FUNCTION RM_GetSpeciesConcentrations(id, species_conc) + USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_GetSpeciesConcentrations(id, species_conc) & - BIND(C, NAME='RMF_GetSpeciesConcentrations') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - REAL(KIND=C_DOUBLE), INTENT(out) :: species_conc(*) - END FUNCTION RMF_GetSpeciesConcentrations + INTEGER(KIND=C_INT) FUNCTION RMF_GetSpeciesConcentrations(id, species_conc) & + BIND(C, NAME='RMF_GetSpeciesConcentrations') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + REAL(KIND=C_DOUBLE), INTENT(out) :: species_conc(*) + END FUNCTION RMF_GetSpeciesConcentrations END INTERFACE INTEGER, INTENT(in) :: id - DOUBLE PRECISION, INTENT(out), DIMENSION(:,:) :: species_conc + real(kind=8), INTENT(out), DIMENSION(:,:) :: species_conc if (rmf_debug) call Chk_GetSpeciesConcentrations(id, species_conc) RM_GetSpeciesConcentrations = RMF_GetSpeciesConcentrations(id, species_conc) -END FUNCTION RM_GetSpeciesConcentrations + END FUNCTION RM_GetSpeciesConcentrations -SUBROUTINE Chk_GetSpeciesConcentrations(id, species_conc) + SUBROUTINE Chk_GetSpeciesConcentrations(id, species_conc) IMPLICIT NONE INTEGER, INTENT(in) :: id - DOUBLE PRECISION, INTENT(in), DIMENSION(:,:) :: species_conc + real(kind=8), INTENT(in), DIMENSION(:,:) :: species_conc INTEGER :: errors, nspecies nspecies = RM_GetSpeciesCount(id) errors = 0 @@ -2737,122 +3010,122 @@ SUBROUTINE Chk_GetSpeciesConcentrations(id, species_conc) if (errors .gt. 0) then errors = RM_Abort(id, -3, "Invalid argument in RM_GetSpeciesConcentrations") endif -END SUBROUTINE Chk_GetSpeciesConcentrations - -!> The number of aqueous species used in the reaction module. -!> This method is intended for use with multicomponent-diffusion transport calculations, -!> and @ref RM_SetSpeciesSaveOn must be set to @a true. -!> The list of aqueous -!> species is determined by @ref RM_FindComponents and includes all -!> aqueous species that can be made from the set of components. -!> -!> @param id The instance @a id returned from @ref RM_Create. -!> @retval IRM_RESULT The number of aqueous species, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_FindComponents, -!> @ref RM_GetSpeciesConcentrations, -!> @ref RM_GetSpeciesD25, -!> @ref RM_GetSpeciesLog10Gammas, -!> @ref RM_GetSpeciesLog10Molalities, -!> @ref RM_GetSpeciesName, -!> @ref RM_GetSpeciesSaveOn, -!> @ref RM_GetSpeciesZ, -!> @ref RM_SetSpeciesSaveOn, -!> @ref RM_SpeciesConcentrations2Module. -!> -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> status = RM_SetSpeciesSaveOn(id, 1)
-!> ncomps = RM_FindComponents(id)
-!> nspecies = RM_GetSpeciesCount(id)
-!> nxyz = RM_GetGridCellCount(id)
-!> allocate(species_c(nxyz, nspecies))
-!> status = RM_RunCells(id)
-!> status = RM_GetSpeciesConcentrations(id, species_c)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root and (or) workers. - -INTEGER FUNCTION RM_GetSpeciesCount(id) + END SUBROUTINE Chk_GetSpeciesConcentrations + + !> The number of aqueous species used in the reaction module. + !> This method is intended for use with multicomponent-diffusion transport calculations, + !> and @ref RM_SetSpeciesSaveOn must be set to @a true. + !> The list of aqueous + !> species is determined by @ref RM_FindComponents and includes all + !> aqueous species that can be made from the set of components. + !> + !> @param id The instance @a id returned from @ref RM_Create. + !> @retval IRM_RESULT The number of aqueous species, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_FindComponents, + !> @ref RM_GetSpeciesConcentrations, + !> @ref RM_GetSpeciesD25, + !> @ref RM_GetSpeciesLog10Gammas, + !> @ref RM_GetSpeciesLog10Molalities, + !> @ref RM_GetSpeciesName, + !> @ref RM_GetSpeciesSaveOn, + !> @ref RM_GetSpeciesZ, + !> @ref RM_SetSpeciesSaveOn, + !> @ref RM_SpeciesConcentrations2Module. + !> + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> status = RM_SetSpeciesSaveOn(id, 1)
+    !> ncomps = RM_FindComponents(id)
+    !> nspecies = RM_GetSpeciesCount(id)
+    !> nxyz = RM_GetGridCellCount(id)
+    !> allocate(species_c(nxyz, nspecies))
+    !> status = RM_RunCells(id)
+    !> status = RM_GetSpeciesConcentrations(id, species_c)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root and (or) workers. + + INTEGER FUNCTION RM_GetSpeciesCount(id) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_GetSpeciesCount(id) & - BIND(C, NAME='RMF_GetSpeciesCount') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - END FUNCTION RMF_GetSpeciesCount + INTEGER(KIND=C_INT) FUNCTION RMF_GetSpeciesCount(id) & + BIND(C, NAME='RMF_GetSpeciesCount') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + END FUNCTION RMF_GetSpeciesCount END INTERFACE INTEGER, INTENT(in) :: id RM_GetSpeciesCount = RMF_GetSpeciesCount(id) -END FUNCTION RM_GetSpeciesCount - -!> Transfers diffusion coefficients at 25C to the array argument (@a diffc). -!> This method is intended for use with multicomponent-diffusion transport calculations, -!> and @ref RM_SetSpeciesSaveOn must be set to @a true. -!> Diffusion coefficients are defined in SOLUTION_SPECIES data blocks, normally in the database file. -!> Databases distributed with the reaction module that have diffusion coefficients defined are -!> phreeqc.dat, Amm.dat, and pitzer.dat. -!> -!> @param id The instance @a id returned from @ref RM_Create. -!> @param diffc Array to receive the diffusion coefficients at 25 C, m^2/s. -!> Dimension of the array is @a nspecies, -!> where @a nspecies is is the number of aqueous species (@ref RM_GetSpeciesCount). -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_FindComponents, -!> @ref RM_GetSpeciesConcentrations, -!> @ref RM_GetSpeciesCount, -!> @ref RM_GetSpeciesLog10Gammas, -!> @ref RM_GetSpeciesLog10Molalities, -!> @ref RM_GetSpeciesName, -!> @ref RM_GetSpeciesSaveOn, -!> @ref RM_GetSpeciesZ, -!> @ref RM_SetSpeciesSaveOn, -!> @ref RM_SpeciesConcentrations2Module. -!> -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> status = RM_SetSpeciesSaveOn(id, 1)
-!> ncomps = RM_FindComponents(id)
-!> nspecies = RM_GetSpeciesCount(id)
-!> allocate(diffc(nspecies))
-!> status = RM_GetSpeciesD25(id, diffc)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root and (or) workers. - -INTEGER FUNCTION RM_GetSpeciesD25(id, diffc) + END FUNCTION RM_GetSpeciesCount + + !> Transfers diffusion coefficients at 25C to the array argument (@a diffc). + !> This method is intended for use with multicomponent-diffusion transport calculations, + !> and @ref RM_SetSpeciesSaveOn must be set to @a true. + !> Diffusion coefficients are defined in SOLUTION_SPECIES data blocks, normally in the database file. + !> Databases distributed with the reaction module that have diffusion coefficients defined are + !> phreeqc.dat, Amm.dat, and pitzer.dat. + !> + !> @param id The instance @a id returned from @ref RM_Create. + !> @param diffc Array to receive the diffusion coefficients at 25 C, m^2/s. + !> Dimension of the array is @a nspecies, + !> where @a nspecies is is the number of aqueous species (@ref RM_GetSpeciesCount). + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_FindComponents, + !> @ref RM_GetSpeciesConcentrations, + !> @ref RM_GetSpeciesCount, + !> @ref RM_GetSpeciesLog10Gammas, + !> @ref RM_GetSpeciesLog10Molalities, + !> @ref RM_GetSpeciesName, + !> @ref RM_GetSpeciesSaveOn, + !> @ref RM_GetSpeciesZ, + !> @ref RM_SetSpeciesSaveOn, + !> @ref RM_SpeciesConcentrations2Module. + !> + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> status = RM_SetSpeciesSaveOn(id, 1)
+    !> ncomps = RM_FindComponents(id)
+    !> nspecies = RM_GetSpeciesCount(id)
+    !> allocate(diffc(nspecies))
+    !> status = RM_GetSpeciesD25(id, diffc)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root and (or) workers. + + INTEGER FUNCTION RM_GetSpeciesD25(id, diffc) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_GetSpeciesD25(id, diffc) & - BIND(C, NAME='RMF_GetSpeciesD25') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - REAL(KIND=C_DOUBLE), INTENT(out) :: diffc(*) - END FUNCTION RMF_GetSpeciesD25 + INTEGER(KIND=C_INT) FUNCTION RMF_GetSpeciesD25(id, diffc) & + BIND(C, NAME='RMF_GetSpeciesD25') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + REAL(KIND=C_DOUBLE), INTENT(out) :: diffc(*) + END FUNCTION RMF_GetSpeciesD25 END INTERFACE INTEGER, INTENT(in) :: id - DOUBLE PRECISION, INTENT(out), DIMENSION(:) :: diffc + real(kind=8), INTENT(out), DIMENSION(:) :: diffc if (rmf_debug) call Chk_GetSpeciesD25(id, diffc) RM_GetSpeciesD25 = RMF_GetSpeciesD25(id, diffc) -END FUNCTION RM_GetSpeciesD25 + END FUNCTION RM_GetSpeciesD25 -SUBROUTINE Chk_GetSpeciesD25(id, diffc) + SUBROUTINE Chk_GetSpeciesD25(id, diffc) IMPLICIT NONE INTEGER, INTENT(in) :: id - DOUBLE PRECISION, INTENT(in), DIMENSION(:) :: diffc + real(kind=8), INTENT(in), DIMENSION(:) :: diffc INTEGER :: errors, nspecies nspecies = RM_GetSpeciesCount(id) errors = 0 @@ -2860,325 +3133,325 @@ SUBROUTINE Chk_GetSpeciesD25(id, diffc) if (errors .gt. 0) then errors = RM_Abort(id, -3, "Invalid argument in RM_GetSpeciesD25") endif -END SUBROUTINE Chk_GetSpeciesD25 - -!> Transfer log10 aqueous-species activity coefficients to the array argument (@a species_log10gammas) -!> This method is intended for use with multicomponent-diffusion transport calculations, -!> and @ref RM_SetSpeciesSaveOn must be set to @a true. -!> The list of aqueous -!> species is determined by @ref RM_FindComponents and includes all -!> aqueous species that can be made from the set of components. -!> -!> @param id The instance @a id returned from @ref RM_Create. -!> @param species_log10gammas Array to receive the aqueous species concentrations. -!> Dimension of the array is (@a nxyz, @a nspecies), -!> where @a nxyz is the number of user grid cells (@ref RM_GetGridCellCount), -!> and @a nspecies is the number of aqueous species (@ref RM_GetSpeciesCount). -!> Values for inactive cells are set to 1e30. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_FindComponents, -!> @ref RM_GetSpeciesConcentrations, -!> @ref RM_GetSpeciesCount, -!> @ref RM_GetSpeciesD25, -!> @ref RM_GetSpeciesLog10Molalities, -!> @ref RM_GetSpeciesName, -!> @ref RM_GetSpeciesSaveOn, -!> @ref RM_GetSpeciesZ, -!> @ref RM_SetSpeciesSaveOn, -!> @ref RM_SpeciesConcentrations2Module. -!> -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> status = RM_SetSpeciesSaveOn(id, 1)
-!> ncomps = RM_FindComponents(id)
-!> nspecies = RM_GetSpeciesCount(id)
-!> nxyz = RM_GetGridCellCount(id)
-!> allocate(species_log10gammas(nxyz, nspecies))
-!> status = RM_RunCells(id)
-!> status = RM_GetSpeciesLog10Gammas(id, species_log10gammas)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root, workers must be in the loop of @ref RM_MpiWorker. - -INTEGER FUNCTION RM_GetSpeciesLog10Gammas(id, species_log10gammas) - USE ISO_C_BINDING + END SUBROUTINE Chk_GetSpeciesD25 + + !> Transfer log10 aqueous-species activity coefficients to the array argument (@a species_log10gammas) + !> This method is intended for use with multicomponent-diffusion transport calculations, + !> and @ref RM_SetSpeciesSaveOn must be set to @a true. + !> The list of aqueous + !> species is determined by @ref RM_FindComponents and includes all + !> aqueous species that can be made from the set of components. + !> + !> @param id The instance @a id returned from @ref RM_Create. + !> @param species_log10gammas Array to receive the aqueous species concentrations. + !> Dimension of the array is (@a nxyz, @a nspecies), + !> where @a nxyz is the number of user grid cells (@ref RM_GetGridCellCount), + !> and @a nspecies is the number of aqueous species (@ref RM_GetSpeciesCount). + !> Values for inactive cells are set to 1e30. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_FindComponents, + !> @ref RM_GetSpeciesConcentrations, + !> @ref RM_GetSpeciesCount, + !> @ref RM_GetSpeciesD25, + !> @ref RM_GetSpeciesLog10Molalities, + !> @ref RM_GetSpeciesName, + !> @ref RM_GetSpeciesSaveOn, + !> @ref RM_GetSpeciesZ, + !> @ref RM_SetSpeciesSaveOn, + !> @ref RM_SpeciesConcentrations2Module. + !> + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> status = RM_SetSpeciesSaveOn(id, 1)
+    !> ncomps = RM_FindComponents(id)
+    !> nspecies = RM_GetSpeciesCount(id)
+    !> nxyz = RM_GetGridCellCount(id)
+    !> allocate(species_log10gammas(nxyz, nspecies))
+    !> status = RM_RunCells(id)
+    !> status = RM_GetSpeciesLog10Gammas(id, species_log10gammas)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref RM_MpiWorker. + + INTEGER FUNCTION RM_GetSpeciesLog10Gammas(id, species_log10gammas) + USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_GetSpeciesLog10Gammas(id, species_log10gammas) & - BIND(C, NAME='RMF_GetSpeciesLog10Gammas') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - REAL(KIND=C_DOUBLE), INTENT(out) :: species_log10gammas(*) - END FUNCTION RMF_GetSpeciesLog10Gammas + INTEGER(KIND=C_INT) FUNCTION RMF_GetSpeciesLog10Gammas(id, species_log10gammas) & + BIND(C, NAME='RMF_GetSpeciesLog10Gammas') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + REAL(KIND=C_DOUBLE), INTENT(out) :: species_log10gammas(*) + END FUNCTION RMF_GetSpeciesLog10Gammas END INTERFACE INTEGER, INTENT(in) :: id - DOUBLE PRECISION, INTENT(out), DIMENSION(:,:) :: species_log10gammas + real(kind=8), INTENT(out), DIMENSION(:,:) :: species_log10gammas if (rmf_debug) call Chk_GetSpeciesLog10Gammas(id, species_log10gammas) RM_GetSpeciesLog10Gammas = RMF_GetSpeciesLog10Gammas(id, species_log10gammas) -END FUNCTION RM_GetSpeciesLog10Gammas + END FUNCTION RM_GetSpeciesLog10Gammas -SUBROUTINE Chk_GetSpeciesLog10Gammas(id, species_log10gammas) + SUBROUTINE Chk_GetSpeciesLog10Gammas(id, species_log10gammas) IMPLICIT NONE INTEGER, INTENT(in) :: id - DOUBLE PRECISION, INTENT(in), DIMENSION(:,:) :: species_log10gammas + real(kind=8), INTENT(in), DIMENSION(:,:) :: species_log10gammas INTEGER :: errors, nspecies - nspecies = RM_GetSpeciesCount(id) - errors = 0 - errors = errors + Chk_Double2D(id, species_log10gammas, rmf_nxyz, nspecies, "species gammas", & - "RM_GetSpeciesLog10Gammas") - if (errors .gt. 0) then - errors = RM_Abort(id, -3, "Invalid argument in RM_GetSpeciesLog10Gammas") - endif -END SUBROUTINE Chk_GetSpeciesLog10Gammas - -!> Transfer log10 aqueous-species log10 molalities to the array argument (@a species_log10molalities) -!> To use this method @ref RM_SetSpeciesSaveOn must be set to @a true. -!> The list of aqueous -!> species is determined by @ref RM_FindComponents and includes all -!> aqueous species that can be made from the set of components. -!> -!> @param id The instance @a id returned from @ref RM_Create. -!> @param species_log10molalities Array to receive the aqueous species molalities. -!> Dimension of the array is (@a nxyz, @a nspecies), -!> where @a nxyz is the number of user grid cells (@ref RM_GetGridCellCount), -!> and @a nspecies is the number of aqueous species (@ref RM_GetSpeciesCount). -!> Values for inactive cells are set to 1e30. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_FindComponents, -!> @ref RM_GetSpeciesConcentrations, -!> @ref RM_GetSpeciesCount, -!> @ref RM_GetSpeciesD25, -!> @ref RM_GetSpeciesLog10Gammas, -!> @ref RM_GetSpeciesName, -!> @ref RM_GetSpeciesSaveOn, -!> @ref RM_GetSpeciesZ, -!> @ref RM_SetSpeciesSaveOn, -!> @ref RM_SpeciesConcentrations2Module. -!> -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> status = RM_SetSpeciesSaveOn(id, 1)
-!> ncomps = RM_FindComponents(id)
-!> nspecies = RM_GetSpeciesCount(id)
-!> nxyz = RM_GetGridCellCount(id)
-!> allocate(species_log10molalities(nxyz, nspecies))
-!> status = RM_RunCells(id)
-!> status = RM_GetSpeciesLog10Molalities(id, species_log10molalites)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root, workers must be in the loop of @ref RM_MpiWorker. - -INTEGER FUNCTION RM_GetSpeciesLog10Molalities(id, species_log10molalities) - USE ISO_C_BINDING + nspecies = RM_GetSpeciesCount(id) + errors = 0 + errors = errors + Chk_Double2D(id, species_log10gammas, rmf_nxyz, nspecies, "species gammas", & + "RM_GetSpeciesLog10Gammas") + if (errors .gt. 0) then + errors = RM_Abort(id, -3, "Invalid argument in RM_GetSpeciesLog10Gammas") + endif + END SUBROUTINE Chk_GetSpeciesLog10Gammas + + !> Transfer log10 aqueous-species log10 molalities to the array argument (@a species_log10molalities) + !> To use this method @ref RM_SetSpeciesSaveOn must be set to @a true. + !> The list of aqueous + !> species is determined by @ref RM_FindComponents and includes all + !> aqueous species that can be made from the set of components. + !> + !> @param id The instance @a id returned from @ref RM_Create. + !> @param species_log10molalities Array to receive the aqueous species molalities. + !> Dimension of the array is (@a nxyz, @a nspecies), + !> where @a nxyz is the number of user grid cells (@ref RM_GetGridCellCount), + !> and @a nspecies is the number of aqueous species (@ref RM_GetSpeciesCount). + !> Values for inactive cells are set to 1e30. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_FindComponents, + !> @ref RM_GetSpeciesConcentrations, + !> @ref RM_GetSpeciesCount, + !> @ref RM_GetSpeciesD25, + !> @ref RM_GetSpeciesLog10Gammas, + !> @ref RM_GetSpeciesName, + !> @ref RM_GetSpeciesSaveOn, + !> @ref RM_GetSpeciesZ, + !> @ref RM_SetSpeciesSaveOn, + !> @ref RM_SpeciesConcentrations2Module. + !> + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> status = RM_SetSpeciesSaveOn(id, 1)
+    !> ncomps = RM_FindComponents(id)
+    !> nspecies = RM_GetSpeciesCount(id)
+    !> nxyz = RM_GetGridCellCount(id)
+    !> allocate(species_log10molalities(nxyz, nspecies))
+    !> status = RM_RunCells(id)
+    !> status = RM_GetSpeciesLog10Molalities(id, species_log10molalites)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref RM_MpiWorker. + + INTEGER FUNCTION RM_GetSpeciesLog10Molalities(id, species_log10molalities) + USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_GetSpeciesLog10Molalities(id, species_log10molalities) & - BIND(C, NAME='RMF_GetSpeciesLog10Molalities') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - REAL(KIND=C_DOUBLE), INTENT(out) :: species_log10molalities(*) - END FUNCTION RMF_GetSpeciesLog10Molalities + INTEGER(KIND=C_INT) FUNCTION RMF_GetSpeciesLog10Molalities(id, species_log10molalities) & + BIND(C, NAME='RMF_GetSpeciesLog10Molalities') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + REAL(KIND=C_DOUBLE), INTENT(out) :: species_log10molalities(*) + END FUNCTION RMF_GetSpeciesLog10Molalities END INTERFACE INTEGER, INTENT(in) :: id - DOUBLE PRECISION, INTENT(out), DIMENSION(:,:) :: species_log10molalities + real(kind=8), INTENT(out), DIMENSION(:,:) :: species_log10molalities if (rmf_debug) call Chk_GetSpeciesLog10Molalities(id, species_log10molalities) RM_GetSpeciesLog10Molalities = RMF_GetSpeciesLog10Molalities(id, species_log10molalities) -END FUNCTION RM_GetSpeciesLog10Molalities + END FUNCTION RM_GetSpeciesLog10Molalities -SUBROUTINE Chk_GetSpeciesLog10Molalities(id, species_log10molalities) + SUBROUTINE Chk_GetSpeciesLog10Molalities(id, species_log10molalities) IMPLICIT NONE INTEGER, INTENT(in) :: id - DOUBLE PRECISION, INTENT(in), DIMENSION(:,:) :: species_log10molalities + real(kind=8), INTENT(in), DIMENSION(:,:) :: species_log10molalities INTEGER :: errors, nspecies nspecies = RM_GetSpeciesCount(id) errors = 0 errors = errors + Chk_Double2D(id, species_log10molalities, rmf_nxyz, nspecies, "species molalities", & - "RM_GetSpeciesLog10Molalities") + "RM_GetSpeciesLog10Molalities") if (errors .gt. 0) then errors = RM_Abort(id, -3, "Invalid argument in RM_GetSpeciesLog10Molalities") endif -END SUBROUTINE Chk_GetSpeciesLog10Molalities - -!> Transfers the name of the @a ith aqueous species to the character argument (@a name). -!> This method is intended for use with multicomponent-diffusion transport calculations, -!> and @ref RM_SetSpeciesSaveOn must be set to @a true. -!> The list of aqueous -!> species is determined by @ref RM_FindComponents and includes all -!> aqueous species that can be made from the set of components. -!> -!> @param id The instance @a id returned from @ref RM_Create. -!> @param i Sequence number of the species in the species list. Fortran, 1 based. -!> @param name Character array to receive the species name. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_FindComponents, -!> @ref RM_GetSpeciesConcentrations, -!> @ref RM_GetSpeciesCount, -!> @ref RM_GetSpeciesD25, -!> @ref RM_GetSpeciesLog10Gammas, -!> @ref RM_GetSpeciesLog10Molalities, -!> @ref RM_GetSpeciesSaveOn, -!> @ref RM_GetSpeciesZ, -!> @ref RM_SetSpeciesSaveOn, -!> @ref RM_SpeciesConcentrations2Module. -!> -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> char*100 name
-!> ...
-!> status = RM_SetSpeciesSaveOn(id, 1)
-!> ncomps = RM_FindComponents(id)
-!> nspecies = RM_GetSpeciesCount(id)
-!> do i = 1, nspecies
-!>   status = RM_GetSpeciesName(id, i, name)
-!>   write(*,*) name
-!> enddo
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root and (or) workers. - -INTEGER FUNCTION RM_GetSpeciesName(id, i, name) + END SUBROUTINE Chk_GetSpeciesLog10Molalities + + !> Transfers the name of the @a ith aqueous species to the character argument (@a name). + !> This method is intended for use with multicomponent-diffusion transport calculations, + !> and @ref RM_SetSpeciesSaveOn must be set to @a true. + !> The list of aqueous + !> species is determined by @ref RM_FindComponents and includes all + !> aqueous species that can be made from the set of components. + !> + !> @param id The instance @a id returned from @ref RM_Create. + !> @param i Sequence number of the species in the species list. Fortran, 1 based. + !> @param name Character array to receive the species name. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_FindComponents, + !> @ref RM_GetSpeciesConcentrations, + !> @ref RM_GetSpeciesCount, + !> @ref RM_GetSpeciesD25, + !> @ref RM_GetSpeciesLog10Gammas, + !> @ref RM_GetSpeciesLog10Molalities, + !> @ref RM_GetSpeciesSaveOn, + !> @ref RM_GetSpeciesZ, + !> @ref RM_SetSpeciesSaveOn, + !> @ref RM_SpeciesConcentrations2Module. + !> + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> char*100 name
+    !> ...
+    !> status = RM_SetSpeciesSaveOn(id, 1)
+    !> ncomps = RM_FindComponents(id)
+    !> nspecies = RM_GetSpeciesCount(id)
+    !> do i = 1, nspecies
+    !>   status = RM_GetSpeciesName(id, i, name)
+    !>   write(*,*) name
+    !> enddo
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root and (or) workers. + + INTEGER FUNCTION RM_GetSpeciesName(id, i, name) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_GetSpeciesName(id, i, name, l) & - BIND(C, NAME='RMF_GetSpeciesName') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id, i, l - CHARACTER(KIND=C_CHAR), INTENT(out) :: name(*) - END FUNCTION RMF_GetSpeciesName + INTEGER(KIND=C_INT) FUNCTION RMF_GetSpeciesName(id, i, name, l) & + BIND(C, NAME='RMF_GetSpeciesName') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id, i, l + CHARACTER(KIND=C_CHAR), INTENT(out) :: name(*) + END FUNCTION RMF_GetSpeciesName END INTERFACE INTEGER, INTENT(in) :: id, i CHARACTER(len=*), INTENT(out) :: name RM_GetSpeciesName = RMF_GetSpeciesName(id, i, name, len(name)) -END FUNCTION RM_GetSpeciesName - -!> Returns the value of the species-save property. -!> By default, concentrations of aqueous species are not saved. Setting the species-save property to true allows -!> aqueous species concentrations to be retrieved -!> with @ref RM_GetSpeciesConcentrations, and solution compositions to be set with -!> @ref RM_SpeciesConcentrations2Module. -!> -!> @param id The instance @a id returned from @ref RM_Create. -!> @retval IRM_RESULT 0, species are not saved; 1, species are saved; negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_FindComponents, -!> @ref RM_GetSpeciesConcentrations, -!> @ref RM_GetSpeciesCount, -!> @ref RM_GetSpeciesD25, -!> @ref RM_GetSpeciesLog10Gammas, -!> @ref RM_GetSpeciesLog10Molalities, -!> @ref RM_GetSpeciesName, -!> @ref RM_GetSpeciesZ, -!> @ref RM_SetSpeciesSaveOn, -!> @ref RM_SpeciesConcentrations2Module. -!> -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> save_on = RM_GetSpeciesSaveOn(id)
-!> if (save_on .ne. 0) then
-!>   write(*,*) "Reaction module is saving species concentrations"
-!> else
-!>   write(*,*) "Reaction module is not saving species concentrations"
-!> end
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root and (or) workers. - -INTEGER FUNCTION RM_GetSpeciesSaveOn(id) + END FUNCTION RM_GetSpeciesName + + !> Returns the value of the species-save property. + !> By default, concentrations of aqueous species are not saved. Setting the species-save property to true allows + !> aqueous species concentrations to be retrieved + !> with @ref RM_GetSpeciesConcentrations, and solution compositions to be set with + !> @ref RM_SpeciesConcentrations2Module. + !> + !> @param id The instance @a id returned from @ref RM_Create. + !> @retval IRM_RESULT 0, species are not saved; 1, species are saved; negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_FindComponents, + !> @ref RM_GetSpeciesConcentrations, + !> @ref RM_GetSpeciesCount, + !> @ref RM_GetSpeciesD25, + !> @ref RM_GetSpeciesLog10Gammas, + !> @ref RM_GetSpeciesLog10Molalities, + !> @ref RM_GetSpeciesName, + !> @ref RM_GetSpeciesZ, + !> @ref RM_SetSpeciesSaveOn, + !> @ref RM_SpeciesConcentrations2Module. + !> + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> save_on = RM_GetSpeciesSaveOn(id)
+    !> if (save_on .ne. 0) then
+    !>   write(*,*) "Reaction module is saving species concentrations"
+    !> else
+    !>   write(*,*) "Reaction module is not saving species concentrations"
+    !> end
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root and (or) workers. + + INTEGER FUNCTION RM_GetSpeciesSaveOn(id) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_GetSpeciesSaveOn(id) & - BIND(C, NAME='RMF_GetSpeciesSaveOn') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - END FUNCTION RMF_GetSpeciesSaveOn + INTEGER(KIND=C_INT) FUNCTION RMF_GetSpeciesSaveOn(id) & + BIND(C, NAME='RMF_GetSpeciesSaveOn') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + END FUNCTION RMF_GetSpeciesSaveOn END INTERFACE INTEGER, INTENT(in) :: id RM_GetSpeciesSaveOn = RMF_GetSpeciesSaveOn(id) -END FUNCTION RM_GetSpeciesSaveOn - -!> Transfers the charge of each aqueous species to the array argument (@a z). -!> This method is intended for use with multicomponent-diffusion transport calculations, -!> and @ref RM_SetSpeciesSaveOn must be set to @a true. -!> -!> @param id The instance @a id returned from @ref RM_Create. -!> @param z Array that receives the charge for each aqueous species. -!> Dimension of the array is @a nspecies, -!> where @a nspecies is is the number of aqueous species (@ref RM_GetSpeciesCount). -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_FindComponents, -!> @ref RM_GetSpeciesConcentrations, -!> @ref RM_GetSpeciesCount, -!> @ref RM_GetSpeciesD25, -!> @ref RM_GetSpeciesLog10Gammas, -!> @ref RM_GetSpeciesLog10Molalities, -!> @ref RM_GetSpeciesName, -!> @ref RM_GetSpeciesSaveOn, -!> @ref RM_SetSpeciesSaveOn, -!> @ref RM_SpeciesConcentrations2Module. -!> -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> status = RM_SetSpeciesSaveOn(id, 1)
-!> ncomps = RM_FindComponents(id)
-!> nspecies = RM_GetSpeciesCount(id)
-!> allocate(z(nspecies))
-!> status = RM_GetSpeciesZ(id, z)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root and (or) workers. - -INTEGER FUNCTION RM_GetSpeciesZ(id, z) + END FUNCTION RM_GetSpeciesSaveOn + + !> Transfers the charge of each aqueous species to the array argument (@a z). + !> This method is intended for use with multicomponent-diffusion transport calculations, + !> and @ref RM_SetSpeciesSaveOn must be set to @a true. + !> + !> @param id The instance @a id returned from @ref RM_Create. + !> @param z Array that receives the charge for each aqueous species. + !> Dimension of the array is @a nspecies, + !> where @a nspecies is is the number of aqueous species (@ref RM_GetSpeciesCount). + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_FindComponents, + !> @ref RM_GetSpeciesConcentrations, + !> @ref RM_GetSpeciesCount, + !> @ref RM_GetSpeciesD25, + !> @ref RM_GetSpeciesLog10Gammas, + !> @ref RM_GetSpeciesLog10Molalities, + !> @ref RM_GetSpeciesName, + !> @ref RM_GetSpeciesSaveOn, + !> @ref RM_SetSpeciesSaveOn, + !> @ref RM_SpeciesConcentrations2Module. + !> + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> status = RM_SetSpeciesSaveOn(id, 1)
+    !> ncomps = RM_FindComponents(id)
+    !> nspecies = RM_GetSpeciesCount(id)
+    !> allocate(z(nspecies))
+    !> status = RM_GetSpeciesZ(id, z)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root and (or) workers. + + INTEGER FUNCTION RM_GetSpeciesZ(id, z) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_GetSpeciesZ(id, z) & - BIND(C, NAME='RMF_GetSpeciesZ') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - REAL(KIND=C_DOUBLE), INTENT(out) :: z(*) - END FUNCTION RMF_GetSpeciesZ + INTEGER(KIND=C_INT) FUNCTION RMF_GetSpeciesZ(id, z) & + BIND(C, NAME='RMF_GetSpeciesZ') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + REAL(KIND=C_DOUBLE), INTENT(out) :: z(*) + END FUNCTION RMF_GetSpeciesZ END INTERFACE INTEGER, INTENT(in) :: id - DOUBLE PRECISION, INTENT(out), DIMENSION(:) :: z - if (rmf_debug) call Chk_GetSpeciesZ(id, z) + real(kind=8), INTENT(out), DIMENSION(:) :: z + if (rmf_debug) call Chk_GetSpeciesZ(id, z) RM_GetSpeciesZ = RMF_GetSpeciesZ(id, z) -END FUNCTION RM_GetSpeciesZ - -SUBROUTINE Chk_GetSpeciesZ(id, z) + END FUNCTION RM_GetSpeciesZ + + SUBROUTINE Chk_GetSpeciesZ(id, z) IMPLICIT NONE INTEGER, INTENT(in) :: id - DOUBLE PRECISION, INTENT(in), DIMENSION(:) :: z + real(kind=8), INTENT(in), DIMENSION(:) :: z INTEGER :: errors, nspecies nspecies = RM_GetSpeciesCount(id) errors = 0 @@ -3186,51 +3459,51 @@ SUBROUTINE Chk_GetSpeciesZ(id, z) if (errors .gt. 0) then errors = RM_Abort(id, -3, "Invalid argument in RM_GetSpeciesZ") endif -END SUBROUTINE Chk_GetSpeciesZ - -!> Returns an array with the starting cell numbers from the range of cell numbers assigned to each worker. -!> @param id The instance @a id returned from @ref RM_Create. -!> @param sc Array to receive the starting cell numbers. Dimension of the array is -!> the number of threads (OpenMP) or the number of processes (MPI). -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_Create, -!> @ref RM_GetEndCell, -!> @ref RM_GetMpiTasks, -!> @ref RM_GetThreadCount. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> n = RM_GetThreadCount(id) * RM_GetMpiTasks(id)
-!> allocate(sc(n))
-!> status = RM_GetStartCell(id, sc)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root and (or) workers. - -INTEGER FUNCTION RM_GetStartCell(id, sc) + END SUBROUTINE Chk_GetSpeciesZ + + !> Returns an array with the starting cell numbers from the range of cell numbers assigned to each worker. + !> @param id The instance @a id returned from @ref RM_Create. + !> @param sc Array to receive the starting cell numbers. Dimension of the array is + !> the number of threads (OpenMP) or the number of processes (MPI). + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_Create, + !> @ref RM_GetEndCell, + !> @ref RM_GetMpiTasks, + !> @ref RM_GetThreadCount. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> n = RM_GetThreadCount(id) * RM_GetMpiTasks(id)
+    !> allocate(sc(n))
+    !> status = RM_GetStartCell(id, sc)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root and (or) workers. + + INTEGER FUNCTION RM_GetStartCell(id, sc) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_GetStartCell(id, sc) & - BIND(C, NAME='RMF_GetStartCell') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - INTEGER(KIND=C_INT), INTENT(out):: sc(*) - END FUNCTION RMF_GetStartCell + INTEGER(KIND=C_INT) FUNCTION RMF_GetStartCell(id, sc) & + BIND(C, NAME='RMF_GetStartCell') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + INTEGER(KIND=C_INT), INTENT(out):: sc(*) + END FUNCTION RMF_GetStartCell END INTERFACE INTEGER, INTENT(in) :: id INTEGER, INTENT(out), DIMENSION(:) :: sc if (rmf_debug) call Chk_GetStartCell(id, sc) RM_GetStartCell = RMF_GetStartCell(id, sc) RETURN -END FUNCTION RM_GetStartCell + END FUNCTION RM_GetStartCell -SUBROUTINE Chk_GetStartCell(id, sc) + SUBROUTINE Chk_GetStartCell(id, sc) IMPLICIT NONE INTEGER, INTENT(in) :: id INTEGER, INTENT(in), DIMENSION(:) :: sc @@ -3241,559 +3514,624 @@ SUBROUTINE Chk_GetStartCell(id, sc) if (errors .gt. 0) then errors = RM_Abort(id, -3, "Invalid argument in RMF_GetStartCell") endif -END SUBROUTINE Chk_GetStartCell - -!> Retrieves the surface name (such as "Hfo") that corresponds with -!> the surface species name. -!> The lists of surface species names and surface names are the same length. -!> @ref RM_FindComponents must be called before @ref RM_GetSurfaceName. -!> This method may be useful when generating selected output definitions related to surfaces. -!> @param id The instance @a id returned from @ref RM_Create. -!> @param num The number of the surface name to be retrieved. Fortran, 1 based. -!> @param name The surface name associated with surface species @a num. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_FindComponents, -!> @ref RM_GetSurfaceSpeciesCount, @ref RM_GetSurfaceSpeciesName, @ref RM_GetSurfaceType. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> do i = 1, RM_GetSurfaceSpeciesCount(id)
-!>   status = RM_GetSurfaceSpeciesName(id, i, line)
-!>   status = RM_GetSurfaceType(id, i, line1)
-!>   status = RM_GetSurfaceName(id, i, line2)
-!>   input = trim(input) // "    " // line // " # " // line1  // line2 // new_line(c)
-!> enddo  
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root. - -INTEGER FUNCTION RM_GetSurfaceName(id, num, name) + END SUBROUTINE Chk_GetStartCell + + !> Retrieves the surface name (such as "Hfo") that corresponds with + !> the surface species name. + !> The lists of surface species names and surface names are the same length. + !> @ref RM_FindComponents must be called before @ref RM_GetSurfaceName. + !> This method may be useful when generating selected output definitions related to surfaces. + !> @param id The instance @a id returned from @ref RM_Create. + !> @param num The number of the surface name to be retrieved. Fortran, 1 based. + !> @param name The surface name associated with surface species @a num. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_FindComponents, + !> @ref RM_GetSurfaceSpeciesCount, @ref RM_GetSurfaceSpeciesName, @ref RM_GetSurfaceType. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> do i = 1, RM_GetSurfaceSpeciesCount(id)
+    !>   status = RM_GetSurfaceSpeciesName(id, i, line)
+    !>   status = RM_GetSurfaceType(id, i, line1)
+    !>   status = RM_GetSurfaceName(id, i, line2)
+    !>   input = trim(input) // "    " // line // " # " // line1  // line2 // new_line(c)
+    !> enddo
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root. + + INTEGER FUNCTION RM_GetSurfaceName(id, num, name) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_GetSurfaceName(id, num, name, l) & - BIND(C, NAME='RMF_GetSurfaceName') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id, num, l - CHARACTER(KIND=C_CHAR), INTENT(out) :: name(*) - END FUNCTION RMF_GetSurfaceName + INTEGER(KIND=C_INT) FUNCTION RMF_GetSurfaceName(id, num, name, l) & + BIND(C, NAME='RMF_GetSurfaceName') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id, num, l + CHARACTER(KIND=C_CHAR), INTENT(out) :: name(*) + END FUNCTION RMF_GetSurfaceName END INTERFACE INTEGER, INTENT(in) :: id, num CHARACTER(len=*), INTENT(inout) :: name RM_GetSurfaceName = RMF_GetSurfaceName(id, num, name, len(name)) return -END FUNCTION RM_GetSurfaceName -!> Returns the number of surface species (such as "Hfo_wOH") in the initial-phreeqc module. -!> @ref RM_FindComponents must be called before @ref RM_GetSurfaceSpeciesCount. -!> This method may be useful when generating selected output definitions related to surfaces. -!> @param id The instance @a id returned from @ref RM_Create. -!> @retval The number of surface species in the initial-phreeqc module. -!> @see -!> @ref RM_FindComponents, -!> @ref RM_GetSurfaceSpeciesName, @ref RM_GetSurfaceType, @ref RM_GetSurfaceName. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> do i = 1, RM_GetSurfaceSpeciesCount(id)
-!>   status = RM_GetSurfaceSpeciesName(id, i, line)
-!>   status = RM_GetSurfaceType(id, i, line1)
-!>   status = RM_GetSurfaceName(id, i, line2)
-!>   input = trim(input) // "    " // line // " # " // line1  // line2 // new_line(c)
-!> enddo  
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root. - -INTEGER FUNCTION RM_GetSurfaceSpeciesCount(id) + END FUNCTION RM_GetSurfaceName + !> Returns the number of surface species (such as "Hfo_wOH") in the initial-phreeqc module. + !> @ref RM_FindComponents must be called before @ref RM_GetSurfaceSpeciesCount. + !> This method may be useful when generating selected output definitions related to surfaces. + !> @param id The instance @a id returned from @ref RM_Create. + !> @retval The number of surface species in the initial-phreeqc module. + !> @see + !> @ref RM_FindComponents, + !> @ref RM_GetSurfaceSpeciesName, @ref RM_GetSurfaceType, @ref RM_GetSurfaceName. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> do i = 1, RM_GetSurfaceSpeciesCount(id)
+    !>   status = RM_GetSurfaceSpeciesName(id, i, line)
+    !>   status = RM_GetSurfaceType(id, i, line1)
+    !>   status = RM_GetSurfaceName(id, i, line2)
+    !>   input = trim(input) // "    " // line // " # " // line1  // line2 // new_line(c)
+    !> enddo
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root. + + INTEGER FUNCTION RM_GetSurfaceSpeciesCount(id) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_GetSurfaceSpeciesCount(id) & - BIND(C, NAME='RMF_GetSurfaceSpeciesCount') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - END FUNCTION RMF_GetSurfaceSpeciesCount + INTEGER(KIND=C_INT) FUNCTION RMF_GetSurfaceSpeciesCount(id) & + BIND(C, NAME='RMF_GetSurfaceSpeciesCount') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + END FUNCTION RMF_GetSurfaceSpeciesCount END INTERFACE INTEGER, INTENT(in) :: id RM_GetSurfaceSpeciesCount = RMF_GetSurfaceSpeciesCount(id) -END FUNCTION RM_GetSurfaceSpeciesCount - -!> Retrieves an item from the surface species list. -!> The list of surface species (for example, "Hfo_wOH") is derived from the list of components -!> (@ref RM_FindComponents) and the list of all surface types (such as "Hfo_w") -!> that are included in SURFACE definitions in the initial-phreeqc module. -!> @ref RM_FindComponents must be called before @ref RM_GetSurfaceSpeciesName. -!> This method may be useful when generating selected output definitions related to surfaces. -!> @param id The instance @a id returned from @ref RM_Create. -!> @param num The number of the surface type to be retrieved. Fortran, 1 based. -!> @param name The surface species name at number @a num. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_FindComponents, -!> @ref RM_GetSurfaceSpeciesCount, @ref RM_GetSurfaceType, @ref RM_GetSurfaceName. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> do i = 1, RM_GetSurfaceSpeciesCount(id)
-!>   status = RM_GetSurfaceSpeciesName(id, i, line)
-!>   status = RM_GetSurfaceType(id, i, line1)
-!>   status = RM_GetSurfaceName(id, i, line2)
-!>   input = trim(input) // "    " // line // " # " // line1  // line2 // new_line(c)
-!> enddo 
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root. - -INTEGER FUNCTION RM_GetSurfaceSpeciesName(id, num, name) + END FUNCTION RM_GetSurfaceSpeciesCount + + !> Retrieves an item from the surface species list. + !> The list of surface species (for example, "Hfo_wOH") is derived from the list of components + !> (@ref RM_FindComponents) and the list of all surface types (such as "Hfo_w") + !> that are included in SURFACE definitions in the initial-phreeqc module. + !> @ref RM_FindComponents must be called before @ref RM_GetSurfaceSpeciesName. + !> This method may be useful when generating selected output definitions related to surfaces. + !> @param id The instance @a id returned from @ref RM_Create. + !> @param num The number of the surface type to be retrieved. Fortran, 1 based. + !> @param name The surface species name at number @a num. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_FindComponents, + !> @ref RM_GetSurfaceSpeciesCount, @ref RM_GetSurfaceType, @ref RM_GetSurfaceName. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> do i = 1, RM_GetSurfaceSpeciesCount(id)
+    !>   status = RM_GetSurfaceSpeciesName(id, i, line)
+    !>   status = RM_GetSurfaceType(id, i, line1)
+    !>   status = RM_GetSurfaceName(id, i, line2)
+    !>   input = trim(input) // "    " // line // " # " // line1  // line2 // new_line(c)
+    !> enddo
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root. + + INTEGER FUNCTION RM_GetSurfaceSpeciesName(id, num, name) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_GetSurfaceSpeciesName(id, num, name, l) & - BIND(C, NAME='RMF_GetSurfaceSpeciesName') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id, num, l - CHARACTER(KIND=C_CHAR), INTENT(out) :: name(*) - END FUNCTION RMF_GetSurfaceSpeciesName + INTEGER(KIND=C_INT) FUNCTION RMF_GetSurfaceSpeciesName(id, num, name, l) & + BIND(C, NAME='RMF_GetSurfaceSpeciesName') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id, num, l + CHARACTER(KIND=C_CHAR), INTENT(out) :: name(*) + END FUNCTION RMF_GetSurfaceSpeciesName END INTERFACE INTEGER, INTENT(in) :: id, num CHARACTER(len=*), INTENT(inout) :: name RM_GetSurfaceSpeciesName = RMF_GetSurfaceSpeciesName(id, num, name, len(name)) return -END FUNCTION RM_GetSurfaceSpeciesName - -!> Retrieves the surface site type (such as "Hfo_w") that corresponds with -!> the surface species name. -!> The lists of surface species names and surface species types are the same length. -!> @ref RM_FindComponents must be called before @ref RM_GetSurfaceType. -!> This method may be useful when generating selected output definitions related to surfaces. -!> @param id The instance @a id returned from @ref RM_Create. -!> @param num The number of the surface type to be retrieved. Fortran, 1 based. -!> @param name The surface type associated with surface species @a num. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_FindComponents, -!> @ref RM_GetSurfaceSpeciesCount, @ref RM_GetSurfaceSpeciesName, @ref RM_GetSurfaceName. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> do i = 1, RM_GetSurfaceSpeciesCount(id)
-!>   status = RM_GetSurfaceSpeciesName(id, i, line)
-!>   status = RM_GetSurfaceType(id, i, line1)
-!>   status = RM_GetSurfaceName(id, i, line2)
-!>   input = trim(input) // "    " // line // " # " // line1  // line2 // new_line(c)
-!> enddo 
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root. - -INTEGER FUNCTION RM_GetSurfaceType(id, num, name) + END FUNCTION RM_GetSurfaceSpeciesName + + !> Retrieves the surface site type (such as "Hfo_w") that corresponds with + !> the surface species name. + !> The lists of surface species names and surface species types are the same length. + !> @ref RM_FindComponents must be called before @ref RM_GetSurfaceType. + !> This method may be useful when generating selected output definitions related to surfaces. + !> @param id The instance @a id returned from @ref RM_Create. + !> @param num The number of the surface type to be retrieved. Fortran, 1 based. + !> @param name The surface type associated with surface species @a num. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_FindComponents, + !> @ref RM_GetSurfaceSpeciesCount, @ref RM_GetSurfaceSpeciesName, @ref RM_GetSurfaceName. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> do i = 1, RM_GetSurfaceSpeciesCount(id)
+    !>   status = RM_GetSurfaceSpeciesName(id, i, line)
+    !>   status = RM_GetSurfaceType(id, i, line1)
+    !>   status = RM_GetSurfaceName(id, i, line2)
+    !>   input = trim(input) // "    " // line // " # " // line1  // line2 // new_line(c)
+    !> enddo
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root. + + INTEGER FUNCTION RM_GetSurfaceType(id, num, name) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_GetSurfaceType(id, num, name, l) & - BIND(C, NAME='RMF_GetSurfaceType') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id, num, l - CHARACTER(KIND=C_CHAR), INTENT(out) :: name(*) - END FUNCTION RMF_GetSurfaceType + INTEGER(KIND=C_INT) FUNCTION RMF_GetSurfaceType(id, num, name, l) & + BIND(C, NAME='RMF_GetSurfaceType') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id, num, l + CHARACTER(KIND=C_CHAR), INTENT(out) :: name(*) + END FUNCTION RMF_GetSurfaceType END INTERFACE INTEGER, INTENT(in) :: id, num CHARACTER(len=*), INTENT(inout) :: name RM_GetSurfaceType = RMF_GetSurfaceType(id, num, name, len(name)) return -END FUNCTION RM_GetSurfaceType - - -!> Returns the number of threads, which is equal to the number of workers used to run in parallel with OPENMP. -!> For the OPENMP version, the number of threads is set implicitly or explicitly with @ref RM_Create. For the -!> MPI version, the number of threads is always one for each process. -!> @param id The instance @a id returned from @ref RM_Create. -!> @retval The number of threads, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_GetMpiTasks. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> write(string1, "(A,I)") "Number of threads: ", RM_GetThreadCount(id)
-!> status = RM_OutputMessage(id, string1)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root and (or) workers; result is always 1. - -INTEGER FUNCTION RM_GetThreadCount(id) + END FUNCTION RM_GetSurfaceType + + !> Returns a vector of temperatures (@a temperature) from the reaction module. + !> Reactions do not change the temperature, so the temperatures are either the + !> temperatures at initialization, or the values set with the last call to + !> @ref RM_SetTemperature. + !> + !> @param id The instance @a id returned from @ref RM_Create. + !> @param temperature Vector to receive the temperatures. + !> Dimension of the array is @a nxyz, + !> where @a nxyz is the number of user grid cells (@ref RM_GetGridCellCount). + !> Values for inactive cells are set to 1e30. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> + !> @see + !> @ref bmif_get_value, + !> @ref bmif_set_value, + !> @ref RM_SetTemperature. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> allocate(temperature(nxyz))
+    !> status = RM_GetTemperature(id, temperature)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref RM_MpiWorker. + + !INTEGER FUNCTION RM_GetTemperature(id, temperature) + !USE ISO_C_BINDING + !IMPLICIT NONE + !INTEGER, INTENT(in) :: id + !real(kind=8), INTENT(out), DIMENSION(:) :: temperature + !real(kind=8), ALLOCATABLE, DIMENSION(:) :: a_temperature + !RM_GetTemperature = bmif_get_value(id, "Temperature", a_temperature) + !temperature = a_temperature + !END FUNCTION RM_GetTemperature + + INTEGER FUNCTION RM_GetTemperature(id, temperature) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION RMF_GetTemperature(id, temperature) & + BIND(C, NAME='RMF_GetTemperature') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + REAL(KIND=C_DOUBLE), INTENT(out) :: temperature(*) + END FUNCTION RMF_GetTemperature + END INTERFACE + INTEGER, INTENT(in) :: id + real(kind=8), INTENT(out), dimension(:) :: temperature + RM_GetTemperature = RMF_GetTemperature(id, temperature) + return + END FUNCTION RM_GetTemperature + + !> Returns the number of threads, which is equal to the number of workers used to run in parallel with OPENMP. + !> For the OPENMP version, the number of threads is set implicitly or explicitly with @ref RM_Create. For the + !> MPI version, the number of threads is always one for each process. + !> @param id The instance @a id returned from @ref RM_Create. + !> @retval Number of threads, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_GetMpiTasks. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> write(string1, "(A,I)") "Number of threads: ", RM_GetThreadCount(id)
+    !> status = RM_OutputMessage(id, string1)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root and (or) workers; result is always 1. + + INTEGER FUNCTION RM_GetThreadCount(id) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_GetThreadCount(id) & - BIND(C, NAME='RMF_GetThreadCount') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - END FUNCTION RMF_GetThreadCount + INTEGER(KIND=C_INT) FUNCTION RMF_GetThreadCount(id) & + BIND(C, NAME='RMF_GetThreadCount') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + END FUNCTION RMF_GetThreadCount END INTERFACE INTEGER, INTENT(in) :: id RM_GetThreadCount = RMF_GetThreadCount(id) -END FUNCTION RM_GetThreadCount - -!> Returns the current simulation time in seconds. The reaction module does not change the time value, so the -!> returned value is equal to the default (0.0) or the last time set by @ref RM_SetTime. -!> @param id The instance @a id returned from @ref RM_Create. -!> @retval The current simulation time in seconds. -!> @see -!> @ref RM_GetTimeConversion, -!> @ref RM_GetTimeStep, -!> @ref RM_SetTime, -!> @ref RM_SetTimeConversion, -!> @ref RM_SetTimeStep. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> write(string, "(A32,F15.1,A)") "Beginning transport calculation ", &
-!>       RM_GetTime(id) * RM_GetTimeConversion(id), " days"
-!> status = RM_LogMessage(id, string)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root and (or) workers. - -DOUBLE PRECISION FUNCTION RM_GetTime(id) + END FUNCTION RM_GetThreadCount + + !> Returns the current simulation time in seconds. The reaction module does not change the time value, so the + !> returned value is equal to the default (0.0) or the last time set by @ref RM_SetTime. + !> @param id The instance @a id returned from @ref RM_Create. + !> @retval The current simulation time in seconds. + !> @see + !> @ref RM_GetTimeConversion, + !> @ref RM_GetTimeStep, + !> @ref RM_SetTime, + !> @ref RM_SetTimeConversion, + !> @ref RM_SetTimeStep. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> write(string, "(A32,F15.1,A)") "Beginning transport calculation ", &
+    !>       RM_GetTime(id) * RM_GetTimeConversion(id), " days"
+    !> status = RM_LogMessage(id, string)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root and (or) workers. + + real(kind=8) FUNCTION RM_GetTime(id) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - REAL(KIND=C_DOUBLE) FUNCTION RMF_GetTime(id) & - BIND(C, NAME='RMF_GetTime') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - END FUNCTION RMF_GetTime + REAL(KIND=C_DOUBLE) FUNCTION RMF_GetTime(id) & + BIND(C, NAME='RMF_GetTime') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + END FUNCTION RMF_GetTime END INTERFACE INTEGER, INTENT(in) :: id RM_GetTime = RMF_GetTime(id) -END FUNCTION RM_GetTime - -!> Returns a multiplier to convert time from seconds to another unit, as specified by the user. -!> The reaction module uses seconds as the time unit. The user can set a conversion -!> factor (@ref RM_SetTimeConversion) and retrieve it with RM_GetTimeConversion. The -!> reaction module only uses the conversion factor when printing the long version -!> of cell chemistry (@ref RM_SetPrintChemistryOn), which is rare. Default conversion factor is 1.0. -!> @param id The instance @a id returned from @ref RM_Create. -!> @retval Multiplier to convert seconds to another time unit. -!> @see -!> @ref RM_GetTime, -!> @ref RM_GetTimeStep, -!> @ref RM_SetTime, -!> @ref RM_SetTimeConversion, -!> @ref RM_SetTimeStep. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> write(string, "(A32,F15.1,A)") "Beginning transport calculation ", &
-!>       RM_GetTime(id) * RM_GetTimeConversion(id), " days"
-!> status = RM_LogMessage(id, string)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root and (or) workers. - -DOUBLE PRECISION FUNCTION RM_GetTimeConversion(id) + END FUNCTION RM_GetTime + + !> Returns a multiplier to convert time from seconds to another unit, as specified by the user. + !> The reaction module uses seconds as the time unit. The user can set a conversion + !> factor (@ref RM_SetTimeConversion) and retrieve it with RM_GetTimeConversion. The + !> reaction module only uses the conversion factor when printing the long version + !> of cell chemistry (@ref RM_SetPrintChemistryOn), which is rare. Default conversion factor is 1.0. + !> @param id The instance @a id returned from @ref RM_Create. + !> @retval Multiplier to convert seconds to another time unit. + !> @see + !> @ref RM_GetTime, + !> @ref RM_GetTimeStep, + !> @ref RM_SetTime, + !> @ref RM_SetTimeConversion, + !> @ref RM_SetTimeStep. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> write(string, "(A32,F15.1,A)") "Beginning transport calculation ", &
+    !>       RM_GetTime(id) * RM_GetTimeConversion(id), " days"
+    !> status = RM_LogMessage(id, string)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root and (or) workers. + + real(kind=8) FUNCTION RM_GetTimeConversion(id) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - REAL(KIND=C_DOUBLE) FUNCTION RMF_GetTimeConversion(id) & - BIND(C, NAME='RMF_GetTimeConversion') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - END FUNCTION RMF_GetTimeConversion + REAL(KIND=C_DOUBLE) FUNCTION RMF_GetTimeConversion(id) & + BIND(C, NAME='RMF_GetTimeConversion') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + END FUNCTION RMF_GetTimeConversion END INTERFACE INTEGER, INTENT(in) :: id RM_GetTimeConversion = RMF_GetTimeConversion(id) -END FUNCTION RM_GetTimeConversion - -!> Returns the current simulation time step in seconds. -!> This is the time over which kinetic reactions are integrated in a call to @ref RM_RunCells. -!> The reaction module does not change the time step value, so the -!> returned value is equal to the default (0.0) or the last time step set by @ref RM_SetTimeStep. -!> @param id The instance @a id returned from @ref RM_Create. -!> @retval The current simulation time step in seconds. -!> @see -!> @ref RM_GetTime, -!> @ref RM_GetTimeConversion, -!> @ref RM_SetTime, -!> @ref RM_SetTimeConversion, -!> @ref RM_SetTimeStep. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> write(string, "(A32,F15.1,A)") "          Time step             ", &
-!>       RM_GetTimeStep(id) * RM_GetTimeConversion(id), " days"
-!> status = RM_LogMessage(id, string)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root and (or) workers. - -DOUBLE PRECISION FUNCTION RM_GetTimeStep(id) + END FUNCTION RM_GetTimeConversion + + !> Returns the current simulation time step in seconds. + !> This is the time over which kinetic reactions are integrated in a call to @ref RM_RunCells. + !> The reaction module does not change the time step value, so the + !> returned value is equal to the default (0.0) or the last time step set by @ref RM_SetTimeStep. + !> @param id The instance @a id returned from @ref RM_Create. + !> @retval The current simulation time step in seconds. + !> @see + !> @ref RM_GetTime, + !> @ref RM_GetTimeConversion, + !> @ref RM_SetTime, + !> @ref RM_SetTimeConversion, + !> @ref RM_SetTimeStep. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> write(string, "(A32,F15.1,A)") "          Time step             ", &
+    !>       RM_GetTimeStep(id) * RM_GetTimeConversion(id), " days"
+    !> status = RM_LogMessage(id, string)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root and (or) workers. + + real(kind=8) FUNCTION RM_GetTimeStep(id) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - REAL(KIND=C_DOUBLE) FUNCTION RMF_GetTimeStep(id) & - BIND(C, NAME='RMF_GetTimeStep') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - END FUNCTION RMF_GetTimeStep + REAL(KIND=C_DOUBLE) FUNCTION RMF_GetTimeStep(id) & + BIND(C, NAME='RMF_GetTimeStep') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + END FUNCTION RMF_GetTimeStep END INTERFACE INTEGER, INTENT(in) :: id RM_GetTimeStep = RMF_GetTimeStep(id) -END FUNCTION RM_GetTimeStep + END FUNCTION RM_GetTimeStep #ifdef USE_YAML -!> A YAML file can be used to initialize an instance of PhreeqcRM. -!> @param id The instance @a id returned from @ref RM_Create. -!> @param yaml_name String containing the YAML file name. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @par -!> The file contains a YAML map of PhreeqcRM methods -!> and the arguments corresponding to the methods. -!> Note that the PhreeqcRM methods do not have the "RM_" prefix -!> and the id argument is not included. -!> For example, -!> @par -!> @htmlonly -!> -!>
-!> LoadDatabase: phreeqc.dat
-!> RunFile:
-!> 	workers: true
-!> 	initial_phreeqc: true
-!> 	utility: true
-!> 	chemistry_name: advect.pqi
-!> 
-!>
-!> @endhtmlonly -!> @par -!> @ref RM_InitializeYAML will read the YAML file and execute the specified methods with -!> the specified arguments. Using YAML -!> terminology, the argument(s) for a method may be a scalar, a sequence, or a map, -!> depending if the argument is -!> a single item, a single vector, or there are multiple arguments. -!> In the case of a map, the name associated -!> with each argument (for example "chemistry_name" above) is arbitrary. -!> The names of the map keys for map -!> arguments are not used in parsing the YAML file; only the order of -!> the arguments is important. -!> @par -!> The following list gives the PhreeqcRM methods that can be specified in a YAML file -!> and the arguments that are required. The arguments are described with C++ formats, which -!> are sufficient to identify which arguments are YAML scalars (single bool/logical, -!> int, double, string/character argument), -!> sequences (single vector argument), or maps (multiple arguments). -!> @htmlonly -!> -!>
-!> CloseFiles(void);
-!> CreateMapping(std::vector< int >& grid2chem);
-!> DumpModule();
-!> FindComponents();
-!> InitialPhreeqc2Module(std::vector< int > initial_conditions1);
-!> InitialPhreeqc2Module(std::vector< int > initial_conditions1, std::vector< int > initial_conditions2, std::vector< double > fraction1);
-!> InitialPhreeqcCell2Module(int n, std::vector< int > cell_numbers);
-!> LoadDatabase(std::string database);
-!> OpenFiles(void);
-!> OutputMessage(std::string str);
-!> RunCells(void);
-!> RunFile(bool workers, bool initial_phreeqc, bool utility, std::string chemistry_name);
-!> RunString(bool workers, bool initial_phreeqc, bool utility, std::string input_string);
-!> ScreenMessage(std::string str);
-!> SetComponentH2O(bool tf);
-!> SetConcentrations(std::vector< double > c);
-!> SetCurrentSelectedOutputUserNumber(int n_user);
-!> SetDensity(std::vector< double > density);
-!> SetDumpFileName(std::string dump_name);
-!> SetErrorHandlerMode(int mode);
-!> SetErrorOn(bool tf);
-!> SetFilePrefix(std::string prefix);
-!> SetGasCompMoles(std::vector< double > gas_moles);
-!> SetGasPhaseVolume(std::vector< double > gas_volume);
-!> SetPartitionUZSolids(bool tf);
-!> SetPorosity(std::vector< double > por);
-!> SetPressure(std::vector< double > p);
-!> SetPrintChemistryMask(std::vector< int > cell_mask);
-!> SetPrintChemistryOn(bool workers, bool initial_phreeqc, bool utility);
-!> SetRebalanceByCell(bool tf);
-!> SetRebalanceFraction(double f);
-!> SetRepresentativeVolume(std::vector< double > rv);
-!> SetSaturation(std::vector< double > sat);
-!> SetScreenOn(bool tf);
-!> SetSelectedOutputOn(bool tf);
-!> SetSpeciesSaveOn(bool save_on);
-!> SetTemperature(std::vector< double > t);
-!> SetTime(double time);
-!> SetTimeConversion(double conv_factor);
-!> SetTimeStep(double time_step);
-!> SetUnitsExchange(int option);
-!> SetUnitsGasPhase(int option);
-!> SetUnitsKinetics(int option);
-!> SetUnitsPPassemblage(int option);
-!> SetUnitsSolution(int option);
-!> SetUnitsSSassemblage(int option);
-!> SetUnitsSurface(int option);
-!> SpeciesConcentrations2Module(std::vector< double > species_conc);
-!> StateSave(int istate);
-!> StateApply(int istate);
-!> StateDelete(int istate);
-!> UseSolutionDensityVolume(bool tf);
-!> WarningMessage(std::string warnstr);
-!> 
-!>
-!> @endhtmlonly -!> -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> 		id = RM_Create(nxyz, MPI_COMM_WORLD)
-!> 		status = RM_InitializeYAML(id, "myfile.yaml")
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root, workers must be in the loop of @ref RM_MpiWorker. - -INTEGER FUNCTION RM_InitializeYAML(id, yaml_name) + !> A YAML file can be used to initialize an instance of PhreeqcRM. + !> @param id The instance @a id returned from @ref RM_Create. + !> @param yaml_name String containing the YAML file name. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @par + !> The file contains a YAML map of PhreeqcRM methods + !> and the arguments corresponding to the methods. + !> Note that the PhreeqcRM methods do not have the "RM_" prefix + !> and the id argument is not included. + !> For example, + !> @par + !> @htmlonly + !> + !>
+    !> LoadDatabase: phreeqc.dat
+    !> RunFile:
+    !> 	workers: true
+    !> 	initial_phreeqc: true
+    !> 	utility: true
+    !> 	chemistry_name: advect.pqi
+    !> 
+ !>
+ !> @endhtmlonly + !> @par + !> @ref RM_InitializeYAML will read the YAML file and execute the specified methods with + !> the specified arguments. Using YAML + !> terminology, the argument(s) for a method may be a scalar, a sequence, or a map, + !> depending if the argument is + !> a single item, a single vector, or there are multiple arguments. + !> In the case of a map, the name associated + !> with each argument (for example "chemistry_name" above) is arbitrary. + !> The names of the map keys for map + !> arguments are not used in parsing the YAML file; only the order of + !> the arguments is important. + !> @par + !> The following list gives the PhreeqcRM methods that can be specified in a YAML file + !> and the arguments that are required. The arguments are described with C++ formats, which + !> are sufficient to identify which arguments are YAML scalars (single bool/logical, + !> int, double, string/character argument), + !> sequences (single vector argument), or maps (multiple arguments). + !> @par + !> @htmlonly + !> + !>
+    !> CloseFiles(void);
+    !> CreateMapping(std::vector< int >& grid2chem);
+    !> DumpModule();
+    !> FindComponents();
+    !> InitialPhreeqc2Module(std::vector< int > initial_conditions1);
+    !> InitialPhreeqc2Module(std::vector< int > initial_conditions1, std::vector< int > initial_conditions2, std::vector< double > fraction1);
+    !> InitialPhreeqcCell2Module(int n, std::vector< int > cell_numbers);
+    !> LoadDatabase(std::string database);
+    !> OpenFiles(void);
+    !> OutputMessage(std::string str);
+    !> RunCells(void);
+    !> RunFile(bool workers, bool initial_phreeqc, bool utility, std::string chemistry_name);
+    !> RunString(bool workers, bool initial_phreeqc, bool utility, std::string input_string);
+    !> ScreenMessage(std::string str);
+    !> SetComponentH2O(bool tf);
+    !> SetConcentrations(std::vector< double > c);
+    !> SetCurrentSelectedOutputUserNumber(int n_user);
+    !> SetDensity(std::vector< double > density);
+    !> SetDumpFileName(std::string dump_name);
+    !> SetErrorHandlerMode(int mode);
+    !> SetErrorOn(bool tf);
+    !> SetFilePrefix(std::string prefix);
+    !> SetGasCompMoles(std::vector< double > gas_moles);
+    !> SetGasPhaseVolume(std::vector< double > gas_volume);
+    !> SetPartitionUZSolids(bool tf);
+    !> SetPorosity(std::vector< double > por);
+    !> SetPressure(std::vector< double > p);
+    !> SetPrintChemistryMask(std::vector< int > cell_mask);
+    !> SetPrintChemistryOn(bool workers, bool initial_phreeqc, bool utility);
+    !> SetRebalanceByCell(bool tf);
+    !> SetRebalanceFraction(double f);
+    !> SetRepresentativeVolume(std::vector< double > rv);
+    !> SetSaturation(std::vector< double > sat);
+    !> SetScreenOn(bool tf);
+    !> SetSelectedOutputOn(bool tf);
+    !> SetSpeciesSaveOn(bool save_on);
+    !> SetTemperature(std::vector< double > t);
+    !> SetTime(double time);
+    !> SetTimeConversion(double conv_factor);
+    !> SetTimeStep(double time_step);
+    !> SetUnitsExchange(int option);
+    !> SetUnitsGasPhase(int option);
+    !> SetUnitsKinetics(int option);
+    !> SetUnitsPPassemblage(int option);
+    !> SetUnitsSolution(int option);
+    !> SetUnitsSSassemblage(int option);
+    !> SetUnitsSurface(int option);
+    !> SpeciesConcentrations2Module(std::vector< double > species_conc);
+    !> StateSave(int istate);
+    !> StateApply(int istate);
+    !> StateDelete(int istate);
+    !> UseSolutionDensityVolume(bool tf);
+    !> WarningMessage(std::string warnstr);
+    !> 
+ !>
+ !> @endhtmlonly + !> + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> 		id = RM_Create(nxyz, MPI_COMM_WORLD)
+    !> 		status = RM_InitializeYAML(id, "myfile.yaml")
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref RM_MpiWorker. + + INTEGER FUNCTION RM_InitializeYAML(id, yaml_name) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_InitializeYAML(id, yaml_name) & - BIND(C, NAME='RMF_InitializeYAML') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - CHARACTER(KIND=C_CHAR), INTENT(in) :: yaml_name(*) - END FUNCTION RMF_InitializeYAML + INTEGER(KIND=C_INT) FUNCTION RMF_InitializeYAML(id, yaml_name) & + BIND(C, NAME='RMF_InitializeYAML') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + CHARACTER(KIND=C_CHAR), INTENT(in) :: yaml_name(*) + END FUNCTION RMF_InitializeYAML END INTERFACE INTEGER, INTENT(in) :: id CHARACTER(len=*), INTENT(in) :: yaml_name RM_InitializeYAML = RMF_InitializeYAML(id, trim(yaml_name)//C_NULL_CHAR) -END FUNCTION RM_InitializeYAML + END FUNCTION RM_InitializeYAML #endif -!> Fills an array (@a bc_conc) with concentrations from solutions in the InitialPhreeqc instance. -!> The method is used to obtain concentrations for boundary conditions. If a negative value -!> is used for a cell in @a bc1, then the highest numbered solution in the InitialPhreeqc instance -!> will be used for that cell. Concentrations may be a mixture of two -!> solutions, @a bc1 and @a bc2, with a mixing fraction for @a bc1 1 of -!> @a f1 and mixing fraction for @a bc2 of (1 - @a f1). -!> A negative value for @a bc2 implies no mixing, and the associated value for @a f1 is ignored. -!> If @a bc2 and @a f1 are omitted, -!> no mixing is used; concentrations are derived from @a bc1 only. -!> -!> @param id The instance @a id returned from @ref RM_Create. -!> @param bc_conc Array of concentrations extracted from the InitialPhreeqc instance. -!> The dimension of @a bc_conc is (@a n_boundary, @a ncomp), -!> where @a ncomp is the number of components returned from @ref RM_FindComponents or @ref RM_GetComponentCount. -!> @param n_boundary The number of boundary condition solutions that need to be filled. -!> @param bc1 Array of solution index numbers that refer to solutions in the InitialPhreeqc instance. -!> Size is @a n_boundary. -!> @param bc2 Array of solution index numbers that that refer to solutions in the InitialPhreeqc instance -!> and are defined to mix with @a bc1. -!> Size is @a n_boundary. Optional in Fortran. -!> @param f1 Fraction of @a bc1 that mixes with (1-@a f1) of @a bc2. -!> Size is (n_boundary). Optional in Fortran. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_FindComponents, -!> @ref RM_GetComponentCount. -!> -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> nbound = 1
-!> allocate(bc1(nbound), bc2(nbound), f1(nbound))
-!> allocate(bc_conc(nbound, ncomps))
-!> bc1 = 0           ! solution 0 from InitialPhreeqc instance
-!> bc2 = -1          ! no bc2 solution for mixing
-!> f1 = 1.0          ! mixing fraction for bc1
-!> status = RM_InitialPhreeqc2Concentrations(id, bc_conc, nbound, bc1, bc2, f1)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root. - -INTEGER FUNCTION RM_InitialPhreeqc2Concentrations(id, bc_conc, n_boundary, bc1, bc2, f1) - USE ISO_C_BINDING - IMPLICIT NONE - INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_InitialPhreeqc2Concentrations(id, bc_conc, n_boundary, bc1) & - BIND(C, NAME='RMF_InitialPhreeqc2Concentrations') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - REAL(KIND=C_DOUBLE), INTENT(OUT) :: bc_conc(*) - INTEGER(KIND=C_INT), INTENT(IN) :: n_boundary, bc1(*) - END FUNCTION RMF_InitialPhreeqc2Concentrations - INTEGER(KIND=C_INT) FUNCTION RMF_InitialPhreeqc2Concentrations2(id, bc_conc, n_boundary, bc1, bc2, f1) & - BIND(C, NAME='RMF_InitialPhreeqc2Concentrations2') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - REAL(KIND=C_DOUBLE), INTENT(OUT) :: bc_conc(*) - INTEGER(KIND=C_INT), INTENT(IN) :: n_boundary, bc1(*) - INTEGER(KIND=C_INT), INTENT(IN) :: bc2(*) - REAL(KIND=C_DOUBLE), INTENT(IN) :: f1(*) - END FUNCTION RMF_InitialPhreeqc2Concentrations2 - END INTERFACE - INTEGER, INTENT(in) :: id - DOUBLE PRECISION, INTENT(OUT), DIMENSION(:,:) :: bc_conc - INTEGER, INTENT(IN) :: n_boundary + !> Fills an array (@a bc_conc) with concentrations from solutions in the InitialPhreeqc instance. + !> The method is used to obtain concentrations for boundary conditions. If a negative value + !> is used for a cell in @a bc1, then the highest numbered solution in the InitialPhreeqc instance + !> will be used for that cell. Concentrations may be a mixture of two + !> solutions, @a bc1 and @a bc2, with a mixing fraction for @a bc1 1 of + !> @a f1 and mixing fraction for @a bc2 of (1 - @a f1). + !> A negative value for @a bc2 implies no mixing, and the associated value for @a f1 is ignored. + !> If @a bc2 and @a f1 are omitted, + !> no mixing is used; concentrations are derived from @a bc1 only. + !> + !> @param id The instance @a id returned from @ref RM_Create. + !> @param bc_conc Array of concentrations extracted from the InitialPhreeqc instance. + !> The dimension of @a bc_conc is (@a n_boundary, @a ncomp), + !> where @a ncomp is the number of components returned from @ref RM_FindComponents or @ref RM_GetComponentCount. + !> @param n_boundary The number of boundary condition solutions that need to be filled. + !> @param bc1 Array of solution index numbers that refer to solutions in the InitialPhreeqc instance. + !> Size is @a n_boundary. + !> @param bc2 Array of solution index numbers that that refer to solutions in the InitialPhreeqc instance + !> and are defined to mix with @a bc1. + !> Size is @a n_boundary. Optional in Fortran. + !> @param f1 Fraction of @a bc1 that mixes with (1-@a f1) of @a bc2. + !> Size is (n_boundary). Optional in Fortran. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_FindComponents, + !> @ref RM_GetComponentCount. + !> + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> nbound = 1
+    !> allocate(bc1(nbound), bc2(nbound), f1(nbound))
+    !> allocate(bc_conc(nbound, ncomps))
+    !> bc1 = 0           ! solution 0 from InitialPhreeqc instance
+    !> bc2 = -1          ! no bc2 solution for mixing
+    !> f1 = 1.0          ! mixing fraction for bc1
+    !> status = RM_InitialPhreeqc2Concentrations(id, bc_conc, nbound, bc1, bc2, f1)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root. + + INTEGER FUNCTION RM_InitialPhreeqc2Concentrations(id, bc_conc, n_boundary, bc1, bc2, f1) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION RMF_InitialPhreeqc2Concentrations(id, bc_conc, n_boundary, bc1) & + BIND(C, NAME='RMF_InitialPhreeqc2Concentrations') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + REAL(KIND=C_DOUBLE), INTENT(OUT) :: bc_conc(*) + INTEGER(KIND=C_INT), INTENT(IN) :: n_boundary, bc1(*) + END FUNCTION RMF_InitialPhreeqc2Concentrations + INTEGER(KIND=C_INT) FUNCTION RMF_InitialPhreeqc2Concentrations2(id, bc_conc, n_boundary, bc1, bc2, f1) & + BIND(C, NAME='RMF_InitialPhreeqc2Concentrations2') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + REAL(KIND=C_DOUBLE), INTENT(OUT) :: bc_conc(*) + INTEGER(KIND=C_INT), INTENT(IN) :: n_boundary, bc1(*) + INTEGER(KIND=C_INT), INTENT(IN) :: bc2(*) + REAL(KIND=C_DOUBLE), INTENT(IN) :: f1(*) + END FUNCTION RMF_InitialPhreeqc2Concentrations2 + END INTERFACE + INTEGER, INTENT(in) :: id + real(kind=8), INTENT(OUT), DIMENSION(:,:) :: bc_conc + INTEGER, INTENT(IN) :: n_boundary INTEGER, INTENT(IN), DIMENSION(:) :: bc1 INTEGER, INTENT(IN), DIMENSION(:) , OPTIONAL :: bc2 - DOUBLE PRECISION, INTENT(IN), DIMENSION(:) , OPTIONAL :: f1 - if (rmf_debug) call Chk_InitialPhreeqc2Concentrations(id, bc_conc, n_boundary, bc1, bc2, f1) + real(kind=8), INTENT(IN), DIMENSION(:) , OPTIONAL :: f1 + if (rmf_debug) call Chk_InitialPhreeqc2Concentrations(id, bc_conc, n_boundary, bc1, bc2, f1) if (present(bc2) .and. present(f1)) then RM_InitialPhreeqc2Concentrations = RMF_InitialPhreeqc2Concentrations2(id, bc_conc, n_boundary, bc1, bc2, f1) else RM_InitialPhreeqc2Concentrations = RMF_InitialPhreeqc2Concentrations(id, bc_conc, n_boundary, bc1) endif -END FUNCTION RM_InitialPhreeqc2Concentrations + END FUNCTION RM_InitialPhreeqc2Concentrations -SUBROUTINE Chk_InitialPhreeqc2Concentrations(id, bc_conc, n_boundary, bc1, bc2, f1) + SUBROUTINE Chk_InitialPhreeqc2Concentrations(id, bc_conc, n_boundary, bc1, bc2, f1) + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION RMF_GetComponentCount(id) & + BIND(C, NAME='RMF_GetComponentCount') + USE ISO_C_BINDING IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + END FUNCTION RMF_GetComponentCount + END INTERFACE INTEGER, INTENT(in) :: id - DOUBLE PRECISION, INTENT(IN), DIMENSION(:,:) :: bc_conc - INTEGER, INTENT(IN) :: n_boundary + real(kind=8), INTENT(IN), DIMENSION(:,:) :: bc_conc + INTEGER, INTENT(IN) :: n_boundary INTEGER, INTENT(IN), DIMENSION(:) :: bc1 INTEGER, INTENT(IN), DIMENSION(:) , OPTIONAL :: bc2 - DOUBLE PRECISION, INTENT(IN), DIMENSION(:) , OPTIONAL :: f1 + real(kind=8), INTENT(IN), DIMENSION(:) , OPTIONAL :: f1 INTEGER :: errors errors = 0 + rmf_ncomps = RMF_GetComponentCount(id) errors = errors + Chk_Double2D(id, bc_conc, n_boundary, rmf_ncomps, "concentration", "RM_InitialPhreeqc2Concentrations") errors = errors + Chk_Integer1D(id, bc1, n_boundary, "bc1", "RM_InitialPhreeqc2Concentrations") if (present(bc2)) then @@ -3805,111 +4143,111 @@ SUBROUTINE Chk_InitialPhreeqc2Concentrations(id, bc_conc, n_boundary, bc1, bc2, if (errors .gt. 0) then errors = RM_Abort(id, -3, "Invalid argument in RM_InitialPhreeqc2Concentrations") endif -END SUBROUTINE Chk_InitialPhreeqc2Concentrations - -!> Transfer solutions and reactants from the InitialPhreeqc instance to the reaction-module workers, possibly with mixing. -!> In its simplest form, @a ic1 is used to select initial conditions, including solutions and reactants, -!> for each cell of the model, without mixing. -!> @a ic1 is dimensioned (@a nxyz, 7), where @a nxyz is the number of grid cells in the user's model -!> (@ref RM_GetGridCellCount). The dimension of 7 refers to solutions and reactants in the following order: -!> (1) SOLUTIONS, (2) EQUILIBRIUM_PHASES, (3) EXCHANGE, (4) SURFACE, (5) GAS_PHASE, -!> (6) SOLID_SOLUTIONS, and (7) KINETICS. In Fortran, ic1(100, 4) = 2, indicates that -!> cell 99 (0 based) contains the SURFACE definition with user number 2 that has been defined in the -!> InitialPhreeqc instance (either by @ref RM_RunFile or @ref RM_RunString). -!> @n@n -!> It is also possible to mix solutions and reactants to obtain the initial conditions for cells. For mixing, -!> @a ic2 contains numbers for a second entity that mixes with the entity defined in @a ic1. -!> @a F1 contains the mixing fraction for @a ic1, whereas (1 - @a f1) is the mixing fraction for -!> @a ic2. -!> In Fortran, ic1(100, 4) = 2, initial_conditions2(100, 4) = 3, f1(100, 4) = 0.25 indicates that -!> cell 99 (0 based) contains a mixture of 0.25 SURFACE 2 and 0.75 SURFACE 3, where the surface -!> compositions have been defined in the InitialPhreeqc instance. -!> If the user number in @a ic2 is negative, no mixing occurs. -!> If @a ic2 and @a f1 are omitted, -!> no mixing is used, and initial conditions are derived solely from @a ic1. -!> -!> @param id The instance @a id returned from @ref RM_Create. -!> @param ic1 Array of solution and reactant index numbers that refer to definitions in the InitialPhreeqc instance. -!> Size is (@a nxyz,7). The order of definitions is given above. -!> Negative values are ignored, resulting in no definition of that entity for that cell. -!> @param ic2 Array of solution and reactant index numbers that refer to definitions in the InitialPhreeqc instance. -!> Nonnegative values of @a ic2 result in mixing with the entities defined in @a ic1. -!> Negative values result in no mixing. -!> Size is (@a nxyz,7). The order of definitions is given above. -!> Optional in Fortran; omitting results in no mixing. -!> @param f1 Fraction of ic1 that mixes with (1-@a f1) of ic2. -!> Size is (nxyz,7). The order of definitions is given above. -!> Optional in Fortran; omitting results in no mixing. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_InitialPhreeqcCell2Module. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> allocate(ic1(nxyz,7), ic2(nxyz,7), f1(nxyz,7))
-!> ic1 = -1
-!> ic2 = -1
-!> f1 = 1.0
-!> do i = 1, nxyz
-!>   ic1(i,1) = 1       ! Solution 1
-!>   ic1(i,2) = -1      ! Equilibrium phases none
-!>   ic1(i,3) = 1       ! Exchange 1
-!>   ic1(i,4) = -1      ! Surface none
-!>   ic1(i,5) = -1      ! Gas phase none
-!>   ic1(i,6) = -1      ! Solid solutions none
-!>   ic1(i,7) = -1      ! Kinetics none
-!> enddo
-!> status = RM_InitialPhreeqc2Module(id, ic1, ic2, f1)1))
-!> ! No mixing is defined, so the following is equivalent
-!> status = RM_InitialPhreeqc2Module(id, ic1)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root, workers must be in the loop of @ref RM_MpiWorker. - -INTEGER FUNCTION RM_InitialPhreeqc2Module(id, ic1, ic2, f1) + END SUBROUTINE Chk_InitialPhreeqc2Concentrations + + !> Transfer solutions and reactants from the InitialPhreeqc instance to the reaction-module workers, possibly with mixing. + !> In its simplest form, @a ic1 is used to select initial conditions, including solutions and reactants, + !> for each cell of the model, without mixing. + !> @a ic1 is dimensioned (@a nxyz, 7), where @a nxyz is the number of grid cells in the user's model + !> (@ref RM_GetGridCellCount). The dimension of 7 refers to solutions and reactants in the following order: + !> (1) SOLUTIONS, (2) EQUILIBRIUM_PHASES, (3) EXCHANGE, (4) SURFACE, (5) GAS_PHASE, + !> (6) SOLID_SOLUTIONS, and (7) KINETICS. In Fortran, ic1(100, 4) = 2, indicates that + !> cell 99 (0 based) contains the SURFACE definition with user number 2 that has been defined in the + !> InitialPhreeqc instance (either by @ref RM_RunFile or @ref RM_RunString). + !> @n@n + !> It is also possible to mix solutions and reactants to obtain the initial conditions for cells. For mixing, + !> @a ic2 contains numbers for a second entity that mixes with the entity defined in @a ic1. + !> @a F1 contains the mixing fraction for @a ic1, whereas (1 - @a f1) is the mixing fraction for + !> @a ic2. + !> In Fortran, ic1(100, 4) = 2, initial_conditions2(100, 4) = 3, f1(100, 4) = 0.25 indicates that + !> cell 99 (0 based) contains a mixture of 0.25 SURFACE 2 and 0.75 SURFACE 3, where the surface + !> compositions have been defined in the InitialPhreeqc instance. + !> If the user number in @a ic2 is negative, no mixing occurs. + !> If @a ic2 and @a f1 are omitted, + !> no mixing is used, and initial conditions are derived solely from @a ic1. + !> + !> @param id The instance @a id returned from @ref RM_Create. + !> @param ic1 Array of solution and reactant index numbers that refer to definitions in the InitialPhreeqc instance. + !> Size is (@a nxyz,7). The order of definitions is given above. + !> Negative values are ignored, resulting in no definition of that entity for that cell. + !> @param ic2 Array of solution and reactant index numbers that refer to definitions in the InitialPhreeqc instance. + !> Nonnegative values of @a ic2 result in mixing with the entities defined in @a ic1. + !> Negative values result in no mixing. + !> Size is (@a nxyz,7). The order of definitions is given above. + !> Optional in Fortran; omitting results in no mixing. + !> @param f1 Fraction of ic1 that mixes with (1-@a f1) of ic2. + !> Size is (nxyz,7). The order of definitions is given above. + !> Optional in Fortran; omitting results in no mixing. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_InitialPhreeqcCell2Module. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> allocate(ic1(nxyz,7), ic2(nxyz,7), f1(nxyz,7))
+    !> ic1 = -1
+    !> ic2 = -1
+    !> f1 = 1.0
+    !> do i = 1, nxyz
+    !>   ic1(i,1) = 1       ! Solution 1
+    !>   ic1(i,2) = -1      ! Equilibrium phases none
+    !>   ic1(i,3) = 1       ! Exchange 1
+    !>   ic1(i,4) = -1      ! Surface none
+    !>   ic1(i,5) = -1      ! Gas phase none
+    !>   ic1(i,6) = -1      ! Solid solutions none
+    !>   ic1(i,7) = -1      ! Kinetics none
+    !> enddo
+    !> status = RM_InitialPhreeqc2Module(id, ic1, ic2, f1)1))
+    !> ! No mixing is defined, so the following is equivalent
+    !> status = RM_InitialPhreeqc2Module(id, ic1)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref RM_MpiWorker. + + INTEGER FUNCTION RM_InitialPhreeqc2Module(id, ic1, ic2, f1) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_InitialPhreeqc2Module(id, ic1) & - BIND(C, NAME='RMF_InitialPhreeqc2Module') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - INTEGER(KIND=C_INT), INTENT(in) :: ic1(*) - END FUNCTION RMF_InitialPhreeqc2Module + INTEGER(KIND=C_INT) FUNCTION RMF_InitialPhreeqc2Module(id, ic1) & + BIND(C, NAME='RMF_InitialPhreeqc2Module') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + INTEGER(KIND=C_INT), INTENT(in) :: ic1(*) + END FUNCTION RMF_InitialPhreeqc2Module END INTERFACE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_InitialPhreeqc2Module2(id, ic1, ic2, f1) & - BIND(C, NAME='RMF_InitialPhreeqc2Module2') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - INTEGER(KIND=C_INT), INTENT(in) :: ic1(*) - INTEGER(KIND=C_INT), INTENT(in) :: ic2(*) - REAL(KIND=C_DOUBLE), INTENT(in) :: f1(*) - END FUNCTION RMF_InitialPhreeqc2Module2 + INTEGER(KIND=C_INT) FUNCTION RMF_InitialPhreeqc2Module2(id, ic1, ic2, f1) & + BIND(C, NAME='RMF_InitialPhreeqc2Module2') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + INTEGER(KIND=C_INT), INTENT(in) :: ic1(*) + INTEGER(KIND=C_INT), INTENT(in) :: ic2(*) + REAL(KIND=C_DOUBLE), INTENT(in) :: f1(*) + END FUNCTION RMF_InitialPhreeqc2Module2 END INTERFACE INTEGER, INTENT(in) :: id INTEGER, INTENT(in), DIMENSION(:,:) :: ic1 INTEGER, INTENT(in), DIMENSION(:,:), OPTIONAL :: ic2 - DOUBLE PRECISION, INTENT(in), DIMENSION(:,:), OPTIONAL :: f1 + real(kind=8), INTENT(in), DIMENSION(:,:), OPTIONAL :: f1 if (rmf_debug) call Chk_InitialPhreeqc2Module(id, ic1, ic2, f1) if (present(ic2) .and. present(f1)) then RM_InitialPhreeqc2Module = RMF_InitialPhreeqc2Module2(id, ic1, ic2, f1) else - RM_InitialPhreeqc2Module = RMF_InitialPhreeqc2Module(id, ic1) - endif -END FUNCTION RM_InitialPhreeqc2Module + RM_InitialPhreeqc2Module = RMF_InitialPhreeqc2Module(id, ic1) + endif + END FUNCTION RM_InitialPhreeqc2Module -SUBROUTINE Chk_InitialPhreeqc2Module(id, ic1, ic2, f1) + SUBROUTINE Chk_InitialPhreeqc2Module(id, ic1, ic2, f1) IMPLICIT NONE INTEGER, INTENT(in) :: id INTEGER, INTENT(IN), DIMENSION(:,:) :: ic1 INTEGER, INTENT(IN), DIMENSION(:,:) , OPTIONAL :: ic2 - DOUBLE PRECISION, INTENT(IN), DIMENSION(:,:) , OPTIONAL :: f1 + real(kind=8), INTENT(IN), DIMENSION(:,:) , OPTIONAL :: f1 INTEGER :: errors errors = 0 errors = errors + Chk_Integer2D(id, ic1, rmf_nxyz, 7, "ic1", "RM_InitialPhreeqc2Module") @@ -3922,85 +4260,85 @@ SUBROUTINE Chk_InitialPhreeqc2Module(id, ic1, ic2, f1) if (errors .gt. 0) then errors = RM_Abort(id, -3, "Invalid argument in RM_InitialPhreeqc2Module") endif -END SUBROUTINE Chk_InitialPhreeqc2Module - -!> Fills an array (@a bc_conc) with aqueous species concentrations from solutions in the InitialPhreeqc instance. -!> This method is intended for use with multicomponent-diffusion transport calculations, -!> and @ref RM_SetSpeciesSaveOn must be set to @a true. -!> The method is used to obtain aqueous species concentrations for boundary conditions. If a negative value -!> is used for a cell in @a bc1, then the highest numbered solution in the InitialPhreeqc instance -!> will be used for that cell. -!> Concentrations may be a mixture of two -!> solutions, @a bc1 and @a bc2, with a mixing fraction for @a bc1 of -!> @a f1 and mixing fraction for @a bc2 of (1 - @a f1). -!> A negative value for @a bc2 implies no mixing, and the associated value for @a f1 is ignored. -!> If @a bc2 and @a f1 are omitted, -!> no mixing is used; concentrations are derived from @a bc1 only. -!> -!> @param id The instance @a id returned from @ref RM_Create. -!> @param bc_conc Array of aqueous concentrations extracted from the InitialPhreeqc instance. -!> The dimension of @a species_c is (@a n_boundary, @a nspecies), -!> where @a nspecies is the number of aqueous species returned from @ref RM_GetSpeciesCount. -!> @param n_boundary The number of boundary condition solutions that need to be filled. -!> @param bc1 Array of solution index numbers that refer to solutions in the InitialPhreeqc instance. -!> Size is @a n_boundary. -!> @param bc2 Array of solution index numbers that that refer to solutions in the InitialPhreeqc instance -!> and are defined to mix with @a bc1. -!> Size is @a n_boundary. Optional in Fortran. -!> @param f1 Fraction of @a bc1 that mixes with (1-@a f1) of @a bc2. -!> Size is @a n_boundary. Optional in Fortran. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_FindComponents, -!> @ref RM_GetSpeciesCount, -!> @ref RM_SetSpeciesSaveOn. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> nbound = 1
-!> allocate(bc1(nbound), bc2(nbound), f1(nbound))
-!> allocate(bc_conc(nbound, ncomps))
-!> bc1 = 0           ! solution 0 from InitialPhreeqc instance
-!> bc2 = -1          ! no bc2 solution for mixing
-!> f1 = 1.0          ! mixing fraction for bc1
-!> status = RM_InitialPhreeqc2SpeciesConcentrations(id, bc_conc, nbound, bc1, bc2, f1)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root. - -INTEGER FUNCTION RM_InitialPhreeqc2SpeciesConcentrations(id, bc_conc, n_boundary, bc1, bc2, f1) - USE ISO_C_BINDING - IMPLICIT NONE - INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_InitialPhreeqc2SpeciesConcentrations(id, bc_conc, n_boundary, bc1) & - BIND(C, NAME='RMF_InitialPhreeqc2SpeciesConcentrations') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - REAL(KIND=C_DOUBLE), INTENT(OUT) :: bc_conc(*) - INTEGER(KIND=C_INT), INTENT(IN) :: n_boundary, bc1(*) - END FUNCTION RMF_InitialPhreeqc2SpeciesConcentrations - INTEGER(KIND=C_INT) FUNCTION RMF_InitialPhreeqc2SpeciesConcentrations2(id, bc_conc, n_boundary, bc1, bc2, f1) & - BIND(C, NAME='RMF_InitialPhreeqc2SpeciesConcentrations2') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - REAL(KIND=C_DOUBLE), INTENT(OUT) :: bc_conc(*) - INTEGER(KIND=C_INT), INTENT(IN) :: n_boundary, bc1(*) - INTEGER(KIND=C_INT), INTENT(IN) :: bc2(*) - REAL(KIND=C_DOUBLE), INTENT(IN) :: f1(*) - END FUNCTION RMF_InitialPhreeqc2SpeciesConcentrations2 - END INTERFACE - INTEGER, INTENT(in) :: id - DOUBLE PRECISION, DIMENSION(:,:), INTENT(OUT) :: bc_conc + END SUBROUTINE Chk_InitialPhreeqc2Module + + !> Fills an array (@a bc_conc) with aqueous species concentrations from solutions in the InitialPhreeqc instance. + !> This method is intended for use with multicomponent-diffusion transport calculations, + !> and @ref RM_SetSpeciesSaveOn must be set to @a true. + !> The method is used to obtain aqueous species concentrations for boundary conditions. If a negative value + !> is used for a cell in @a bc1, then the highest numbered solution in the InitialPhreeqc instance + !> will be used for that cell. + !> Concentrations may be a mixture of two + !> solutions, @a bc1 and @a bc2, with a mixing fraction for @a bc1 of + !> @a f1 and mixing fraction for @a bc2 of (1 - @a f1). + !> A negative value for @a bc2 implies no mixing, and the associated value for @a f1 is ignored. + !> If @a bc2 and @a f1 are omitted, + !> no mixing is used; concentrations are derived from @a bc1 only. + !> + !> @param id The instance @a id returned from @ref RM_Create. + !> @param bc_conc Array of aqueous concentrations extracted from the InitialPhreeqc instance. + !> The dimension of @a species_c is (@a n_boundary, @a nspecies), + !> where @a nspecies is the number of aqueous species returned from @ref RM_GetSpeciesCount. + !> @param n_boundary The number of boundary condition solutions that need to be filled. + !> @param bc1 Array of solution index numbers that refer to solutions in the InitialPhreeqc instance. + !> Size is @a n_boundary. + !> @param bc2 Array of solution index numbers that that refer to solutions in the InitialPhreeqc instance + !> and are defined to mix with @a bc1. + !> Size is @a n_boundary. Optional in Fortran. + !> @param f1 Fraction of @a bc1 that mixes with (1-@a f1) of @a bc2. + !> Size is @a n_boundary. Optional in Fortran. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_FindComponents, + !> @ref RM_GetSpeciesCount, + !> @ref RM_SetSpeciesSaveOn. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> nbound = 1
+    !> allocate(bc1(nbound), bc2(nbound), f1(nbound))
+    !> allocate(bc_conc(nbound, ncomps))
+    !> bc1 = 0           ! solution 0 from InitialPhreeqc instance
+    !> bc2 = -1          ! no bc2 solution for mixing
+    !> f1 = 1.0          ! mixing fraction for bc1
+    !> status = RM_InitialPhreeqc2SpeciesConcentrations(id, bc_conc, nbound, bc1, bc2, f1)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root. + + INTEGER FUNCTION RM_InitialPhreeqc2SpeciesConcentrations(id, bc_conc, n_boundary, bc1, bc2, f1) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION RMF_InitialPhreeqc2SpeciesConcentrations(id, bc_conc, n_boundary, bc1) & + BIND(C, NAME='RMF_InitialPhreeqc2SpeciesConcentrations') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + REAL(KIND=C_DOUBLE), INTENT(OUT) :: bc_conc(*) + INTEGER(KIND=C_INT), INTENT(IN) :: n_boundary, bc1(*) + END FUNCTION RMF_InitialPhreeqc2SpeciesConcentrations + INTEGER(KIND=C_INT) FUNCTION RMF_InitialPhreeqc2SpeciesConcentrations2(id, bc_conc, n_boundary, bc1, bc2, f1) & + BIND(C, NAME='RMF_InitialPhreeqc2SpeciesConcentrations2') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + REAL(KIND=C_DOUBLE), INTENT(OUT) :: bc_conc(*) + INTEGER(KIND=C_INT), INTENT(IN) :: n_boundary, bc1(*) + INTEGER(KIND=C_INT), INTENT(IN) :: bc2(*) + REAL(KIND=C_DOUBLE), INTENT(IN) :: f1(*) + END FUNCTION RMF_InitialPhreeqc2SpeciesConcentrations2 + END INTERFACE + INTEGER, INTENT(in) :: id + real(kind=8), DIMENSION(:,:), INTENT(OUT) :: bc_conc INTEGER, INTENT(IN) :: n_boundary INTEGER, INTENT(IN), DIMENSION(:) :: bc1 INTEGER, INTENT(IN), DIMENSION(:), OPTIONAL :: bc2 - DOUBLE PRECISION, INTENT(IN), DIMENSION(:), OPTIONAL :: f1 - if (rmf_debug) call Chk_InitialPhreeqc2SpeciesConcentrations(id, bc_conc, n_boundary, bc1, bc2, f1) + real(kind=8), INTENT(IN), DIMENSION(:), OPTIONAL :: f1 + if (rmf_debug) call Chk_InitialPhreeqc2SpeciesConcentrations(id, bc_conc, n_boundary, bc1, bc2, f1) if (present(bc2) .and. present(f1)) then RM_InitialPhreeqc2SpeciesConcentrations = & RMF_InitialPhreeqc2SpeciesConcentrations2(id, bc_conc, n_boundary, bc1, bc2, f1) @@ -4008,16 +4346,16 @@ END FUNCTION RMF_InitialPhreeqc2SpeciesConcentrations2 RM_InitialPhreeqc2SpeciesConcentrations = & RMF_InitialPhreeqc2SpeciesConcentrations(id, bc_conc, n_boundary, bc1) endif -END FUNCTION RM_InitialPhreeqc2SpeciesConcentrations + END FUNCTION RM_InitialPhreeqc2SpeciesConcentrations -SUBROUTINE Chk_InitialPhreeqc2SpeciesConcentrations(id, bc_conc, n_boundary, bc1, bc2, f1) + SUBROUTINE Chk_InitialPhreeqc2SpeciesConcentrations(id, bc_conc, n_boundary, bc1, bc2, f1) IMPLICIT NONE INTEGER, INTENT(in) :: id - DOUBLE PRECISION, INTENT(IN), DIMENSION(:,:) :: bc_conc - INTEGER, INTENT(IN) :: n_boundary + real(kind=8), INTENT(IN), DIMENSION(:,:) :: bc_conc + INTEGER, INTENT(IN) :: n_boundary INTEGER, INTENT(IN), DIMENSION(:) :: bc1 INTEGER, INTENT(IN), DIMENSION(:) , OPTIONAL :: bc2 - DOUBLE PRECISION, INTENT(IN), DIMENSION(:) , OPTIONAL :: f1 + real(kind=8), INTENT(IN), DIMENSION(:) , OPTIONAL :: f1 INTEGER :: errors, nspecies nspecies = RM_GetSpeciesCount(id) errors = 0 @@ -4032,52 +4370,52 @@ SUBROUTINE Chk_InitialPhreeqc2SpeciesConcentrations(id, bc_conc, n_boundary, bc1 if (errors .gt. 0) then errors = RM_Abort(id, -3, "Invalid argument in RM_InitialPhreeqc2SpeciesConcentrations") endif -END SUBROUTINE Chk_InitialPhreeqc2SpeciesConcentrations - -!> A cell numbered @a n_user in the InitialPhreeqc instance is selected to populate a series of cells. -!> All reactants with the number @a n_user are transferred along with the solution. -!> If MIX @a n_user exists, it is used for the definition of the solution. -!> If @a n_user is negative, @a n_user is redefined to be the largest solution or MIX number in the InitialPhreeqc instance. -!> All reactants for each cell in the list @a cell_numbers are removed before the cell -!> definition is copied from the InitialPhreeqc instance to the workers. -!> @param id The instance @a id returned from @ref RM_Create. -!> @param n_user Cell number refers to a solution or MIX and associated reactants in the InitialPhreeqc instance. -!> A negative number indicates the largest solution or MIX number in the InitialPhreeqc instance will be used. -!> @param cell_numbers A list of cell numbers in the user's grid-cell numbering system that will be populated with -!> cell @a n_user from the InitialPhreeqc instance. -!> @param n_cell The number of cell numbers in the @a cell_numbers list. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_InitialPhreeqc2Module. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> allocate (cell_numbers(2))
-!> cell_numbers(1) = 18
-!> cell_numbers(2) = 19
-!> ! n will be the largest SOLUTION number in InitialPhreeqc instance
-!> ! copies solution and reactants to cells 18 and 19
-!> status = RM_InitialPhreeqcCell2Module(id, -1, cell_numbers, 2)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root, workers must be in the loop of @ref RM_MpiWorker. - -INTEGER FUNCTION RM_InitialPhreeqcCell2Module(id, n_user, cell_numbers, n_cell) + END SUBROUTINE Chk_InitialPhreeqc2SpeciesConcentrations + + !> A cell numbered @a n_user in the InitialPhreeqc instance is selected to populate a series of cells. + !> All reactants with the number @a n_user are transferred along with the solution. + !> If MIX @a n_user exists, it is used for the definition of the solution. + !> If @a n_user is negative, @a n_user is redefined to be the largest solution or MIX number in the InitialPhreeqc instance. + !> All reactants for each cell in the list @a cell_numbers are removed before the cell + !> definition is copied from the InitialPhreeqc instance to the workers. + !> @param id The instance @a id returned from @ref RM_Create. + !> @param n_user Cell number refers to a solution or MIX and associated reactants in the InitialPhreeqc instance. + !> A negative number indicates the largest solution or MIX number in the InitialPhreeqc instance will be used. + !> @param cell_numbers A list of cell numbers in the user's grid-cell numbering system that will be populated with + !> cell @a n_user from the InitialPhreeqc instance. + !> @param n_cell The number of cell numbers in the @a cell_numbers list. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_InitialPhreeqc2Module. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> allocate (cell_numbers(2))
+    !> cell_numbers(1) = 18
+    !> cell_numbers(2) = 19
+    !> ! n will be the largest SOLUTION number in InitialPhreeqc instance
+    !> ! copies solution and reactants to cells 18 and 19
+    !> status = RM_InitialPhreeqcCell2Module(id, -1, cell_numbers, 2)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref RM_MpiWorker. + + INTEGER FUNCTION RM_InitialPhreeqcCell2Module(id, n_user, cell_numbers, n_cell) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_InitialPhreeqcCell2Module(id, n_user, cell_numbers, n_cell) & - BIND(C, NAME='RMF_InitialPhreeqcCell2Module') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - INTEGER(KIND=C_INT), INTENT(in) :: n_user - INTEGER(KIND=C_INT), INTENT(in) :: cell_numbers(*) - INTEGER(KIND=C_INT), INTENT(in) :: n_cell - END FUNCTION RMF_InitialPhreeqcCell2Module + INTEGER(KIND=C_INT) FUNCTION RMF_InitialPhreeqcCell2Module(id, n_user, cell_numbers, n_cell) & + BIND(C, NAME='RMF_InitialPhreeqcCell2Module') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + INTEGER(KIND=C_INT), INTENT(in) :: n_user + INTEGER(KIND=C_INT), INTENT(in) :: cell_numbers(*) + INTEGER(KIND=C_INT), INTENT(in) :: n_cell + END FUNCTION RMF_InitialPhreeqcCell2Module END INTERFACE INTEGER, INTENT(in) :: id INTEGER, INTENT(in) :: n_user @@ -4085,9 +4423,9 @@ END FUNCTION RMF_InitialPhreeqcCell2Module INTEGER, INTENT(in) :: n_cell if (rmf_debug) call Chk_InitialPhreeqcCell2Module(id, n_user, cell_numbers, n_cell) RM_InitialPhreeqcCell2Module = RMF_InitialPhreeqcCell2Module(id, n_user, cell_numbers, n_cell) -END FUNCTION RM_InitialPhreeqcCell2Module + END FUNCTION RM_InitialPhreeqcCell2Module -SUBROUTINE Chk_InitialPhreeqcCell2Module(id, n_user, cell_numbers, n_cell) + SUBROUTINE Chk_InitialPhreeqcCell2Module(id, n_user, cell_numbers, n_cell) IMPLICIT NONE INTEGER, INTENT(in) :: id, n_user, n_cell INTEGER, INTENT(in), DIMENSION(:) :: cell_numbers @@ -4097,1352 +4435,1360 @@ SUBROUTINE Chk_InitialPhreeqcCell2Module(id, n_user, cell_numbers, n_cell) if (errors .gt. 0) then errors = RM_Abort(id, -3, "Invalid argument in RM_InitialPhreeqcCell2Module") endif -END SUBROUTINE Chk_InitialPhreeqcCell2Module - -!> Load a database for all IPhreeqc instances--workers, InitialPhreeqc, and Utility. All definitions -!> of the reaction module are cleared (SOLUTION_SPECIES, PHASES, SOLUTIONs, etc.), and the database is read. -!> @param id The instance @a id returned from @ref RM_Create. -!> @param db_name String containing the database name. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_Create. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> status = RM_LoadDatabase(id, "phreeqc.dat")
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root, workers must be in the loop of @ref RM_MpiWorker. - -INTEGER FUNCTION RM_LoadDatabase(id, db_name) + END SUBROUTINE Chk_InitialPhreeqcCell2Module + + !> Load a database for all IPhreeqc instances--workers, InitialPhreeqc, and Utility. All definitions + !> of the reaction module are cleared (SOLUTION_SPECIES, PHASES, SOLUTIONs, etc.), and the database is read. + !> @param id The instance @a id returned from @ref RM_Create. + !> @param db_name String containing the database name. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_Create. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> status = RM_LoadDatabase(id, "phreeqc.dat")
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref RM_MpiWorker. + + INTEGER FUNCTION RM_LoadDatabase(id, db_name) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_LoadDatabase(id, db_name) & - BIND(C, NAME='RMF_LoadDatabase') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - CHARACTER(KIND=C_CHAR), INTENT(in) :: db_name(*) - END FUNCTION RMF_LoadDatabase + INTEGER(KIND=C_INT) FUNCTION RMF_LoadDatabase(id, db_name) & + BIND(C, NAME='RMF_LoadDatabase') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + CHARACTER(KIND=C_CHAR), INTENT(in) :: db_name(*) + END FUNCTION RMF_LoadDatabase END INTERFACE INTEGER, INTENT(in) :: id CHARACTER(len=*), INTENT(in) :: db_name RM_LoadDatabase = RMF_LoadDatabase(id, trim(db_name)//C_NULL_CHAR) -END FUNCTION RM_LoadDatabase - -!> Print a message to the log file. -!> @param id The instance @a id returned from @ref RM_Create. -!> @param str String to be printed. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_ErrorMessage, -!> @ref RM_OpenFiles, -!> @ref RM_OutputMessage, -!> @ref RM_ScreenMessage, -!> @ref RM_WarningMessage. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> write(string, "(A32,F15.1,A)") "Beginning transport calculation ", &
-!>       RM_GetTime(id) * RM_GetTimeConversion(id), " days"
-!> status = RM_LogMessage(id, string)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root. - -INTEGER FUNCTION RM_LogMessage(id, str) + END FUNCTION RM_LoadDatabase + + !> Print a message to the log file. + !> @param id The instance @a id returned from @ref RM_Create. + !> @param str String to be printed. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_ErrorMessage, + !> @ref RM_OpenFiles, + !> @ref RM_OutputMessage, + !> @ref RM_ScreenMessage, + !> @ref RM_WarningMessage. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> write(string, "(A32,F15.1,A)") "Beginning transport calculation ", &
+    !>       RM_GetTime(id) * RM_GetTimeConversion(id), " days"
+    !> status = RM_LogMessage(id, string)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root. + + INTEGER FUNCTION RM_LogMessage(id, str) USE ISO_C_BINDING IMPLICIT NONE - INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_LogMessage(id, str) & - BIND(C, NAME='RMF_LogMessage') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - CHARACTER(KIND=C_CHAR), INTENT(in) :: str(*) - END FUNCTION RMF_LogMessage - END INTERFACE - INTEGER, INTENT(in) :: id - CHARACTER(len=*), INTENT(in) :: str - RM_LogMessage = RMF_LogMessage(id, trim(str)//C_NULL_CHAR) -END FUNCTION RM_LogMessage - -!> MPI only. Workers (processes with @ref RM_GetMpiMyself > 0) must call RM_MpiWorker to be able to -!> respond to messages from the root to accept data, perform calculations, and -!> (or) return data. RM_MpiWorker contains a loop that reads a message from root, performs a -!> task, and waits for another message from root. @ref RM_SetConcentrations, @ref RM_RunCells, and @ref RM_GetConcentrations -!> are examples of methods that send a message from root to get the workers to perform a task. The workers will -!> respond to all methods that are designated "workers must be in the loop of RM_MpiWorker" in the -!> MPI section of the method documentation. -!> The workers will continue to respond to messages from root until root calls -!> @ref RM_MpiWorkerBreak. -!> @n@n -!> (Advanced) The list of tasks that the workers perform can be extended by using @ref RM_SetMpiWorkerCallback. -!> It is then possible to use the MPI processes to perform other developer-defined tasks, such as transport calculations, without -!> exiting from the RM_MpiWorker loop. Alternatively, root calls @ref RM_MpiWorkerBreak to allow the workers to continue -!> past a call to RM_MpiWorker. The workers perform developer-defined calculations, and then RM_MpiWorker is called again to respond to -!> requests from root to perform reaction-module tasks. -!> -!> @param id The instance @a id returned from @ref RM_Create. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). RM_MpiWorker returns a value only when -!> @ref RM_MpiWorkerBreak is called by root. -!> @see -!> @ref RM_MpiWorkerBreak, -!> @ref RM_SetMpiWorkerCallback. -!> -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> status = RM_MpiWorker(id)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by all workers. - -INTEGER FUNCTION RM_MpiWorker(id) + INTERFACE + INTEGER(KIND=C_INT) FUNCTION RMF_LogMessage(id, str) & + BIND(C, NAME='RMF_LogMessage') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + CHARACTER(KIND=C_CHAR), INTENT(in) :: str(*) + END FUNCTION RMF_LogMessage + END INTERFACE + INTEGER, INTENT(in) :: id + CHARACTER(len=*), INTENT(in) :: str + RM_LogMessage = RMF_LogMessage(id, trim(str)//C_NULL_CHAR) + END FUNCTION RM_LogMessage + + !> MPI only. Workers (processes with @ref RM_GetMpiMyself > 0) must call RM_MpiWorker to be able to + !> respond to messages from the root to accept data, perform calculations, and + !> (or) return data. RM_MpiWorker contains a loop that reads a message from root, performs a + !> task, and waits for another message from root. @ref RM_SetConcentrations, @ref RM_RunCells, and @ref RM_GetConcentrations + !> are examples of methods that send a message from root to get the workers to perform a task. The workers will + !> respond to all methods that are designated "workers must be in the loop of RM_MpiWorker" in the + !> MPI section of the method documentation. + !> The workers will continue to respond to messages from root until root calls + !> @ref RM_MpiWorkerBreak. + !> @n@n + !> (Advanced) The list of tasks that the workers perform can be extended by using @ref RM_SetMpiWorkerCallback. + !> It is then possible to use the MPI processes to perform other developer-defined tasks, such as transport calculations, without + !> exiting from the RM_MpiWorker loop. Alternatively, root calls @ref RM_MpiWorkerBreak to allow the workers to continue + !> past a call to RM_MpiWorker. The workers perform developer-defined calculations, and then RM_MpiWorker is called again to respond to + !> requests from root to perform reaction-module tasks. + !> + !> @param id The instance @a id returned from @ref RM_Create. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). RM_MpiWorker returns a value only when + !> @ref RM_MpiWorkerBreak is called by root. + !> @see + !> @ref RM_MpiWorkerBreak, + !> @ref RM_SetMpiWorkerCallback. + !> + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> status = RM_MpiWorker(id)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by all workers. + + INTEGER FUNCTION RM_MpiWorker(id) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_MpiWorker(id) & - BIND(C, NAME='RMF_MpiWorker') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - END FUNCTION RMF_MpiWorker + INTEGER(KIND=C_INT) FUNCTION RMF_MpiWorker(id) & + BIND(C, NAME='RMF_MpiWorker') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + END FUNCTION RMF_MpiWorker END INTERFACE INTEGER, INTENT(in) :: id RM_MpiWorker = RMF_MpiWorker(id) -END FUNCTION RM_MpiWorker - -!> MPI only. This method is called by root to force workers (processes with @ref RM_GetMpiMyself > 0) -!> to return from a call to @ref RM_MpiWorker. -!> @ref RM_MpiWorker contains a loop that reads a message from root, performs a -!> task, and waits for another message from root. The workers respond to all methods that are designated -!> "workers must be in the loop of RM_MpiWorker" in the -!> MPI section of the method documentation. -!> The workers will continue to respond to messages from root until root calls RM_MpiWorkerBreak. -!> @param id The instance @a id returned from @ref RM_Create. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_MpiWorker, -!> @ref RM_SetMpiWorkerCallback. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> status = RM_MpiWorkerBreak(id)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root. - -INTEGER FUNCTION RM_MpiWorkerBreak(id) + END FUNCTION RM_MpiWorker + + !> MPI only. This method is called by root to force workers (processes with @ref RM_GetMpiMyself > 0) + !> to return from a call to @ref RM_MpiWorker. + !> @ref RM_MpiWorker contains a loop that reads a message from root, performs a + !> task, and waits for another message from root. The workers respond to all methods that are designated + !> "workers must be in the loop of RM_MpiWorker" in the + !> MPI section of the method documentation. + !> The workers will continue to respond to messages from root until root calls RM_MpiWorkerBreak. + !> @param id The instance @a id returned from @ref RM_Create. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_MpiWorker, + !> @ref RM_SetMpiWorkerCallback. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> status = RM_MpiWorkerBreak(id)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root. + + INTEGER FUNCTION RM_MpiWorkerBreak(id) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_MpiWorkerBreak(id) & - BIND(C, NAME='RMF_MpiWorkerBreak') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - END FUNCTION RMF_MpiWorkerBreak + INTEGER(KIND=C_INT) FUNCTION RMF_MpiWorkerBreak(id) & + BIND(C, NAME='RMF_MpiWorkerBreak') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + END FUNCTION RMF_MpiWorkerBreak END INTERFACE INTEGER, INTENT(in) :: id RM_MpiWorkerBreak = RMF_MpiWorkerBreak(id) -END FUNCTION RM_MpiWorkerBreak - -!> Opens the output and log files. Files are named prefix.chem.txt and prefix.log.txt -!> based on the prefix defined by @ref RM_SetFilePrefix. -!> @param id The instance @a id returned from @ref RM_Create. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_CloseFiles, -!> @ref RM_ErrorMessage, -!> @ref RM_GetFilePrefix, -!> @ref RM_LogMessage, -!> @ref RM_OutputMessage, -!> @ref RM_SetFilePrefix, -!> @ref RM_WarningMessage. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> status = RM_SetFilePrefix(id, "Advect_f90")
-!> status = RM_OpenFiles(id)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root. - -INTEGER FUNCTION RM_OpenFiles(id) + END FUNCTION RM_MpiWorkerBreak + + !> Opens the output and log files. Files are named prefix.chem.txt and prefix.log.txt + !> based on the prefix defined by @ref RM_SetFilePrefix. + !> @param id The instance @a id returned from @ref RM_Create. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_CloseFiles, + !> @ref RM_ErrorMessage, + !> @ref RM_GetFilePrefix, + !> @ref RM_LogMessage, + !> @ref RM_OutputMessage, + !> @ref RM_SetFilePrefix, + !> @ref RM_WarningMessage. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> status = RM_SetFilePrefix(id, "Advect_f90")
+    !> status = RM_OpenFiles(id)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root. + + INTEGER FUNCTION RM_OpenFiles(id) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_OpenFiles(id) & - BIND(C, NAME='RMF_OpenFiles') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - END FUNCTION RMF_OpenFiles + INTEGER(KIND=C_INT) FUNCTION RMF_OpenFiles(id) & + BIND(C, NAME='RMF_OpenFiles') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + END FUNCTION RMF_OpenFiles END INTERFACE INTEGER, INTENT(in) :: id RM_OpenFiles = RMF_OpenFiles(id) -END FUNCTION RM_OpenFiles - -!> Print a message to the output file. -!> @param id The instance @a id returned from @ref RM_Create. -!> @param str String to be printed. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_ErrorMessage, -!> @ref RM_LogMessage, -!> @ref RM_ScreenMessage, -!> @ref RM_WarningMessage. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> write(string1, "(A,I10)") "Number of threads:                                ", RM_GetThreadCount(id)
-!> status = RM_OutputMessage(id, string1)
-!> write(string1, "(A,I10)") "Number of MPI processes:                          ", RM_GetMpiTasks(id)
-!> status = RM_OutputMessage(id, string1)
-!> write(string1, "(A,I10)") "MPI task number:                                  ", RM_GetMpiMyself(id)
-!> status = RM_OutputMessage(id, string1)
-!> status = RM_GetFilePrefix(id, string)
-!> write(string1, "(A,A)") "File prefix:                                      ", string
-!> status = RM_OutputMessage(id, trim(string1))
-!> write(string1, "(A,I10)") "Number of grid cells in the user's model:         ", RM_GetGridCellCount(id)
-!> status = RM_OutputMessage(id, trim(string1))
-!> write(string1, "(A,I10)") "Number of chemistry cells in the reaction module: ", RM_GetChemistryCellCount(id)
-!> status = RM_OutputMessage(id, trim(string1))
-!> write(string1, "(A,I10)") "Number of components for transport:               ", RM_GetComponentCount(id)
-!> status = RM_OutputMessage(id, trim(string1))
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root. - -INTEGER FUNCTION RM_OutputMessage(id, str) + END FUNCTION RM_OpenFiles + + !> Print a message to the output file. + !> @param id The instance @a id returned from @ref RM_Create. + !> @param str String to be printed. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_ErrorMessage, + !> @ref RM_LogMessage, + !> @ref RM_ScreenMessage, + !> @ref RM_WarningMessage. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> write(string1, "(A,I10)") "Number of threads:                                ", RM_GetThreadCount(id)
+    !> status = RM_OutputMessage(id, string1)
+    !> write(string1, "(A,I10)") "Number of MPI processes:                          ", RM_GetMpiTasks(id)
+    !> status = RM_OutputMessage(id, string1)
+    !> write(string1, "(A,I10)") "MPI task number:                                  ", RM_GetMpiMyself(id)
+    !> status = RM_OutputMessage(id, string1)
+    !> status = RM_GetFilePrefix(id, string)
+    !> write(string1, "(A,A)") "File prefix:                                        ", string
+    !> status = RM_OutputMessage(id, trim(string1))
+    !> write(string1, "(A,I10)") "Number of grid cells in the user's model:         ", RM_GetGridCellCount(id)
+    !> status = RM_OutputMessage(id, trim(string1))
+    !> write(string1, "(A,I10)") "Number of chemistry cells in the reaction module: ", RM_GetChemistryCellCount(id)
+    !> status = RM_OutputMessage(id, trim(string1))
+    !> write(string1, "(A,I10)") "Number of components for transport:               ", RM_GetComponentCount(id)
+    !> status = RM_OutputMessage(id, trim(string1))
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root. + + INTEGER FUNCTION RM_OutputMessage(id, str) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_OutputMessage(id, str) & - BIND(C, NAME='RMF_OutputMessage') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - CHARACTER(KIND=C_CHAR), INTENT(in) :: str(*) - END FUNCTION RMF_OutputMessage + INTEGER(KIND=C_INT) FUNCTION RMF_OutputMessage(id, str) & + BIND(C, NAME='RMF_OutputMessage') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + CHARACTER(KIND=C_CHAR), INTENT(in) :: str(*) + END FUNCTION RMF_OutputMessage END INTERFACE INTEGER, INTENT(in) :: id CHARACTER(len=*), INTENT(in) :: str RM_OutputMessage = RMF_OutputMessage(id, trim(str)//C_NULL_CHAR) -END FUNCTION RM_OutputMessage - -!> Runs a reaction step for all of the cells in the reaction module. -!> Normally, tranport concentrations are transferred to the reaction cells (@ref RM_SetConcentrations) before -!> reaction calculations are run. The length of time over which kinetic reactions are integrated is set -!> by @ref RM_SetTimeStep. Other properties that may need to be updated as a result of the transport -!> calculations include porosity (@ref RM_SetPorosity), saturation (@ref RM_SetSaturation), -!> temperature (@ref RM_SetTemperature), and pressure (@ref RM_SetPressure). -!> @param id The instance @a id returned from @ref RM_Create. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_SetConcentrations, -!> @ref RM_SetPorosity, -!> @ref RM_SetPressure, -!> @ref RM_SetSaturation, -!> @ref RM_SetTemperature, -!> @ref RM_SetTimeStep. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> status = RM_SetPorosity(id, por)                ! If pore volume changes
-!> status = RM_SetSaturation(id, sat)              ! If saturation changes
-!> status = RM_SetTemperature(id, temperature)     ! If temperature changes
-!> status = RM_SetPressure(id, pressure)           ! If pressure changes
-!> status = RM_SetConcentrations(id, c)          ! Transported concentrations
-!> status = RM_SetTimeStep(id, time_step)             ! Time step for kinetic reactions
-!> status = RM_RunCells(id)
-!> status = RM_GetConcentrations(id, c)          ! Concentrations after reaction
-!> status = RM_GetDensity(id, density)             ! Density after reaction
-!> status = RM_GetSolutionVolume(id, volume)       ! Solution volume after reaction
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root, workers must be in the loop of @ref RM_MpiWorker. - -INTEGER FUNCTION RM_RunCells(id) + END FUNCTION RM_OutputMessage + + !> Runs a reaction step for all of the cells in the reaction module. + !> Normally, tranport concentrations are transferred to the reaction cells (@ref RM_SetConcentrations) before + !> reaction calculations are run. The length of time over which kinetic reactions are integrated is set + !> by @ref RM_SetTimeStep. Other properties that may need to be updated as a result of the transport + !> calculations include porosity (@ref RM_SetPorosity), saturation (@ref RM_SetSaturation), + !> temperature (@ref RM_SetTemperature), and pressure (@ref RM_SetPressure). + !> @param id The instance @a id returned from @ref RM_Create. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_SetConcentrations, + !> @ref RM_SetPorosity, + !> @ref RM_SetPressure, + !> @ref RM_SetSaturation, + !> @ref RM_SetTemperature, + !> @ref RM_SetTimeStep. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> status = RM_SetPorosity(id, por)                ! If pore volume changes
+    !> status = RM_SetSaturation(id, sat)              ! If saturation changes
+    !> status = RM_SetTemperature(id, temperature)     ! If temperature changes
+    !> status = RM_SetPressure(id, pressure)           ! If pressure changes
+    !> status = RM_SetConcentrations(id, c)            ! Transported concentrations
+    !> status = RM_SetTimeStep(id, time_step)          ! Time step for kinetic reactions
+    !> status = RM_RunCells(id)
+    !> status = RM_GetConcentrations(id, c)            ! Concentrations after reaction
+    !> status = RM_GetDensity(id, density)             ! Density after reaction
+    !> status = RM_GetSolutionVolume(id, volume)       ! Solution volume after reaction
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref RM_MpiWorker. + + INTEGER FUNCTION RM_RunCells(id) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_RunCells(id) & - BIND(C, NAME='RMF_RunCells') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - END FUNCTION RMF_RunCells + INTEGER(KIND=C_INT) FUNCTION RMF_RunCells(id) & + BIND(C, NAME='RMF_RunCells') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + END FUNCTION RMF_RunCells END INTERFACE INTEGER, INTENT(in) :: id RM_RunCells = RMF_RunCells(id) -END FUNCTION RM_RunCells - -!> Run a PHREEQC input file. The first three arguments determine which IPhreeqc instances will run -!> the file--the workers, the InitialPhreeqc instance, and (or) the Utility instance. Input -!> files that modify the thermodynamic database should be run by all three sets of instances. -!> Files with SELECTED_OUTPUT definitions that will be used during the time-stepping loop need to -!> be run by the workers. Files that contain initial conditions or boundary conditions should -!> be run by the InitialPhreeqc instance. -!> @param id The instance @a id returned from @ref RM_Create. -!> @param workers 1, the workers will run the file; 0, the workers will not run the file. -!> @param initial_phreeqc 1, the InitialPhreeqc instance will run the file; 0, the InitialPhreeqc will not run the file. -!> @param utility 1, the Utility instance will run the file; 0, the Utility instance will not run the file. -!> @param chem_name Name of the file to run. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_RunString. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> status = RM_RunFile(id, 1, 1, 1, "advect.pqi")
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root, workers must be in the loop of @ref RM_MpiWorker. - -INTEGER FUNCTION RM_RunFile(id, workers, initial_phreeqc, utility, chem_name) + END FUNCTION RM_RunCells + + !> Run a PHREEQC input file. The first three arguments determine which IPhreeqc instances will run + !> the file--the workers, the InitialPhreeqc instance, and (or) the Utility instance. Input + !> files that modify the thermodynamic database should be run by all three sets of instances. + !> Files with SELECTED_OUTPUT definitions that will be used during the time-stepping loop need to + !> be run by the workers. Files that contain initial conditions or boundary conditions should + !> be run by the InitialPhreeqc instance. + !> @param id The instance @a id returned from @ref RM_Create. + !> @param workers 1, the workers will run the file; 0, the workers will not run the file. + !> @param initial_phreeqc 1, the InitialPhreeqc instance will run the file; 0, the InitialPhreeqc will not run the file. + !> @param utility 1, the Utility instance will run the file; 0, the Utility instance will not run the file. + !> @param chem_name Name of the file to run. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_RunString. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> status = RM_RunFile(id, 1, 1, 1, "advect.pqi")
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref RM_MpiWorker. + + INTEGER FUNCTION RM_RunFile(id, workers, initial_phreeqc, utility, chem_name) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_RunFile(id, workers, initial_phreeqc, utility, chem_name) & - BIND(C, NAME='RMF_RunFile') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - INTEGER(KIND=C_INT), INTENT(in) :: workers, initial_phreeqc, utility - CHARACTER(KIND=C_CHAR), INTENT(in) :: chem_name(*) - END FUNCTION RMF_RunFile + INTEGER(KIND=C_INT) FUNCTION RMF_RunFile(id, workers, initial_phreeqc, utility, chem_name) & + BIND(C, NAME='RMF_RunFile') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + INTEGER(KIND=C_INT), INTENT(in) :: workers, initial_phreeqc, utility + CHARACTER(KIND=C_CHAR), INTENT(in) :: chem_name(*) + END FUNCTION RMF_RunFile END INTERFACE INTEGER, INTENT(in) :: id INTEGER, INTENT(in) :: workers, initial_phreeqc, utility CHARACTER(len=*), INTENT(in) :: chem_name RM_RunFile = RMF_RunFile(id, workers, initial_phreeqc, utility, trim(chem_name)//C_NULL_CHAR) -END FUNCTION RM_RunFile - -!> Run a PHREEQC input string. The first three arguments determine which -!> IPhreeqc instances will run -!> the string--the workers, the InitialPhreeqc instance, and (or) the Utility instance. Input -!> strings that modify the thermodynamic database should be run by all three sets of instances. -!> Strings with SELECTED_OUTPUT definitions that will be used during the time-stepping loop need to -!> be run by the workers. Strings that contain initial conditions or boundary conditions should -!> be run by the InitialPhreeqc instance. -!> @param id The instance @a id returned from @ref RM_Create. -!> @param workers 1, the workers will run the string; 0, the workers will not run the string. -!> @param initial_phreeqc 1, the InitialPhreeqc instance will run the string; 0, the InitialPhreeqc will not run the string. -!> @param utility 1, the Utility instance will run the string; 0, the Utility instance will not run the string. -!> @param input_string String containing PHREEQC input. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_RunFile. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> string = "DELETE; -all"
-!> status = RM_RunString(id, 1, 0, 1, string)  ! workers, initial_phreeqc, utility
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root, workers must be in the loop of @ref RM_MpiWorker. - -INTEGER FUNCTION RM_RunString(id, workers, initial_phreeqc, utility, input_string) + END FUNCTION RM_RunFile + + !> Run a PHREEQC input string. The first three arguments determine which + !> IPhreeqc instances will run + !> the string--the workers, the InitialPhreeqc instance, and (or) the Utility instance. Input + !> strings that modify the thermodynamic database should be run by all three sets of instances. + !> Strings with SELECTED_OUTPUT definitions that will be used during the time-stepping loop need to + !> be run by the workers. Strings that contain initial conditions or boundary conditions should + !> be run by the InitialPhreeqc instance. + !> @param id The instance @a id returned from @ref RM_Create. + !> @param workers 1, the workers will run the string; 0, the workers will not run the string. + !> @param initial_phreeqc 1, the InitialPhreeqc instance will run the string; 0, the InitialPhreeqc will not run the string. + !> @param utility 1, the Utility instance will run the string; 0, the Utility instance will not run the string. + !> @param input_string String containing PHREEQC input. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_RunFile. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> string = "DELETE; -all"
+    !> status = RM_RunString(id, 1, 0, 1, string)  ! workers, initial_phreeqc, utility
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref RM_MpiWorker. + + INTEGER FUNCTION RM_RunString(id, workers, initial_phreeqc, utility, input_string) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_RunString(id, workers, initial_phreeqc, utility, input_string) & - BIND(C, NAME='RMF_RunString') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - INTEGER(KIND=C_INT), INTENT(in) :: initial_phreeqc, workers, utility - CHARACTER(KIND=C_CHAR), INTENT(in) :: input_string(*) - END FUNCTION RMF_RunString + INTEGER(KIND=C_INT) FUNCTION RMF_RunString(id, workers, initial_phreeqc, utility, input_string) & + BIND(C, NAME='RMF_RunString') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + INTEGER(KIND=C_INT), INTENT(in) :: initial_phreeqc, workers, utility + CHARACTER(KIND=C_CHAR), INTENT(in) :: input_string(*) + END FUNCTION RMF_RunString END INTERFACE INTEGER, INTENT(in) :: id INTEGER, INTENT(in) :: initial_phreeqc, workers, utility CHARACTER(len=*), INTENT(in) :: input_string RM_RunString = RMF_RunString(id, workers, initial_phreeqc, utility, trim(input_string)//C_NULL_CHAR) -END FUNCTION RM_RunString - -!> Print message to the screen. -!> @param id The instance @a id returned from @ref RM_Create. -!> @param str String to be printed. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_ErrorMessage, -!> @ref RM_LogMessage, -!> @ref RM_OutputMessage, -!> @ref RM_WarningMessage. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> write(string, "(A32,F15.1,A)") "Beginning reaction calculation  ", &
-!>       time * RM_GetTimeConversion(id), " days"
-!> status = RM_ScreenMessage(id, string)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root and (or) workers. - -INTEGER FUNCTION RM_ScreenMessage(id, str) + END FUNCTION RM_RunString + + !> Print message to the screen. + !> @param id The instance @a id returned from @ref RM_Create. + !> @param str String to be printed. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_ErrorMessage, + !> @ref RM_LogMessage, + !> @ref RM_OutputMessage, + !> @ref RM_WarningMessage. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> write(string, "(A32,F15.1,A)") "Beginning reaction calculation  ", &
+    !>       time * RM_GetTimeConversion(id), " days"
+    !> status = RM_ScreenMessage(id, string)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root and (or) workers. + + INTEGER FUNCTION RM_ScreenMessage(id, str) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_ScreenMessage(id, str) & - BIND(C, NAME='RMF_ScreenMessage') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - CHARACTER(KIND=C_CHAR), INTENT(in) :: str(*) - END FUNCTION RMF_ScreenMessage + INTEGER(KIND=C_INT) FUNCTION RMF_ScreenMessage(id, str) & + BIND(C, NAME='RMF_ScreenMessage') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + CHARACTER(KIND=C_CHAR), INTENT(in) :: str(*) + END FUNCTION RMF_ScreenMessage END INTERFACE INTEGER, INTENT(in) :: id CHARACTER(len=*), INTENT(in) :: str - RM_ScreenMessage = RMF_ScreenMessage(id, trim(str)//C_NULL_CHAR) -END FUNCTION RM_ScreenMessage - -!> Select whether to include H2O in the component list. -!> The concentrations of H and O must be known -!> accurately (8 to 10 significant digits) for the numerical method of -!> PHREEQC to produce accurate pH and pe values. -!> Because most of the H and O are in the water species, -!> it may be more robust (require less accuracy in transport) to -!> transport the excess H and O (the H and O not in water) and water. -!> The default setting (@a true) is to include water, excess H, and excess O as components. -!> A setting of @a false will include total H and total O as components. -!> @a RM_SetComponentH2O must be called before @ref RM_FindComponents. -!> -!> @param id The instance id returned from @ref RM_Create. -!> @param tf 0, total H and O are included in the component list; 1, excess H, excess O, and water -!> are included in the component list. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_FindComponents. -!> -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> status = RM_SetComponentH2O(id, 0)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root, workers must be in the loop of @ref RM_MpiWorker. - -INTEGER FUNCTION RM_SetComponentH2O(id, tf) + RM_ScreenMessage = RMF_ScreenMessage(id, trim(str)//C_NULL_CHAR) + END FUNCTION RM_ScreenMessage + + !> Select whether to include H2O in the component list. + !> The concentrations of H and O must be known + !> accurately (8 to 10 significant digits) for the numerical method of + !> PHREEQC to produce accurate pH and pe values. + !> Because most of the H and O are in the water species, + !> it may be more robust (require less accuracy in transport) to + !> transport the excess H and O (the H and O not in water) and water. + !> The default setting (@a true) is to include water, excess H, and excess O as components. + !> A setting of @a false will include total H and total O as components. + !> @a RM_SetComponentH2O must be called before @ref RM_FindComponents. + !> + !> @param id The instance id returned from @ref RM_Create. + !> @param tf 0, total H and O are included in the component list; 1, excess H, excess O, and water + !> are included in the component list. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_FindComponents. + !> + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> status = RM_SetComponentH2O(id, 0)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref RM_MpiWorker. + + INTEGER FUNCTION RM_SetComponentH2O(id, tf) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_SetComponentH2O(id, tf) & - BIND(C, NAME='RMF_SetComponentH2O') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - INTEGER(KIND=C_INT), INTENT(in) :: tf - END FUNCTION RMF_SetComponentH2O + INTEGER(KIND=C_INT) FUNCTION RMF_SetComponentH2O(id, tf) & + BIND(C, NAME='RMF_SetComponentH2O') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + INTEGER(KIND=C_INT), INTENT(in) :: tf + END FUNCTION RMF_SetComponentH2O END INTERFACE INTEGER, INTENT(in) :: id INTEGER, INTENT(in) :: tf RM_SetComponentH2O = RMF_SetComponentH2O(id, tf) -END FUNCTION RM_SetComponentH2O - -!> Use the vector of concentrations (@a c) to set the moles of components in each reaction cell. -!> The volume of water in a cell is the product of porosity (@ref RM_SetPorosity), saturation (@ref RM_SetSaturation), -!> and reference volume (@ref RM_SetRepresentativeVolume). -!> The moles of each component are determined by the volume of water and per liter concentrations. -!> If concentration units (@ref RM_SetUnitsSolution) are mass fraction, the -!> density (as specified by @ref RM_SetDensity) is used to convert from mass fraction to per mass per liter. -!> -!> @param id The instance @a id returned from @ref RM_Create. -!> @param c Array of component concentrations. Size of array is (@a nxyz, @a ncomps), where @a nxyz is the number -!> of grid cells in the user's model (@ref RM_GetGridCellCount), and @a ncomps is the number of components as determined -!> by @ref RM_FindComponents or @ref RM_GetComponentCount. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_SetDensity, -!> @ref RM_SetPorosity, -!> @ref RM_SetRepresentativeVolume, -!> @ref RM_SetSaturation, -!> @ref RM_SetUnitsSolution. -!> -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> allocate(c(nxyz, ncomps))
-!> ...
-!> call advect_f90(c, bc_conc, ncomps, nxyz)
-!> status = RM_SetPorosity(id, por)               ! If porosity changes
-!> status = RM_SetSaturation(id, sat)             ! If saturation changes
-!> status = RM_SetTemperature(id, temperature))   ! If temperature changes
-!> status = RM_SetPressure(id, pressure)          ! If pressure changes
-!> status = RM_SetConcentrations(id, c)           ! Transported concentrations
-!> status = RM_SetTimeStep(id, time_step)         ! Time step for kinetic reactions
-!> status = RM_SetTime(id, time)                  ! Current time
-!> status = RM_RunCells(id)
-!> status = RM_GetConcentrations(id, c)           ! Concentrations after reaction
-!> status = RM_GetDensity(id, density)            ! Density after reaction
-!> status = RM_GetSolutionVolume(id, volume)      ! Solution volume after reaction
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root, workers must be in the loop of @ref RM_MpiWorker. - -INTEGER FUNCTION RM_SetConcentrations(id, c) + END FUNCTION RM_SetComponentH2O + + !> Use the vector of concentrations (@a c) to set the moles of components in each reaction cell. + !> The volume of water in a cell is the product of porosity (@ref RM_SetPorosity), saturation (@ref RM_SetSaturation), + !> and reference volume (@ref RM_SetRepresentativeVolume). + !> The moles of each component are determined by the volume of water and per liter concentrations. + !> If concentration units (@ref RM_SetUnitsSolution) are mass fraction, the + !> density (as specified by @ref RM_SetDensity) is used to convert from mass fraction to per mass per liter. + !> + !> @param id The instance @a id returned from @ref RM_Create. + !> @param c Array of component concentrations. Size of array is (@a nxyz, @a ncomps), where @a nxyz is the number + !> of grid cells in the user's model (@ref RM_GetGridCellCount), and @a ncomps is the number of components as determined + !> by @ref RM_FindComponents or @ref RM_GetComponentCount. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_SetDensity, + !> @ref RM_SetPorosity, + !> @ref RM_SetRepresentativeVolume, + !> @ref RM_SetSaturation, + !> @ref RM_SetUnitsSolution. + !> + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> allocate(c(nxyz, ncomps))
+    !> ...
+    !> call advect_f90(c, bc_conc, ncomps, nxyz)
+    !> status = RM_SetPorosity(id, por)               ! If porosity changes
+    !> status = RM_SetSaturation(id, sat)             ! If saturation changes
+    !> status = RM_SetTemperature(id, temperature))   ! If temperature changes
+    !> status = RM_SetPressure(id, pressure)          ! If pressure changes
+    !> status = RM_SetConcentrations(id, c)           ! Transported concentrations
+    !> status = RM_SetTimeStep(id, time_step)         ! Time step for kinetic reactions
+    !> status = RM_SetTime(id, time)                  ! Current time
+    !> status = RM_RunCells(id)
+    !> status = RM_GetConcentrations(id, c)           ! Concentrations after reaction
+    !> status = RM_GetDensity(id, density)            ! Density after reaction
+    !> status = RM_GetSolutionVolume(id, volume)      ! Solution volume after reaction
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref RM_MpiWorker. + + INTEGER FUNCTION RM_SetConcentrations(id, c) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_SetConcentrations(id, c) & - BIND(C, NAME='RMF_SetConcentrations') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - REAL(KIND=C_DOUBLE), INTENT(in) :: c(*) - END FUNCTION RMF_SetConcentrations + INTEGER(KIND=C_INT) FUNCTION RMF_SetConcentrations(id, c) & + BIND(C, NAME='RMF_SetConcentrations') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + REAL(KIND=C_DOUBLE), INTENT(in) :: c(*) + END FUNCTION RMF_SetConcentrations END INTERFACE INTEGER, INTENT(in) :: id - DOUBLE PRECISION, DIMENSION(:,:), INTENT(in) :: c + real(kind=8), DIMENSION(:,:), INTENT(in) :: c if (rmf_debug) call Chk_SetConcentrations(id, c) RM_SetConcentrations = RMF_SetConcentrations(id, c) -END FUNCTION RM_SetConcentrations - -SUBROUTINE Chk_SetConcentrations(id, c) + END FUNCTION RM_SetConcentrations + + SUBROUTINE Chk_SetConcentrations(id, c) + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION RMF_GetComponentCount(id) & + BIND(C, NAME='RMF_GetComponentCount') + USE ISO_C_BINDING IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + END FUNCTION RMF_GetComponentCount + END INTERFACE INTEGER, INTENT(in) :: id - DOUBLE PRECISION, INTENT(in), DIMENSION(:,:) :: c + real(kind=8), INTENT(in), DIMENSION(:,:) :: c INTEGER :: errors errors = 0 + rmf_ncomps = RMF_GetComponentCount(id) errors = errors + Chk_Double2D(id, c, rmf_nxyz, rmf_ncomps, "concentration", "RM_SetConcentrations") if (errors .gt. 0) then errors = RM_Abort(id, -3, "Invalid argument in RM_SetConcentrations") endif -END SUBROUTINE Chk_SetConcentrations + END SUBROUTINE Chk_SetConcentrations #ifdef SKIP -!INTEGER FUNCTION RM_SetConcentrations1D(id, c) -! USE ISO_C_BINDING -! IMPLICIT NONE -! INTERFACE -! INTEGER(KIND=C_INT) FUNCTION RMF_SetConcentrations(id, c) & -! BIND(C, NAME='RMF_SetConcentrations') -! USE ISO_C_BINDING -! IMPLICIT NONE -! INTEGER(KIND=C_INT), INTENT(in) :: id -! REAL(KIND=C_DOUBLE), INTENT(in) :: c(*) -! END FUNCTION RMF_SetConcentrations -! END INTERFACE -! INTEGER, INTENT(in) :: id -! DOUBLE PRECISION, DIMENSION(:), INTENT(in) :: c -! RM_SetConcentrations1D = RMF_SetConcentrations(id, c) -!END FUNCTION RM_SetConcentrations1D + !INTEGER FUNCTION RM_SetConcentrations1D(id, c) + ! USE ISO_C_BINDING + ! IMPLICIT NONE + ! INTERFACE + ! INTEGER(KIND=C_INT) FUNCTION RMF_SetConcentrations(id, c) & + ! BIND(C, NAME='RMF_SetConcentrations') + ! USE ISO_C_BINDING + ! IMPLICIT NONE + ! INTEGER(KIND=C_INT), INTENT(in) :: id + ! REAL(KIND=C_DOUBLE), INTENT(in) :: c(*) + ! END FUNCTION RMF_SetConcentrations + ! END INTERFACE + ! INTEGER, INTENT(in) :: id + ! real(kind=8), DIMENSION(:), INTENT(in) :: c + ! RM_SetConcentrations1D = RMF_SetConcentrations(id, c) + !END FUNCTION RM_SetConcentrations1D #endif -!> Select the current selected output by user number. The user may define multiple SELECTED_OUTPUT -!> data blocks for the workers. A user number is specified for each data block. The value of -!> the argument @a n_user selects which of the SELECTED_OUTPUT definitions will be used -!> for selected-output operations. -!> @param id The instance @a id returned from @ref RM_Create. -!> @param n_user User number of the SELECTED_OUTPUT data block that is to be used. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_GetCurrentSelectedOutputUserNumber, -!> @ref RM_GetNthSelectedOutputUserNumber, -!> @ref RM_GetSelectedOutput, -!> @ref RM_GetSelectedOutputColumnCount, -!> @ref RM_GetSelectedOutputCount, -!> @ref RM_GetSelectedOutputHeading, -!> @ref RM_GetSelectedOutputRowCount, -!> @ref RM_SetNthSelectedOutput, -!> @ref RM_SetSelectedOutputOn. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> do isel = 1, RM_GetSelectedOutputCount(id)
-!>   n_user = RM_GetNthSelectedOutputUserNumber(id, isel)
-!>   status = RM_SetCurrentSelectedOutputUserNumber(id, n_user)
-!>   col = RM_GetSelectedOutputColumnCount(id)
-!>   allocate(selected_out(nxyz,col))
-!>   status = RM_GetSelectedOutput(id, selected_out)
-!>   ! Process results here
-!>   deallocate(selected_out)
-!> enddo
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root. -!> */ - -INTEGER FUNCTION RM_SetCurrentSelectedOutputUserNumber(id, n_user) - USE ISO_C_BINDING + !> Select the current selected output by user number. The user may define multiple SELECTED_OUTPUT + !> data blocks for the workers. A user number is specified for each data block. The value of + !> the argument @a n_user selects which of the SELECTED_OUTPUT definitions will be used + !> for selected-output operations. + !> @param id The instance @a id returned from @ref RM_Create. + !> @param n_user User number of the SELECTED_OUTPUT data block that is to be used. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_GetCurrentSelectedOutputUserNumber, + !> @ref RM_GetNthSelectedOutputUserNumber, + !> @ref RM_GetSelectedOutput, + !> @ref RM_GetSelectedOutputColumnCount, + !> @ref RM_GetSelectedOutputCount, + !> @ref RM_GetSelectedOutputHeading, + !> @ref RM_GetSelectedOutputRowCount, + !> @ref RM_SetNthSelectedOutput, + !> @ref RM_SetSelectedOutputOn. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> do isel = 1, RM_GetSelectedOutputCount(id)
+    !>   n_user = RM_GetNthSelectedOutputUserNumber(id, isel)
+    !>   status = RM_SetCurrentSelectedOutputUserNumber(id, n_user)
+    !>   col = RM_GetSelectedOutputColumnCount(id)
+    !>   allocate(selected_out(nxyz,col))
+    !>   status = RM_GetSelectedOutput(id, selected_out)
+    !>   ! Process results here
+    !>   deallocate(selected_out)
+    !> enddo
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root. + + INTEGER FUNCTION RM_SetCurrentSelectedOutputUserNumber(id, n_user) + USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_SetCurrentSelectedOutputUserNumber(id, n_user) & - BIND(C, NAME='RMF_SetCurrentSelectedOutputUserNumber') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - INTEGER(KIND=C_INT), INTENT(in) :: n_user - END FUNCTION RMF_SetCurrentSelectedOutputUserNumber + INTEGER(KIND=C_INT) FUNCTION RMF_SetCurrentSelectedOutputUserNumber(id, n_user) & + BIND(C, NAME='RMF_SetCurrentSelectedOutputUserNumber') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + INTEGER(KIND=C_INT), INTENT(in) :: n_user + END FUNCTION RMF_SetCurrentSelectedOutputUserNumber END INTERFACE INTEGER, INTENT(in) :: id INTEGER, INTENT(in) :: n_user RM_SetCurrentSelectedOutputUserNumber = RMF_SetCurrentSelectedOutputUserNumber(id, n_user) -END FUNCTION RM_SetCurrentSelectedOutputUserNumber - -!> Set the density for each reaction cell. These density values are used -!> when converting from transported mass fraction concentrations (@ref RM_SetUnitsSolution) to -!> produce per liter concentrations during a call to @ref RM_SetConcentrations. -!> They are also used when converting from module concentrations to transport concentrations -!> of mass fraction (@ref RM_GetConcentrations), if @ref RM_UseSolutionDensityVolume is set to @a false. -!> -!> @param id The instance @a id returned from @ref RM_Create. -!> @param density Array of densities. Size of array is @a nxyz, where @a nxyz is the number -!> of grid cells in the user's model (@ref RM_GetGridCellCount). -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_GetConcentrations, -!> @ref RM_SetConcentrations, -!> @ref RM_SetUnitsSolution, -!> @ref RM_UseSolutionDensityVolume. -!> -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> allocate(density(nxyz))
-!> density = 1.0
-!> status = RM_SetDensity(id, density(1))
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root, workers must be in the loop of @ref RM_MpiWorker. - -INTEGER FUNCTION RM_SetDensity(id, density) + END FUNCTION RM_SetCurrentSelectedOutputUserNumber + + !> Set the density for each reaction cell. These density values are used + !> when converting from transported mass fraction concentrations (@ref RM_SetUnitsSolution) to + !> produce per liter concentrations during a call to @ref RM_SetConcentrations. + !> They are also used when converting from module concentrations to transport concentrations + !> of mass fraction (@ref RM_GetConcentrations), if @ref RM_UseSolutionDensityVolume is set to @a false. + !> + !> @param id The instance @a id returned from @ref RM_Create. + !> @param density Array of densities. Size of array is @a nxyz, where @a nxyz is the number + !> of grid cells in the user's model (@ref RM_GetGridCellCount). + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_GetConcentrations, + !> @ref RM_SetConcentrations, + !> @ref RM_SetUnitsSolution, + !> @ref RM_UseSolutionDensityVolume. + !> + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> allocate(density(nxyz))
+    !> density = 1.0
+    !> status = RM_SetDensity(id, density)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref RM_MpiWorker. + + INTEGER FUNCTION RM_SetDensity(id, density) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_SetDensity(id, density) & - BIND(C, NAME='RMF_SetDensity') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - REAL(KIND=C_DOUBLE), INTENT(in) :: density(*) - END FUNCTION RMF_SetDensity + INTEGER(KIND=C_INT) FUNCTION RMF_SetDensity(id, density) & + BIND(C, NAME='RMF_SetDensity') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + REAL(KIND=C_DOUBLE), INTENT(in) :: density(*) + END FUNCTION RMF_SetDensity END INTERFACE INTEGER, INTENT(in) :: id - DOUBLE PRECISION, DIMENSION(:), INTENT(in) :: density + real(kind=8), DIMENSION(:), INTENT(in) :: density if (rmf_debug) call Chk_SetDensity(id, density) RM_SetDensity = RMF_SetDensity(id, density) -END FUNCTION RM_SetDensity + END FUNCTION RM_SetDensity -SUBROUTINE Chk_SetDensity(id, density) + SUBROUTINE Chk_SetDensity(id, density) IMPLICIT NONE INTEGER, INTENT(in) :: id - DOUBLE PRECISION, INTENT(in), DIMENSION(:) :: density + real(kind=8), INTENT(in), DIMENSION(:) :: density INTEGER :: errors errors = 0 errors = errors + Chk_Double1D(id, density, rmf_nxyz, "density", "RM_SetDensity") if (errors .gt. 0) then errors = RM_Abort(id, -3, "Invalid argument in RM_SetDensity") endif -END SUBROUTINE Chk_SetDensity - -!> Set the name of the dump file. It is the name used by @ref RM_DumpModule. -!> @param id The instance @a id returned from @ref RM_Create. -!> @param dump_name Name of dump file. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_DumpModule. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> status = RM_SetDumpFileName(id, "advection_f90.dmp")
-!> dump_on = 1
-!> append = 0
-!> status = RM_DumpModule(id, dump_on, append)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root. - -INTEGER FUNCTION RM_SetDumpFileName(id, dump_name) + END SUBROUTINE Chk_SetDensity + + !> Set the name of the dump file. It is the name used by @ref RM_DumpModule. + !> @param id The instance @a id returned from @ref RM_Create. + !> @param dump_name Name of dump file. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_DumpModule. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> status = RM_SetDumpFileName(id, "advection_f90.dmp")
+    !> dump_on = 1
+    !> append = 0
+    !> status = RM_DumpModule(id, dump_on, append)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root. + + INTEGER FUNCTION RM_SetDumpFileName(id, dump_name) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_SetDumpFileName(id, dump_name) & - BIND(C, NAME='RMF_SetDumpFileName') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - CHARACTER(KIND=C_CHAR), INTENT(in) :: dump_name(*) - END FUNCTION RMF_SetDumpFileName + INTEGER(KIND=C_INT) FUNCTION RMF_SetDumpFileName(id, dump_name) & + BIND(C, NAME='RMF_SetDumpFileName') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + CHARACTER(KIND=C_CHAR), INTENT(in) :: dump_name(*) + END FUNCTION RMF_SetDumpFileName END INTERFACE INTEGER, INTENT(in) :: id CHARACTER(len=*), INTENT(in) :: dump_name RM_SetDumpFileName = RMF_SetDumpFileName(id, trim(dump_name)//C_NULL_CHAR) -END FUNCTION RM_SetDumpFileName - -!> Set the action to be taken when the reaction module encounters an error. -!> Options are 0, return to calling program with an error return code (default); -!> 1, throw an exception, in C++, the exception can be caught, for C and Fortran, the program will exit; or -!> 2, attempt to exit gracefully. -!> @param id The instance id returned from @ref RM_Create. -!> @param mode Error handling mode: 0, 1, or 2. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> id = RM_create(nxyz, nthreads)
-!> status = RM_SetErrorHandlerMode(id, 2)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root, workers must be in the loop of @ref RM_MpiWorker. - -INTEGER FUNCTION RM_SetErrorHandlerMode(id, mode) + END FUNCTION RM_SetDumpFileName + + !> Set the action to be taken when the reaction module encounters an error. + !> Options are 0, return to calling program with an error return code (default); + !> 1, throw an exception, in C++, the exception can be caught, for C and Fortran, the program will exit; or + !> 2, attempt to exit gracefully. + !> @param id The instance id returned from @ref RM_Create. + !> @param mode Error handling mode: 0, 1, or 2. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> id = RM_create(nxyz, nthreads)
+    !> status = RM_SetErrorHandlerMode(id, 2)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref RM_MpiWorker. + + INTEGER FUNCTION RM_SetErrorHandlerMode(id, mode) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_SetErrorHandlerMode(id, mode) & - BIND(C, NAME='RMF_SetErrorHandlerMode') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - INTEGER(KIND=C_INT), INTENT(in) :: mode - END FUNCTION RMF_SetErrorHandlerMode + INTEGER(KIND=C_INT) FUNCTION RMF_SetErrorHandlerMode(id, mode) & + BIND(C, NAME='RMF_SetErrorHandlerMode') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + INTEGER(KIND=C_INT), INTENT(in) :: mode + END FUNCTION RMF_SetErrorHandlerMode END INTERFACE INTEGER, INTENT(in) :: id INTEGER, INTENT(in) :: mode RM_SetErrorHandlerMode = RMF_SetErrorHandlerMode(id, mode) -END FUNCTION RM_SetErrorHandlerMode -!> Set the property that controls whether error messages are generated and displayed. -!> Messages include PHREEQC "ERROR" messages, and -!> any messages written with @ref RM_ErrorMessage. -!> -!> @param id The instance @a id returned from @ref RM_Create. -!> @param tf @a 1, enable error messages; @a 0, disable error messages. Default is 1. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_ErrorMessage, -!> @ref RM_ScreenMessage. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> status = RM_SetErrorOn(rm_id, 1)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root. - -INTEGER FUNCTION RM_SetErrorOn(id, tf) + END FUNCTION RM_SetErrorHandlerMode + !> Set the property that controls whether error messages are generated and displayed. + !> Messages include PHREEQC "ERROR" messages, and + !> any messages written with @ref RM_ErrorMessage. + !> + !> @param id The instance @a id returned from @ref RM_Create. + !> @param tf @a 1, enable error messages; @a 0, disable error messages. Default is 1. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_ErrorMessage, + !> @ref RM_ScreenMessage. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> status = RM_SetErrorOn(rm_id, 1)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root. + + INTEGER FUNCTION RM_SetErrorOn(id, tf) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_SetErrorOn(id, tf) & - BIND(C, NAME='RMF_SetErrorOn') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - INTEGER(KIND=C_INT), INTENT(in) :: tf - END FUNCTION RMF_SetErrorOn + INTEGER(KIND=C_INT) FUNCTION RMF_SetErrorOn(id, tf) & + BIND(C, NAME='RMF_SetErrorOn') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + INTEGER(KIND=C_INT), INTENT(in) :: tf + END FUNCTION RMF_SetErrorOn END INTERFACE INTEGER, INTENT(in) :: id INTEGER, INTENT(in) :: tf RM_SetErrorOn = RMF_SetErrorOn(id, tf) -END FUNCTION RM_SetErrorOn -!> Set the prefix for the output (prefix.chem.txt) and log (prefix.log.txt) files. -!> These files are opened by @ref RM_OpenFiles. -!> @param id The instance @a id returned from @ref RM_Create. -!> @param prefix Prefix used when opening the output and log files. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_OpenFiles, -!> @ref RM_CloseFiles. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> status = RM_SetFilePrefix(id, "Advect_f90")
-!> status = RM_OpenFiles(id)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root. - -INTEGER FUNCTION RM_SetFilePrefix(id, prefix) + END FUNCTION RM_SetErrorOn + !> Set the prefix for the output (prefix.chem.txt) and log (prefix.log.txt) files. + !> These files are opened by @ref RM_OpenFiles. + !> @param id The instance @a id returned from @ref RM_Create. + !> @param prefix Prefix used when opening the output and log files. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_OpenFiles, + !> @ref RM_CloseFiles. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> status = RM_SetFilePrefix(id, "Advect_f90")
+    !> status = RM_OpenFiles(id)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root. + + INTEGER FUNCTION RM_SetFilePrefix(id, prefix) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_SetFilePrefix(id, prefix) & - BIND(C, NAME='RMF_SetFilePrefix') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - CHARACTER(KIND=C_CHAR), INTENT(in) :: prefix(*) - END FUNCTION RMF_SetFilePrefix + INTEGER(KIND=C_INT) FUNCTION RMF_SetFilePrefix(id, prefix) & + BIND(C, NAME='RMF_SetFilePrefix') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + CHARACTER(KIND=C_CHAR), INTENT(in) :: prefix(*) + END FUNCTION RMF_SetFilePrefix END INTERFACE INTEGER, INTENT(in) :: id CHARACTER(len=*), INTENT(in) :: prefix - RM_SetFilePrefix = RMF_SetFilePrefix(id, trim(prefix)//C_NULL_CHAR) -END FUNCTION RM_SetFilePrefix - -!> Use the array of concentrations (@a gas_moles) to set the moles of -!> gas components in each reaction cell. -!> -!> @param id The instance @a id returned from @ref RM_Create. -!> @param gas_moles Array of moles of gas components. -!> Dimensions of the vector are (nxyz, ngas_comps), -!> where ngas_comps is the result of @ref RM_GetGasComponentsCount, -!> and @a nxyz is the number of user grid cells (@ref RM_GetGridCellCount). -!> If the number of moles is set to a negative number, the gas component will -!> not be defined for the GAS_PHASE of the reaction cell. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_FindComponents, -!> @ref RM_GetGasComponentsCount, -!> @ref RM_GetGasCompMoles, -!> @ref RM_GetGasCompPressures, -!> @ref RM_GetGasCompPhi, -!> @ref RM_GetGasPhaseVolume, -!> @ref RM_SetGasPhaseVolume. -!> -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> ngas_comps = RM_SetGasComponentsCount(id)
-!> allocate(gas_moles(nxyz, ngas_comps))
-!> ...
-!> status = RM_SetGasCompMoles(id, gas_moles)
-!> status = RM_RunCells(id)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root, workers must be in the loop of @ref RM_MpiWorker. - -INTEGER FUNCTION RM_SetGasCompMoles(id, gas_moles) + RM_SetFilePrefix = RMF_SetFilePrefix(id, trim(prefix)//C_NULL_CHAR) + END FUNCTION RM_SetFilePrefix + + !> Use the array of concentrations (@a gas_moles) to set the moles of + !> gas components in each reaction cell. + !> + !> @param id The instance @a id returned from @ref RM_Create. + !> @param gas_moles Array of moles of gas components. + !> Dimensions of the vector are (nxyz, ngas_comps), + !> where ngas_comps is the result of @ref RM_GetGasComponentsCount, + !> and @a nxyz is the number of user grid cells (@ref RM_GetGridCellCount). + !> If the number of moles is set to a negative number, the gas component will + !> not be defined for the GAS_PHASE of the reaction cell. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_FindComponents, + !> @ref RM_GetGasComponentsCount, + !> @ref RM_GetGasCompMoles, + !> @ref RM_GetGasCompPressures, + !> @ref RM_GetGasCompPhi, + !> @ref RM_GetGasPhaseVolume, + !> @ref RM_SetGasPhaseVolume. + !> + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> ngas_comps = RM_SetGasComponentsCount(id)
+    !> allocate(gas_moles(nxyz, ngas_comps))
+    !> ...
+    !> status = RM_SetGasCompMoles(id, gas_moles)
+    !> status = RM_RunCells(id)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref RM_MpiWorker. + + INTEGER FUNCTION RM_SetGasCompMoles(id, gas_moles) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_SetGasCompMoles(id, gas_moles) & - BIND(C, NAME='RMF_SetGasCompMoles') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - REAL(KIND=C_DOUBLE), INTENT(in) :: gas_moles(*) - END FUNCTION RMF_SetGasCompMoles + INTEGER(KIND=C_INT) FUNCTION RMF_SetGasCompMoles(id, gas_moles) & + BIND(C, NAME='RMF_SetGasCompMoles') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + REAL(KIND=C_DOUBLE), INTENT(in) :: gas_moles(*) + END FUNCTION RMF_SetGasCompMoles END INTERFACE INTEGER, INTENT(in) :: id - DOUBLE PRECISION, DIMENSION(:,:), INTENT(in) :: gas_moles + real(kind=8), DIMENSION(:,:), INTENT(in) :: gas_moles if (rmf_debug) call Chk_SetGasCompMoles(id, gas_moles) RM_SetGasCompMoles = RMF_SetGasCompMoles(id, gas_moles) -END FUNCTION RM_SetGasCompMoles - -SUBROUTINE Chk_SetGasCompMoles(id, gas_moles) + END FUNCTION RM_SetGasCompMoles + + SUBROUTINE Chk_SetGasCompMoles(id, gas_moles) IMPLICIT NONE INTEGER, INTENT(in) :: id - DOUBLE PRECISION, INTENT(in), DIMENSION(:,:) :: gas_moles + real(kind=8), INTENT(in), DIMENSION(:,:) :: gas_moles INTEGER :: errors, rmf_ngas_comps errors = 0 - rmf_ngas_comps = RM_GetGasComponentsCount(id) + rmf_ngas_comps = RM_GetGasComponentsCount(id) errors = errors + Chk_Double2D(id, gas_moles, rmf_nxyz, rmf_ngas_comps, "gas moles", "RM_SetGasCompMoles") if (errors .gt. 0) then errors = RM_Abort(id, -3, "Invalid argument in RM_SetGasCompMoles") endif -END SUBROUTINE Chk_SetGasCompMoles - -!> Transfer volumes of gas phases from -!> the array given in the argument list (@a gas_volume) to each reaction cell. -!> The gas-phase volume affects the pressures calculated for fixed-volume -!> gas phases. If a gas-phase volume is defined with this method -!> for a GAS_PHASE in a cell, -!> the gas phase is forced to be a fixed-volume gas phase. -!> -!> @param id The instance @a id returned from @ref RM_Create. -!> @param gas_volume Array of gas-phase volumes. -!> Dimension of the array is (nxyz), -!> where @a nxyz is the number of user grid cells (@ref RM_GetGridCellCount). -!> If an element of the array is set to a negative number, the gas component will -!> not be defined for the GAS_PHASE of the reaction cell. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_FindComponents, -!> @ref RM_GetGasComponentsCount, -!> @ref RM_GetGasCompMoles, -!> @ref RM_GetGasCompPressures, -!> @ref RM_GetGasCompPhi, -!> @ref RM_GetGasPhaseVolume, -!> @ref RM_SetGasCompMoles. -!> -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> allocate(gas_volume(nxyz))
-!> ...
-!> status = RM_SetGasPhaseVolume(id, gas_volume)
-!> status = RM_RunCells(id)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root, workers must be in the loop of @ref RM_MpiWorker. - -INTEGER FUNCTION RM_SetGasPhaseVolume(id, gas_volume) + END SUBROUTINE Chk_SetGasCompMoles + + !> Transfer volumes of gas phases from + !> the array given in the argument list (@a gas_volume) to each reaction cell. + !> The gas-phase volume affects the pressures calculated for fixed-volume + !> gas phases. If a gas-phase volume is defined with this method + !> for a GAS_PHASE in a cell, + !> the gas phase is forced to be a fixed-volume gas phase. + !> + !> @param id The instance @a id returned from @ref RM_Create. + !> @param gas_volume Array of gas-phase volumes. + !> Dimension of the array is (nxyz), + !> where @a nxyz is the number of user grid cells (@ref RM_GetGridCellCount). + !> If an element of the array is set to a negative number, the gas component will + !> not be defined for the GAS_PHASE of the reaction cell. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_FindComponents, + !> @ref RM_GetGasComponentsCount, + !> @ref RM_GetGasCompMoles, + !> @ref RM_GetGasCompPressures, + !> @ref RM_GetGasCompPhi, + !> @ref RM_GetGasPhaseVolume, + !> @ref RM_SetGasCompMoles. + !> + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> allocate(gas_volume(nxyz))
+    !> ...
+    !> status = RM_SetGasPhaseVolume(id, gas_volume)
+    !> status = RM_RunCells(id)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref RM_MpiWorker. + + INTEGER FUNCTION RM_SetGasPhaseVolume(id, gas_volume) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_SetGasPhaseVolume(id, gas_volume) & - BIND(C, NAME='RMF_SetGasPhaseVolume') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - REAL(KIND=C_DOUBLE), INTENT(in) :: gas_volume(*) - END FUNCTION RMF_SetGasPhaseVolume + INTEGER(KIND=C_INT) FUNCTION RMF_SetGasPhaseVolume(id, gas_volume) & + BIND(C, NAME='RMF_SetGasPhaseVolume') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + REAL(KIND=C_DOUBLE), INTENT(in) :: gas_volume(*) + END FUNCTION RMF_SetGasPhaseVolume END INTERFACE INTEGER, INTENT(in) :: id - DOUBLE PRECISION, DIMENSION(:), INTENT(in) :: gas_volume + real(kind=8), DIMENSION(:), INTENT(in) :: gas_volume if (rmf_debug) call Chk_SetGasPhaseVolume(id, gas_volume) RM_SetGasPhaseVolume = RMF_SetGasPhaseVolume(id, gas_volume) -END FUNCTION RM_SetGasPhaseVolume - -SUBROUTINE Chk_SetGasPhaseVolume(id, gas_volume) + END FUNCTION RM_SetGasPhaseVolume + + SUBROUTINE Chk_SetGasPhaseVolume(id, gas_volume) IMPLICIT NONE INTEGER, INTENT(in) :: id - DOUBLE PRECISION, INTENT(in), DIMENSION(:) :: gas_volume + real(kind=8), INTENT(in), DIMENSION(:) :: gas_volume INTEGER :: errors, rmf_ngas_comps errors = 0 - rmf_ngas_comps = RM_GetGasComponentsCount(id) + rmf_ngas_comps = RM_GetGasComponentsCount(id) errors = errors + Chk_Double1D(id, gas_volume, rmf_nxyz, "gas volume", "RM_SetGasPhaseVolume") if (errors .gt. 0) then errors = RM_Abort(id, -3, "Invalid argument in RM_SetGasPhaseVolume") endif -END SUBROUTINE Chk_SetGasPhaseVolume - -!> MPI only. Defines a callback function that allows additional tasks to be done -!> by the workers. The method @ref RM_MpiWorker contains a loop, -!> where the workers receive a message (an integer), -!> run a function corresponding to that integer, -!> and then wait for another message. -!> RM_SetMpiWorkerCallback allows the developer to add another function -!> that responds to additional integer messages by calling developer-defined functions -!> corresponding to those integers. -!> @ref RM_MpiWorker calls the callback function when the message number -!> is not one of the PhreeqcRM message numbers. -!> Messages are unique integer numbers. PhreeqcRM uses integers in a range -!> beginning at 0. It is suggested that developers use message numbers starting -!> at 1000 or higher for their tasks. -!> The callback function calls a developer-defined function specified -!> by the message number and then returns to @ref RM_MpiWorker to wait for -!> another message. -!> @n@n -!> For Fortran, the functions that are called from the callback function -!> can use USE statements to find the data necessary to perform the tasks, and -!> the only argument to the callback function is an integer message argument. -!> @a RM_SetMpiWorkerCallback -!> must be called by each worker before @ref RM_MpiWorker is called. -!> @n@n -!> The motivation for this method is to allow the workers to perform other -!> tasks, for instance, parallel transport calculations, within the structure -!> of @ref RM_MpiWorker. The callback function -!> can be used to allow the workers to receive data, perform transport calculations, -!> and (or) send results, without leaving the loop of @ref RM_MpiWorker. Alternatively, -!> it is possible for the workers to return from @ref RM_MpiWorker -!> by a call to @ref RM_MpiWorkerBreak by root. The workers could then call -!> subroutines to receive data, calculate transport, and send data, -!> and then resume processing PhreeqcRM messages from root with another -!> call to @ref RM_MpiWorker. -!> @param id The instance @a id returned from @ref RM_Create. -!> @param fcn A function that returns an integer and has an integer argument. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_MpiWorker, -!> @ref RM_MpiWorkerBreak. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> Code executed by root:
-!> status = do_something()
-!> 
-!> Code executed by workers:
-!> status = RM_SetMpiWorkerCallback(id, worker_tasks_f)
-!> status = RM_MpiWorker(id)
-!> 
-!> Code executed by root and workers:    
-!> integer function do_something
-!>   implicit none
-!>   INCLUDE 'mpif.h'
-!>   integer status
-!>   integer i, method_number, mpi_myself, mpi_task, mpi_tasks, worker_number;
-!>   method_number = 1000
-!>   call MPI_Comm_size(MPI_COMM_WORLD, mpi_tasks, status)
-!>   call MPI_Comm_rank(MPI_COMM_WORLD, mpi_myself, status)
-!>   if (mpi_myself .eq. 0) then     
-!>     CALL MPI_Bcast(method_number, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, status)
-!>     write(*,*) "I am root."
-!>     do i = 1, mpi_tasks-1
-!>       CALL MPI_Recv(worker_number, 1, MPI_INTEGER, i, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE, status)
-!>       write(*,*) "Recieved data from worker number ", worker_number, "."
-!>     enddo
-!>   else
-!>     CALL MPI_Send(mpi_myself, 1, MPI_INTEGER, 0, 0, MPI_COMM_WORLD, status)
-!>   endif
-!>   do_something = 0
-!> end function do_something
-!> 
-!> Code called by workers from method MpiWorker:
-!> integer(kind=C_INT) function worker_tasks_f(method_number) BIND(C, NAME='worker_tasks_f')
-!>   USE ISO_C_BINDING
-!>   implicit none
-!>   interface
-!>     integer function do_something
-!>     end function do_something
-!>   end interface
-!>   integer(kind=c_int), intent(in) :: method_number
-!>   integer :: status
-!>   if (method_number .eq. 1000) then
-!>     status = do_something()
-!>   endif
-!>   worker_tasks_f = 0
-!> end function worker_tasks_f
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by workers, before call to @ref RM_MpiWorker. - -INTEGER FUNCTION RM_SetMpiWorkerCallback(id, fcn) - USE ISO_C_BINDING - IMPLICIT NONE - INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_SetMpiWorkerCallback(id, fcn) & - BIND(C, NAME='RMF_SetMpiWorkerCallback') - USE ISO_C_BINDING - INTEGER(KIND=C_INT), INTENT(in) :: id -!> \cond - INTERFACE - INTEGER(KIND=C_INT) FUNCTION fcn(method_number) BIND(C) - USE ISO_C_BINDING - INTEGER(KIND=C_INT), INTENT(in) :: method_number - END FUNCTION fcn - END INTERFACE -!> \endcond - END FUNCTION RMF_SetMpiWorkerCallback - END INTERFACE - INTEGER, INTENT(IN) :: id - - INTERFACE - INTEGER(kind=c_int) FUNCTION fcn(method_number) BIND(C) - USE ISO_C_BINDING - !INTEGER, INTENT(in) :: method_number - INTEGER(kind=c_int), INTENT(in) :: method_number - END FUNCTION fcn - END INTERFACE - - RM_SetMpiWorkerCallback = RMF_SetMpiWorkerCallback(id, fcn) -END FUNCTION RM_SetMpiWorkerCallback - -!> Specify the current selected output by sequence number. The user may define multiple SELECTED_OUTPUT -!> data blocks for the workers. A user number is specified for each data block, and the blocks are -!> stored in user-number order. The value of -!> the argument @a n selects the sequence number of the SELECTED_OUTPUT definition that will be used -!> for selected-output operations. -!> @param id The instance @a id returned from @ref RM_Create. -!> @param n Sequence number of the SELECTED_OUTPUT data block that is to be used. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_GetCurrentSelectedOutputUserNumber, -!> @ref RM_GetNthSelectedOutputUserNumber, -!> @ref RM_GetSelectedOutput, -!> @ref RM_GetSelectedOutputColumnCount, -!> @ref RM_GetSelectedOutputCount, -!> @ref RM_GetSelectedOutputHeading, -!> @ref RM_GetSelectedOutputRowCount, -!> @ref RM_SetCurrentSelectedOutputUserNumber, -!> @ref RM_SetSelectedOutputOn. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> do isel = 1, RM_GetSelectedOutputCount(id)
-!>   status = RM_SetNthSelectedOutput(id, isel)
-!>   n_user = RM_GetCurrentSelectedOutputUserNumber(id)
-!>   col = RM_GetSelectedOutputColumnCount(id)
-!>   allocate(selected_out(nxyz,col))
-!>   status = RM_GetSelectedOutput(id, selected_out)
-!>   ! Process results here
-!>   deallocate(selected_out)
-!> enddo
-!> 	
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root. -INTEGER FUNCTION RM_SetNthSelectedOutput(id, n) - USE ISO_C_BINDING - IMPLICIT NONE - INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_SetNthSelectedOutput(id, n) & - BIND(C, NAME='RMF_SetNthSelectedOutput') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - INTEGER(KIND=C_INT), INTENT(in) :: n - END FUNCTION RMF_SetNthSelectedOutput + END SUBROUTINE Chk_SetGasPhaseVolume + + !> MPI only. Defines a callback function that allows additional tasks to be done + !> by the workers. The method @ref RM_MpiWorker contains a loop, + !> where the workers receive a message (an integer), + !> run a function corresponding to that integer, + !> and then wait for another message. + !> RM_SetMpiWorkerCallback allows the developer to add another function + !> that responds to additional integer messages by calling developer-defined functions + !> corresponding to those integers. + !> @ref RM_MpiWorker calls the callback function when the message number + !> is not one of the PhreeqcRM message numbers. + !> Messages are unique integer numbers. PhreeqcRM uses integers in a range + !> beginning at 0. It is suggested that developers use message numbers starting + !> at 1000 or higher for their tasks. + !> The callback function calls a developer-defined function specified + !> by the message number and then returns to @ref RM_MpiWorker to wait for + !> another message. + !> @n@n + !> For Fortran, the functions that are called from the callback function + !> can use USE statements to find the data necessary to perform the tasks, and + !> the only argument to the callback function is an integer message argument. + !> @a RM_SetMpiWorkerCallback + !> must be called by each worker before @ref RM_MpiWorker is called. + !> @n@n + !> The motivation for this method is to allow the workers to perform other + !> tasks, for instance, parallel transport calculations, within the structure + !> of @ref RM_MpiWorker. The callback function + !> can be used to allow the workers to receive data, perform transport calculations, + !> and (or) send results, without leaving the loop of @ref RM_MpiWorker. Alternatively, + !> it is possible for the workers to return from @ref RM_MpiWorker + !> by a call to @ref RM_MpiWorkerBreak by root. The workers could then call + !> subroutines to receive data, calculate transport, and send data, + !> and then resume processing PhreeqcRM messages from root with another + !> call to @ref RM_MpiWorker. + !> @param id The instance @a id returned from @ref RM_Create. + !> @param fcn A function that returns an integer and has an integer argument. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_MpiWorker, + !> @ref RM_MpiWorkerBreak. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> Code executed by root:
+    !> status = do_something()
+    !>
+    !> Code executed by workers:
+    !> status = RM_SetMpiWorkerCallback(id, worker_tasks_f)
+    !> status = RM_MpiWorker(id)
+    !>
+    !> Code executed by root and workers:
+    !> integer function do_something
+    !>   implicit none
+    !>   INCLUDE 'mpif.h'
+    !>   integer status
+    !>   integer i, method_number, mpi_myself, mpi_task, mpi_tasks, worker_number;
+    !>   method_number = 1000
+    !>   call MPI_Comm_size(MPI_COMM_WORLD, mpi_tasks, status)
+    !>   call MPI_Comm_rank(MPI_COMM_WORLD, mpi_myself, status)
+    !>   if (mpi_myself .eq. 0) then
+    !>     CALL MPI_Bcast(method_number, 1, MPI_INTEGER, 0, MPI_COMM_WORLD, status)
+    !>     write(*,*) "I am root."
+    !>     do i = 1, mpi_tasks-1
+    !>       CALL MPI_Recv(worker_number, 1, MPI_INTEGER, i, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE, status)
+    !>       write(*,*) "Recieved data from worker number ", worker_number, "."
+    !>     enddo
+    !>   else
+    !>     CALL MPI_Send(mpi_myself, 1, MPI_INTEGER, 0, 0, MPI_COMM_WORLD, status)
+    !>   endif
+    !>   do_something = 0
+    !> end function do_something
+    !>
+    !> Code called by workers from method RM_MpiWorker:
+    !> integer(kind=C_INT) function worker_tasks_f(method_number) BIND(C, NAME='worker_tasks_f')
+    !>   USE ISO_C_BINDING
+    !>   implicit none
+    !>   interface
+    !>     integer function do_something
+    !>     end function do_something
+    !>   end interface
+    !>   integer(kind=c_int), intent(in) :: method_number
+    !>   integer :: status
+    !>   if (method_number .eq. 1000) then
+    !>     status = do_something()
+    !>   endif
+    !>   worker_tasks_f = 0
+    !> end function worker_tasks_f
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by workers, before call to @ref RM_MpiWorker. + + INTEGER FUNCTION RM_SetMpiWorkerCallback(id, fcn) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION RMF_SetMpiWorkerCallback(id, fcn) & + BIND(C, NAME='RMF_SetMpiWorkerCallback') + USE ISO_C_BINDING + INTEGER(KIND=C_INT), INTENT(in) :: id + !> \cond + INTERFACE + INTEGER(KIND=C_INT) FUNCTION fcn(method_number) BIND(C) + USE ISO_C_BINDING + INTEGER(KIND=C_INT), INTENT(in) :: method_number + END FUNCTION fcn + END INTERFACE + !> \endcond + END FUNCTION RMF_SetMpiWorkerCallback + END INTERFACE + INTEGER, INTENT(IN) :: id + + INTERFACE + INTEGER(kind=c_int) FUNCTION fcn(method_number) BIND(C) + USE ISO_C_BINDING + !INTEGER, INTENT(in) :: method_number + INTEGER(kind=c_int), INTENT(in) :: method_number + END FUNCTION fcn + END INTERFACE + + RM_SetMpiWorkerCallback = RMF_SetMpiWorkerCallback(id, fcn) + END FUNCTION RM_SetMpiWorkerCallback + + !> Specify the current selected output by sequence number. The user may define multiple SELECTED_OUTPUT + !> data blocks for the workers. A user number is specified for each data block, and the blocks are + !> stored in user-number order. The value of + !> the argument @a n selects the sequence number of the SELECTED_OUTPUT definition that will be used + !> for selected-output operations. + !> @param id The instance @a id returned from @ref RM_Create. + !> @param n Sequence number of the SELECTED_OUTPUT data block that is to be used. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_GetCurrentSelectedOutputUserNumber, + !> @ref RM_GetNthSelectedOutputUserNumber, + !> @ref RM_GetSelectedOutput, + !> @ref RM_GetSelectedOutputColumnCount, + !> @ref RM_GetSelectedOutputCount, + !> @ref RM_GetSelectedOutputHeading, + !> @ref RM_GetSelectedOutputRowCount, + !> @ref RM_SetCurrentSelectedOutputUserNumber, + !> @ref RM_SetSelectedOutputOn. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> do isel = 1, RM_GetSelectedOutputCount(id)
+    !>   status = RM_SetNthSelectedOutput(id, isel)
+    !>   n_user = RM_GetCurrentSelectedOutputUserNumber(id)
+    !>   col = RM_GetSelectedOutputColumnCount(id)
+    !>   allocate(selected_out(nxyz,col))
+    !>   status = RM_GetSelectedOutput(id, selected_out)
+    !>   ! Process results here
+    !>   deallocate(selected_out)
+    !> enddo
+    !> 	
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root. + INTEGER FUNCTION RM_SetNthSelectedOutput(id, n) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION RMF_SetNthSelectedOutput(id, n) & + BIND(C, NAME='RMF_SetNthSelectedOutput') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + INTEGER(KIND=C_INT), INTENT(in) :: n + END FUNCTION RMF_SetNthSelectedOutput END INTERFACE INTEGER, INTENT(in) :: id INTEGER, INTENT(in) :: n - RM_SetNthSelectedOutput = RMF_SetNthSelectedOutput(id, n) -END FUNCTION RM_SetNthSelectedOutput - -!> Sets the property for partitioning solids between the saturated and unsaturated -!> parts of a partially saturated cell. -!> -!> The option is intended to be used by saturated-only -!> flow codes that allow a variable water table. -!> The value has meaning only when saturations -!> less than 1.0 are encountered. The partially saturated cells -!> may have a small water-to-rock ratio that causes -!> reactions to proceed differently relative to fully saturated cells. -!> By setting @a RM_SetPartitionUZSolids to true, the -!> amounts of solids and gases are partioned according to the saturation. -!> If a cell has a saturation of 0.5, then -!> the water interacts with only half of the solids and gases; the other half is unreactive -!> until the water table rises. As the saturation in a cell varies, -!> solids and gases are transferred between the -!> saturated and unsaturated (unreactive) reservoirs of the cell. -!> Unsaturated-zone flow and transport codes will probably use the default (false), -!> which assumes all gases and solids are reactive regardless of saturation. -!> -!> @param id The instance @a id returned from @ref RM_Create. -!> @param tf @a True, the fraction of solids and gases available for -!> reaction is equal to the saturation; -!> @a False (default), all solids and gases are reactive regardless of saturation. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> status = RM_SetPartitionUZSolids(id, 0)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root, workers must be in the loop of @ref RM_MpiWorker. - -INTEGER FUNCTION RM_SetPartitionUZSolids(id, tf) + RM_SetNthSelectedOutput = RMF_SetNthSelectedOutput(id, n-1) + END FUNCTION RM_SetNthSelectedOutput + + !> Sets the property for partitioning solids between the saturated and unsaturated + !> parts of a partially saturated cell. + !> + !> The option is intended to be used by saturated-only + !> flow codes that allow a variable water table. + !> The value has meaning only when saturations + !> less than 1.0 are encountered. The partially saturated cells + !> may have a small water-to-rock ratio that causes + !> reactions to proceed differently relative to fully saturated cells. + !> By setting @a RM_SetPartitionUZSolids to true, the + !> amounts of solids and gases are partioned according to the saturation. + !> If a cell has a saturation of 0.5, then + !> the water interacts with only half of the solids and gases; the other half is unreactive + !> until the water table rises. As the saturation in a cell varies, + !> solids and gases are transferred between the + !> saturated and unsaturated (unreactive) reservoirs of the cell. + !> Unsaturated-zone flow and transport codes will probably use the default (false), + !> which assumes all gases and solids are reactive regardless of saturation. + !> + !> @param id The instance @a id returned from @ref RM_Create. + !> @param tf @a True, the fraction of solids and gases available for + !> reaction is equal to the saturation; + !> @a False (default), all solids and gases are reactive regardless of saturation. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> status = RM_SetPartitionUZSolids(id, 0)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref RM_MpiWorker. + + INTEGER FUNCTION RM_SetPartitionUZSolids(id, tf) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_SetPartitionUZSolids(id, tf) & - BIND(C, NAME='RMF_SetPartitionUZSolids') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - INTEGER(KIND=C_INT), INTENT(in) :: tf - END FUNCTION RMF_SetPartitionUZSolids + INTEGER(KIND=C_INT) FUNCTION RMF_SetPartitionUZSolids(id, tf) & + BIND(C, NAME='RMF_SetPartitionUZSolids') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + INTEGER(KIND=C_INT), INTENT(in) :: tf + END FUNCTION RMF_SetPartitionUZSolids END INTERFACE INTEGER, INTENT(in) :: id INTEGER, INTENT(in) :: tf RM_SetPartitionUZSolids = RMF_SetPartitionUZSolids(id, tf) -END FUNCTION RM_SetPartitionUZSolids - -!> Set the porosity for each reaction cell. -!> The volume of water in a reaction cell is the product of the porosity, the saturation -!> (@ref RM_SetSaturation), and the representative volume (@ref RM_SetRepresentativeVolume). -!> @param id The instance @a id returned from @ref RM_Create. -!> @param por Array of porosities, unitless. Default is 0.1. Size of array is @a nxyz, where @a nxyz is the number -!> of grid cells in the user's model (@ref RM_GetGridCellCount). -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_GetSaturation, -!> @ref RM_SetRepresentativeVolume, -!> @ref RM_SetSaturation. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> allocate(por(nxyz))
-!> por = 0.2
-!> status = RM_SetPorosity(id, por(1))
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root, workers must be in the loop of @ref RM_MpiWorker. - -INTEGER FUNCTION RM_SetPorosity(id, por) + END FUNCTION RM_SetPartitionUZSolids + + !> Set the porosity for each reaction cell. + !> The volume of water in a reaction cell is the product of the porosity, the saturation + !> (@ref RM_SetSaturation), and the representative volume (@ref RM_SetRepresentativeVolume). + !> @param id The instance @a id returned from @ref RM_Create. + !> @param por Array of porosities, unitless. Default is 0.1. Size of array is @a nxyz, where @a nxyz is the number + !> of grid cells in the user's model (@ref RM_GetGridCellCount). + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_GetSaturation, + !> @ref RM_SetRepresentativeVolume, + !> @ref RM_SetSaturation. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> allocate(por(nxyz))
+    !> por = 0.2
+    !> status = RM_SetPorosity(id, por)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref RM_MpiWorker. + + INTEGER FUNCTION RM_SetPorosity(id, por) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_SetPorosity(id, por) & - BIND(C, NAME='RMF_SetPorosity') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - REAL(KIND=C_DOUBLE), INTENT(in) :: por(*) - END FUNCTION RMF_SetPorosity + INTEGER(KIND=C_INT) FUNCTION RMF_SetPorosity(id, por) & + BIND(C, NAME='RMF_SetPorosity') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + REAL(KIND=C_DOUBLE), INTENT(in) :: por(*) + END FUNCTION RMF_SetPorosity END INTERFACE INTEGER, INTENT(in) :: id - DOUBLE PRECISION, DIMENSION(:), INTENT(in) :: por + real(kind=8), DIMENSION(:), INTENT(in) :: por if (rmf_debug) call Chk_SetPorosity(id, por) RM_SetPorosity = RMF_SetPorosity(id, por) -END FUNCTION RM_SetPorosity + END FUNCTION RM_SetPorosity -SUBROUTINE Chk_SetPorosity(id, por) + SUBROUTINE Chk_SetPorosity(id, por) IMPLICIT NONE INTEGER, INTENT(in) :: id - DOUBLE PRECISION, INTENT(in), DIMENSION(:) :: por + real(kind=8), INTENT(in), DIMENSION(:) :: por INTEGER :: errors errors = 0 errors = errors + Chk_Double1D(id, por, rmf_nxyz, "porosity", "RM_SetPorosity") if (errors .gt. 0) then errors = RM_Abort(id, -3, "Invalid argument in RM_SetPorosity") endif -END SUBROUTINE Chk_SetPorosity - -!> Set the pressure for each reaction cell. Pressure effects are considered only in three of the -!> databases distributed with PhreeqcRM: phreeqc.dat, Amm.dat, and pitzer.dat. -!> @param id The instance @a id returned from @ref RM_Create. -!> @param p Array of pressures, in atm. Size of array is @a nxyz, where @a nxyz is the number -!> of grid cells in the user's model (@ref RM_GetGridCellCount). -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_SetTemperature. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> allocate(pressure(nxyz))
-!> pressure = 2.0
-!> status = RM_SetPressure(id, pressure(1))
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root, workers must be in the loop of @ref RM_MpiWorker. - -INTEGER FUNCTION RM_SetPressure(id, p) + END SUBROUTINE Chk_SetPorosity + + !> Set the pressure for each reaction cell. Pressure effects are considered only in three of the + !> databases distributed with PhreeqcRM: phreeqc.dat, Amm.dat, and pitzer.dat. + !> @param id The instance @a id returned from @ref RM_Create. + !> @param p Array of pressures, in atm. Size of array is @a nxyz, where @a nxyz is the number + !> of grid cells in the user's model (@ref RM_GetGridCellCount). + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_SetTemperature. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> allocate(pressure(nxyz))
+    !> pressure = 2.0
+    !> status = RM_SetPressure(id, pressure)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref RM_MpiWorker. + + INTEGER FUNCTION RM_SetPressure(id, p) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_SetPressure(id, p) & - BIND(C, NAME='RMF_SetPressure') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - REAL(KIND=C_DOUBLE), INTENT(in) :: p(*) - END FUNCTION RMF_SetPressure + INTEGER(KIND=C_INT) FUNCTION RMF_SetPressure(id, p) & + BIND(C, NAME='RMF_SetPressure') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + REAL(KIND=C_DOUBLE), INTENT(in) :: p(*) + END FUNCTION RMF_SetPressure END INTERFACE INTEGER, INTENT(in) :: id - DOUBLE PRECISION, DIMENSION(:), INTENT(in) :: p + real(kind=8), DIMENSION(:), INTENT(in) :: p if (rmf_debug) call Chk_SetPressure(id, p) RM_SetPressure = RMF_SetPressure(id, p) -END FUNCTION RM_SetPressure + END FUNCTION RM_SetPressure -SUBROUTINE Chk_SetPressure(id, p) + SUBROUTINE Chk_SetPressure(id, p) IMPLICIT NONE INTEGER, INTENT(in) :: id - DOUBLE PRECISION, INTENT(in), DIMENSION(:) :: p + real(kind=8), INTENT(in), DIMENSION(:) :: p INTEGER :: errors errors = 0 errors = errors + Chk_Double1D(id, p, rmf_nxyz, "pressure", "RM_SetPressure") if (errors .gt. 0) then errors = RM_Abort(id, -3, "Invalid argument in RM_SetPressure") endif -END SUBROUTINE Chk_SetPressure - -!> Enable or disable detailed output for each reaction cell. -!> Printing for a cell will occur only when the -!> printing is enabled with @ref RM_SetPrintChemistryOn and the @a cell_mask value is 1. -!> -!> @param id The instance @a id returned from @ref RM_Create. -!> @param cell_mask Array of integers. Size of array is @a nxyz, where @a nxyz is the number -!> of grid cells in the user's model (@ref RM_GetGridCellCount). A value of 0 will -!> disable printing detailed output for the cell; a value of 1 will enable printing detailed output for a cell. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_SetPrintChemistryOn. -!> -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> allocate(print_chemistry_mask(nxyz))
-!>   do i = 1, nxyz/2
-!>   print_chemistry_mask(i) = 1
-!>   print_chemistry_mask(i+nxyz/2) = 0
-!> enddo
-!> status = RM_SetPrintChemistryMask(id, print_chemistry_mask(1))
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root, workers must be in the loop of @ref RM_MpiWorker. - -INTEGER FUNCTION RM_SetPrintChemistryMask(id, cell_mask) + END SUBROUTINE Chk_SetPressure + + !> Enable or disable detailed output for each reaction cell. + !> Printing for a cell will occur only when the + !> printing is enabled with @ref RM_SetPrintChemistryOn and the @a cell_mask value is 1. + !> + !> @param id The instance @a id returned from @ref RM_Create. + !> @param cell_mask Array of integers. Size of array is @a nxyz, where @a nxyz is the number + !> of grid cells in the user's model (@ref RM_GetGridCellCount). A value of 0 will + !> disable printing detailed output for the cell; a value of 1 will enable printing detailed output for a cell. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_SetPrintChemistryOn. + !> + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> allocate(print_chemistry_mask(nxyz))
+    !>   do i = 1, nxyz/2
+    !>   print_chemistry_mask(i) = 1
+    !>   print_chemistry_mask(i+nxyz/2) = 0
+    !> enddo
+    !> status = RM_SetPrintChemistryMask(id, print_chemistry_mask)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref RM_MpiWorker. + + INTEGER FUNCTION RM_SetPrintChemistryMask(id, cell_mask) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION RMF_SetPrintChemistryMask(id, cell_mask) & + BIND(C, NAME='RMF_SetPrintChemistryMask') USE ISO_C_BINDING IMPLICIT NONE - INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_SetPrintChemistryMask(id, cell_mask) & - BIND(C, NAME='RMF_SetPrintChemistryMask') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - INTEGER(KIND=C_INT), INTENT(in) :: cell_mask(*) - END FUNCTION RMF_SetPrintChemistryMask + INTEGER(KIND=C_INT), INTENT(in) :: id + INTEGER(KIND=C_INT), INTENT(in) :: cell_mask(*) + END FUNCTION RMF_SetPrintChemistryMask END INTERFACE INTEGER, INTENT(in) :: id INTEGER, DIMENSION(:), INTENT(in) :: cell_mask if (rmf_debug) call Chk_SetPrintChemistryMask(id, cell_mask) RM_SetPrintChemistryMask = RMF_SetPrintChemistryMask(id, cell_mask) -END FUNCTION RM_SetPrintChemistryMask + END FUNCTION RM_SetPrintChemistryMask -SUBROUTINE Chk_SetPrintChemistryMask(id, cell_mask) + SUBROUTINE Chk_SetPrintChemistryMask(id, cell_mask) IMPLICIT NONE INTEGER, INTENT(in) :: id INTEGER, INTENT(in), DIMENSION(:) :: cell_mask @@ -5452,1036 +5798,1036 @@ SUBROUTINE Chk_SetPrintChemistryMask(id, cell_mask) if (errors .gt. 0) then errors = RM_Abort(id, -3, "Invalid argument in RM_SetPrintChemistryMask") endif -END SUBROUTINE Chk_SetPrintChemistryMask - -!> Setting to enable or disable printing detailed output from reaction calculations to the output file for a set of -!> cells defined by @ref RM_SetPrintChemistryMask. The detailed output prints all of the output -!> typical of a PHREEQC reaction calculation, which includes solution descriptions and the compositions of -!> all other reactants. The output can be several hundred lines per cell, which can lead to a very -!> large output file (prefix.chem.txt, @ref RM_OpenFiles). For the worker instances, the output can be limited to a set of cells -!> (@ref RM_SetPrintChemistryMask) and, in general, the -!> amount of information printed can be limited by use of options in the PRINT data block of PHREEQC -!> (applied by using @ref RM_RunFile or @ref RM_RunString). -!> Printing the detailed output for the workers is generally used only for debugging, and PhreeqcRM will run -!> significantly faster when printing detailed output for the workers is disabled. -!> -!> @param id The instance @a id returned from @ref RM_Create. -!> @param workers 0, disable detailed printing in the worker instances, 1, enable detailed printing -!> in the worker instances. -!> @param initial_phreeqc 0, disable detailed printing in the InitialPhreeqc instance, 1, enable detailed printing -!> in the InitialPhreeqc instances. -!> @param utility 0, disable detailed printing in the Utility instance, 1, enable detailed printing -!> in the Utility instance. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_SetPrintChemistryMask. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> status = RM_SetPrintChemistryOn(id, 0, 1, 0)  ! workers, initial_phreeqc, utility
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root, workers must be in the loop of @ref RM_MpiWorker. - -INTEGER FUNCTION RM_SetPrintChemistryOn(id, workers, initial_phreeqc, utility) + END SUBROUTINE Chk_SetPrintChemistryMask + + !> Setting to enable or disable printing detailed output from reaction calculations to the output file for a set of + !> cells defined by @ref RM_SetPrintChemistryMask. The detailed output prints all of the output + !> typical of a PHREEQC reaction calculation, which includes solution descriptions and the compositions of + !> all other reactants. The output can be several hundred lines per cell, which can lead to a very + !> large output file (prefix.chem.txt, @ref RM_OpenFiles). For the worker instances, the output can be limited to a set of cells + !> (@ref RM_SetPrintChemistryMask) and, in general, the + !> amount of information printed can be limited by use of options in the PRINT data block of PHREEQC + !> (applied by using @ref RM_RunFile or @ref RM_RunString). + !> Printing the detailed output for the workers is generally used only for debugging, and PhreeqcRM will run + !> significantly faster when printing detailed output for the workers is disabled. + !> + !> @param id The instance @a id returned from @ref RM_Create. + !> @param workers 0, disable detailed printing in the worker instances, 1, enable detailed printing + !> in the worker instances. + !> @param initial_phreeqc 0, disable detailed printing in the InitialPhreeqc instance, 1, enable detailed printing + !> in the InitialPhreeqc instances. + !> @param utility 0, disable detailed printing in the Utility instance, 1, enable detailed printing + !> in the Utility instance. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_SetPrintChemistryMask. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> status = RM_SetPrintChemistryOn(id, 0, 1, 0)  ! workers, initial_phreeqc, utility
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref RM_MpiWorker. + + INTEGER FUNCTION RM_SetPrintChemistryOn(id, workers, initial_phreeqc, utility) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_SetPrintChemistryOn(id, workers, initial_phreeqc, utility) & - BIND(C, NAME='RMF_SetPrintChemistryOn') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - INTEGER(KIND=C_INT), INTENT(in) :: workers, initial_phreeqc, utility - END FUNCTION RMF_SetPrintChemistryOn + INTEGER(KIND=C_INT) FUNCTION RMF_SetPrintChemistryOn(id, workers, initial_phreeqc, utility) & + BIND(C, NAME='RMF_SetPrintChemistryOn') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + INTEGER(KIND=C_INT), INTENT(in) :: workers, initial_phreeqc, utility + END FUNCTION RMF_SetPrintChemistryOn END INTERFACE INTEGER, INTENT(in) :: id INTEGER, INTENT(in) :: workers, initial_phreeqc, utility RM_SetPrintChemistryOn = RMF_SetPrintChemistryOn(id, workers, initial_phreeqc, utility) -END FUNCTION RM_SetPrintChemistryOn - -!> Set the load-balancing algorithm. -!> PhreeqcRM attempts to rebalance the load of each thread or process such that each -!> thread or process takes the same amount of time to run its part of a @ref RM_RunCells -!> calculation. Two algorithms are available; one uses individual times for each cell and -!> accounts for cells that were not run because -!> saturation was zero (default), and -!> the other assigns an average time to all cells. -!> The methods are similar, but limited testing indicates the default method performs better. -!> -!> @param id The instance @a id returned from @ref RM_Create. -!> @param method 0, indicates average times are used in rebalancing; 1 indicates individual -!> cell times are used in rebalancing (default). -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_SetRebalanceFraction. -!> -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> status = RM_SetRebalanceByCell(id, 1)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root, workers must be in the loop of @ref RM_MpiWorker. - -INTEGER FUNCTION RM_SetRebalanceByCell(id, method) + END FUNCTION RM_SetPrintChemistryOn + + !> Set the load-balancing algorithm. + !> PhreeqcRM attempts to rebalance the load of each thread or process such that each + !> thread or process takes the same amount of time to run its part of a @ref RM_RunCells + !> calculation. Two algorithms are available; one uses individual times for each cell and + !> accounts for cells that were not run because + !> saturation was zero (default), and + !> the other assigns an average time to all cells. + !> The methods are similar, but limited testing indicates the default method performs better. + !> + !> @param id The instance @a id returned from @ref RM_Create. + !> @param method 0, indicates average times are used in rebalancing; 1 indicates individual + !> cell times are used in rebalancing (default). + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_SetRebalanceFraction. + !> + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> status = RM_SetRebalanceByCell(id, 1)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref RM_MpiWorker. + + INTEGER FUNCTION RM_SetRebalanceByCell(id, method) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_SetRebalanceByCell(id, method) & - BIND(C, NAME='RMF_SetRebalanceByCell') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - INTEGER(KIND=C_INT), INTENT(in) :: method - END FUNCTION RMF_SetRebalanceByCell + INTEGER(KIND=C_INT) FUNCTION RMF_SetRebalanceByCell(id, method) & + BIND(C, NAME='RMF_SetRebalanceByCell') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + INTEGER(KIND=C_INT), INTENT(in) :: method + END FUNCTION RMF_SetRebalanceByCell END INTERFACE INTEGER, INTENT(in) :: id INTEGER, INTENT(in) :: method RM_SetRebalanceByCell = RMF_SetRebalanceByCell(id, method) -END FUNCTION RM_SetRebalanceByCell - -!> Sets the fraction of cells that are transferred among threads or processes when rebalancing. -!> PhreeqcRM attempts to rebalance the load of each thread or process such that each -!> thread or process takes the same amount of time to run its part of a @ref RM_RunCells -!> calculation. The rebalancing transfers cell calculations among threads or processes to -!> try to achieve an optimum balance. @a RM_SetRebalanceFraction -!> adjusts the calculated optimum number of cell transfers by a fraction from 0 to 1.0 to -!> determine the actual number of cell transfers. A value of zero eliminates -!> load rebalancing. A value less than 1.0 is suggested to slow the approach to the optimum cell -!> distribution and avoid possible oscillations -!> when too many cells are transferred at one iteration, requiring reverse transfers at the next iteration. -!> Default is 0.5. -!> -!> @param id The instance @a id returned from @ref RM_Create. -!> @param f Fraction from 0.0 to 1.0. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_SetRebalanceByCell. -!> -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> status = RM_SetRebalanceFraction(id, 0.5d0)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root, workers must be in the loop of @ref RM_MpiWorker. - -INTEGER FUNCTION RM_SetRebalanceFraction(id, f) + END FUNCTION RM_SetRebalanceByCell + + !> Sets the fraction of cells that are transferred among threads or processes when rebalancing. + !> PhreeqcRM attempts to rebalance the load of each thread or process such that each + !> thread or process takes the same amount of time to run its part of a @ref RM_RunCells + !> calculation. The rebalancing transfers cell calculations among threads or processes to + !> try to achieve an optimum balance. @a RM_SetRebalanceFraction + !> adjusts the calculated optimum number of cell transfers by a fraction from 0 to 1.0 to + !> determine the actual number of cell transfers. A value of zero eliminates + !> load rebalancing. A value less than 1.0 is suggested to slow the approach to the optimum cell + !> distribution and avoid possible oscillations + !> when too many cells are transferred at one iteration, requiring reverse transfers at the next iteration. + !> Default is 0.5. + !> + !> @param id The instance @a id returned from @ref RM_Create. + !> @param f Fraction from 0.0 to 1.0. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_SetRebalanceByCell. + !> + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> status = RM_SetRebalanceFraction(id, 0.5d0)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref RM_MpiWorker. + + INTEGER FUNCTION RM_SetRebalanceFraction(id, f) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_SetRebalanceFraction(id, f) & - BIND(C, NAME='RMF_SetRebalanceFraction') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - REAL(KIND=C_DOUBLE), INTENT(in) :: f - END FUNCTION RMF_SetRebalanceFraction + INTEGER(KIND=C_INT) FUNCTION RMF_SetRebalanceFraction(id, f) & + BIND(C, NAME='RMF_SetRebalanceFraction') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + REAL(KIND=C_DOUBLE), INTENT(in) :: f + END FUNCTION RMF_SetRebalanceFraction END INTERFACE INTEGER, INTENT(in) :: id - DOUBLE PRECISION, INTENT(in) :: f + real(kind=8), INTENT(in) :: f RM_SetRebalanceFraction = RMF_SetRebalanceFraction(id, f) -END FUNCTION RM_SetRebalanceFraction - -!> Set the representative volume of each reaction cell. -!> By default the representative volume of each reaction cell is 1 liter. -!> The volume of water in a reaction cell is determined by the procuct of the representative volume, -!> the porosity (@ref RM_SetPorosity), and the saturation (@ref RM_SetSaturation). -!> The numerical method of PHREEQC is more robust if the water volume for a reaction cell is -!> within a couple orders of magnitude of 1.0. -!> Small water volumes caused by small porosities and (or) small saturations (and (or) small representative volumes) -!> may cause non-convergence of the numerical method. -!> In these cases, a larger representative volume may help. Note -!> that increasing the representative volume also increases -!> the number of moles of the reactants in the reaction cell (minerals, surfaces, exchangers, -!> and others), which are defined as moles per representative volume. -!> -!> @param id The instance @a id returned from @ref RM_Create. -!> @param rv Vector of representative volumes, in liters. Default is 1.0 liter. -!> Size of array is @a nxyz, where @a nxyz is the number -!> of grid cells in the user's model (@ref RM_GetGridCellCount). -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_SetPorosity, -!> @ref RM_SetSaturation. -!> -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> double precision, dimension(:), allocatable   :: rv
-!> allocate(rv(nxyz))
-!> rv = 1.0
-!> status = RM_SetRepresentativeVolume(id, rv(1))
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root, workers must be in the loop of @ref RM_MpiWorker. - -INTEGER FUNCTION RM_SetRepresentativeVolume(id, rv) + END FUNCTION RM_SetRebalanceFraction + + !> Set the representative volume of each reaction cell. + !> By default the representative volume of each reaction cell is 1 liter. + !> The volume of water in a reaction cell is determined by the procuct of the representative volume, + !> the porosity (@ref RM_SetPorosity), and the saturation (@ref RM_SetSaturation). + !> The numerical method of PHREEQC is more robust if the water volume for a reaction cell is + !> within a couple orders of magnitude of 1.0. + !> Small water volumes caused by small porosities and (or) small saturations (and (or) small representative volumes) + !> may cause non-convergence of the numerical method. + !> In these cases, a larger representative volume may help. Note + !> that increasing the representative volume also increases + !> the number of moles of the reactants in the reaction cell (minerals, surfaces, exchangers, + !> and others), which are defined as moles per representative volume. + !> + !> @param id The instance @a id returned from @ref RM_Create. + !> @param rv Vector of representative volumes, in liters. Default is 1.0 liter. + !> Size of array is @a nxyz, where @a nxyz is the number + !> of grid cells in the user's model (@ref RM_GetGridCellCount). + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_SetPorosity, + !> @ref RM_SetSaturation. + !> + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> real(kind=8), dimension(:), allocatable   :: rv
+    !> allocate(rv(nxyz))
+    !> rv = 1.0
+    !> status = RM_SetRepresentativeVolume(id, rv)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref RM_MpiWorker. + + INTEGER FUNCTION RM_SetRepresentativeVolume(id, rv) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_SetRepresentativeVolume(id, rv) & - BIND(C, NAME='RMF_SetRepresentativeVolume') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - REAL(KIND=C_DOUBLE), INTENT(in) :: rv(*) - END FUNCTION RMF_SetRepresentativeVolume + INTEGER(KIND=C_INT) FUNCTION RMF_SetRepresentativeVolume(id, rv) & + BIND(C, NAME='RMF_SetRepresentativeVolume') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + REAL(KIND=C_DOUBLE), INTENT(in) :: rv(*) + END FUNCTION RMF_SetRepresentativeVolume END INTERFACE INTEGER, INTENT(in) :: id - DOUBLE PRECISION, DIMENSION(:), INTENT(in) :: rv + real(kind=8), DIMENSION(:), INTENT(in) :: rv RM_SetRepresentativeVolume = RMF_SetRepresentativeVolume(id, rv) -END FUNCTION RM_SetRepresentativeVolume - -!> Set the saturation of each reaction cell. Saturation is a fraction ranging from 0 to 1. -!> The volume of water in a cell is the product of porosity (@ref RM_SetPorosity), saturation (@a RM_SetSaturation), -!> and representative volume (@ref RM_SetRepresentativeVolume). As a result of a reaction calculation, -!> solution properties (density and volume) will change; -!> the databases phreeqc.dat, Amm.dat, and pitzer.dat have the molar volume data to calculate these changes. -!> The methods @ref RM_GetDensity, @ref RM_GetSolutionVolume, and @ref RM_GetSaturation -!> can be used to account for these changes in the succeeding transport calculation. -!> @a RM_SetRepresentativeVolume should be called before initial conditions are defined for the reaction cells. -!> -!> @param id The instance @a id returned from @ref RM_Create. -!> @param sat Array of saturations, unitless. Size of array is @a nxyz, where @a nxyz is the number -!> of grid cells in the user's model (@ref RM_GetGridCellCount). -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_GetDensity, -!> @ref RM_GetSaturation, -!> @ref RM_GetSolutionVolume, -!> @ref RM_SetPorosity, -!> @ref RM_SetRepresentativeVolume. -!> -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> allocate(sat(nxyz))
-!> sat = 1.0
-!> status = RM_SetSaturation(id, sat(1))
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root, workers must be in the loop of @ref RM_MpiWorker. - -INTEGER FUNCTION RM_SetSaturation(id, sat) + END FUNCTION RM_SetRepresentativeVolume + + !> Set the saturation of each reaction cell. Saturation is a fraction ranging from 0 to 1. + !> The volume of water in a cell is the product of porosity (@ref RM_SetPorosity), saturation (@a RM_SetSaturation), + !> and representative volume (@ref RM_SetRepresentativeVolume). As a result of a reaction calculation, + !> solution properties (density and volume) will change; + !> the databases phreeqc.dat, Amm.dat, and pitzer.dat have the molar volume data to calculate these changes. + !> The methods @ref RM_GetDensity, @ref RM_GetSolutionVolume, and @ref RM_GetSaturation + !> can be used to account for these changes in the succeeding transport calculation. + !> @a RM_SetRepresentativeVolume should be called before initial conditions are defined for the reaction cells. + !> + !> @param id The instance @a id returned from @ref RM_Create. + !> @param sat Array of saturations, unitless. Size of array is @a nxyz, where @a nxyz is the number + !> of grid cells in the user's model (@ref RM_GetGridCellCount). + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_GetDensity, + !> @ref RM_GetSaturation, + !> @ref RM_GetSolutionVolume, + !> @ref RM_SetPorosity, + !> @ref RM_SetRepresentativeVolume. + !> + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> allocate(sat(nxyz))
+    !> sat = 1.0
+    !> status = RM_SetSaturation(id, sat)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref RM_MpiWorker. + + INTEGER FUNCTION RM_SetSaturation(id, sat) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_SetSaturation(id, sat) & - BIND(C, NAME='RMF_SetSaturation') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - REAL(KIND=C_DOUBLE), INTENT(in) :: sat(*) - END FUNCTION RMF_SetSaturation + INTEGER(KIND=C_INT) FUNCTION RMF_SetSaturation(id, sat) & + BIND(C, NAME='RMF_SetSaturation') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + REAL(KIND=C_DOUBLE), INTENT(in) :: sat(*) + END FUNCTION RMF_SetSaturation END INTERFACE INTEGER, INTENT(in) :: id - DOUBLE PRECISION, DIMENSION(:), INTENT(in) :: sat + real(kind=8), DIMENSION(:), INTENT(in) :: sat if (rmf_debug) call Chk_SetSaturation(id, sat) RM_SetSaturation = RMF_SetSaturation(id, sat) -END FUNCTION RM_SetSaturation + END FUNCTION RM_SetSaturation -SUBROUTINE Chk_SetSaturation(id, sat) + SUBROUTINE Chk_SetSaturation(id, sat) IMPLICIT NONE INTEGER, INTENT(in) :: id - DOUBLE PRECISION, INTENT(in), DIMENSION(:) :: sat + real(kind=8), INTENT(in), DIMENSION(:) :: sat INTEGER :: errors errors = 0 errors = errors + Chk_Double1D(id, sat, rmf_nxyz, "sataturation", "RM_SetSaturation") if (errors .gt. 0) then errors = RM_Abort(id, -3, "Invalid argument in RM_SetSaturation") endif -END SUBROUTINE Chk_SetSaturation - -!> Set the property that controls whether messages are written to the screen. -!> Messages include information about rebalancing during @ref RM_RunCells, and -!> any messages written with @ref RM_ScreenMessage. -!> -!> @param id The instance @a id returned from @ref RM_Create. -!> @param tf @a 1, enable screen messages; @a 0, disable screen messages. Default is 1. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_RunCells, -!> @ref RM_ScreenMessage. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> status = RM_SetScreenOn(rm_id, 1)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root. - -INTEGER FUNCTION RM_SetScreenOn(id, tf) + END SUBROUTINE Chk_SetSaturation + + !> Set the property that controls whether messages are written to the screen. + !> Messages include information about rebalancing during @ref RM_RunCells, and + !> any messages written with @ref RM_ScreenMessage. + !> + !> @param id The instance @a id returned from @ref RM_Create. + !> @param tf @a 1, enable screen messages; @a 0, disable screen messages. Default is 1. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_RunCells, + !> @ref RM_ScreenMessage. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> status = RM_SetScreenOn(rm_id, 1)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root. + + INTEGER FUNCTION RM_SetScreenOn(id, tf) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_SetScreenOn(id, tf) & - BIND(C, NAME='RMF_SetScreenOn') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - INTEGER(KIND=C_INT), INTENT(in) :: tf - END FUNCTION RMF_SetScreenOn + INTEGER(KIND=C_INT) FUNCTION RMF_SetScreenOn(id, tf) & + BIND(C, NAME='RMF_SetScreenOn') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + INTEGER(KIND=C_INT), INTENT(in) :: tf + END FUNCTION RMF_SetScreenOn END INTERFACE INTEGER, INTENT(in) :: id INTEGER, INTENT(in) :: tf RM_SetScreenOn = RMF_SetScreenOn(id, tf) -END FUNCTION RM_SetScreenOn - -!> Setting determines whether selected-output results are available to be retrieved -!> with @ref RM_GetSelectedOutput. @a 1 indicates that selected-output results -!> will be accumulated during @ref RM_RunCells and can be retrieved with @ref RM_GetSelectedOutput; -!> @a 0 indicates that selected-output results will not -!> be accumulated during @ref RM_RunCells. -!> -!> @param id The instance @a id returned from @ref RM_Create. -!> @param tf 0, disable selected output; 1, enable selected output. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_GetCurrentSelectedOutputUserNumber, -!> @ref RM_GetNthSelectedOutputUserNumber, -!> @ref RM_GetSelectedOutput, -!> @ref RM_GetSelectedOutputColumnCount, -!> @ref RM_GetSelectedOutputCount, -!> @ref RM_GetSelectedOutputHeading, -!> @ref RM_GetSelectedOutputRowCount, -!> @ref RM_SetCurrentSelectedOutputUserNumber, -!> @ref RM_SetNthSelectedOutput. -!> -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> status = RM_SetSelectedOutputOn(id, 1)        ! enable selected output
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root, workers must be in the loop of @ref RM_MpiWorker. - -INTEGER FUNCTION RM_SetSelectedOutputOn(id, tf) + END FUNCTION RM_SetScreenOn + + !> Setting determines whether selected-output results are available to be retrieved + !> with @ref RM_GetSelectedOutput. @a 1 indicates that selected-output results + !> will be accumulated during @ref RM_RunCells and can be retrieved with @ref RM_GetSelectedOutput; + !> @a 0 indicates that selected-output results will not + !> be accumulated during @ref RM_RunCells. + !> + !> @param id The instance @a id returned from @ref RM_Create. + !> @param tf 0, disable selected output; 1, enable selected output. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_GetCurrentSelectedOutputUserNumber, + !> @ref RM_GetNthSelectedOutputUserNumber, + !> @ref RM_GetSelectedOutput, + !> @ref RM_GetSelectedOutputColumnCount, + !> @ref RM_GetSelectedOutputCount, + !> @ref RM_GetSelectedOutputHeading, + !> @ref RM_GetSelectedOutputRowCount, + !> @ref RM_SetCurrentSelectedOutputUserNumber, + !> @ref RM_SetNthSelectedOutput. + !> + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> status = RM_SetSelectedOutputOn(id, 1)        ! enable selected output
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref RM_MpiWorker. + + INTEGER FUNCTION RM_SetSelectedOutputOn(id, tf) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_SetSelectedOutputOn(id, tf) & - BIND(C, NAME='RMF_SetSelectedOutputOn') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - INTEGER(KIND=C_INT), INTENT(in) :: tf - END FUNCTION RMF_SetSelectedOutputOn + INTEGER(KIND=C_INT) FUNCTION RMF_SetSelectedOutputOn(id, tf) & + BIND(C, NAME='RMF_SetSelectedOutputOn') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + INTEGER(KIND=C_INT), INTENT(in) :: tf + END FUNCTION RMF_SetSelectedOutputOn END INTERFACE INTEGER, INTENT(in) :: id INTEGER, INTENT(in) :: tf RM_SetSelectedOutputOn = RMF_SetSelectedOutputOn(id, tf) -END FUNCTION RM_SetSelectedOutputOn - -!> Sets the value of the species-save property. -!> This method enables use of PhreeqcRM with multicomponent-diffusion transport calculations. -!> By default, concentrations of aqueous species are not saved. Setting the species-save property to 1 allows -!> aqueous species concentrations to be retrieved -!> with @ref RM_GetSpeciesConcentrations, and solution compositions to be set with -!> @ref RM_SpeciesConcentrations2Module. -!> RM_SetSpeciesSaveOn must be called before calls to @ref RM_FindComponents. -!> -!> @param id The instance @a id returned from @ref RM_Create. -!> @param save_on 0, indicates species concentrations are not saved; 1, indicates species concentrations are -!> saved. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_FindComponents, -!> @ref RM_GetSpeciesConcentrations, -!> @ref RM_GetSpeciesCount, -!> @ref RM_GetSpeciesD25, -!> @ref RM_GetSpeciesLog10Gammas, -!> @ref RM_GetSpeciesLog10Molalities, -!> @ref RM_GetSpeciesName, -!> @ref RM_GetSpeciesSaveOn, -!> @ref RM_GetSpeciesZ, -!> @ref RM_SpeciesConcentrations2Module. -!> -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> save_on = RM_SetSpeciesSaveOn(id, 1)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root and (or) workers. - -INTEGER FUNCTION RM_SetSpeciesSaveOn(id, save_on) + END FUNCTION RM_SetSelectedOutputOn + + !> Sets the value of the species-save property. + !> This method enables use of PhreeqcRM with multicomponent-diffusion transport calculations. + !> By default, concentrations of aqueous species are not saved. Setting the species-save property to 1 allows + !> aqueous species concentrations to be retrieved + !> with @ref RM_GetSpeciesConcentrations, and solution compositions to be set with + !> @ref RM_SpeciesConcentrations2Module. + !> RM_SetSpeciesSaveOn must be called before calls to @ref RM_FindComponents. + !> + !> @param id The instance @a id returned from @ref RM_Create. + !> @param save_on 0, indicates species concentrations are not saved; 1, indicates species concentrations are + !> saved. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_FindComponents, + !> @ref RM_GetSpeciesConcentrations, + !> @ref RM_GetSpeciesCount, + !> @ref RM_GetSpeciesD25, + !> @ref RM_GetSpeciesLog10Gammas, + !> @ref RM_GetSpeciesLog10Molalities, + !> @ref RM_GetSpeciesName, + !> @ref RM_GetSpeciesSaveOn, + !> @ref RM_GetSpeciesZ, + !> @ref RM_SpeciesConcentrations2Module. + !> + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> save_on = RM_SetSpeciesSaveOn(id, 1)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root and (or) workers. + + INTEGER FUNCTION RM_SetSpeciesSaveOn(id, save_on) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_SetSpeciesSaveOn(id, save_on) & - BIND(C, NAME='RMF_SetSpeciesSaveOn') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - INTEGER(KIND=C_INT), INTENT(in) :: save_on - END FUNCTION RMF_SetSpeciesSaveOn + INTEGER(KIND=C_INT) FUNCTION RMF_SetSpeciesSaveOn(id, save_on) & + BIND(C, NAME='RMF_SetSpeciesSaveOn') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + INTEGER(KIND=C_INT), INTENT(in) :: save_on + END FUNCTION RMF_SetSpeciesSaveOn END INTERFACE INTEGER, INTENT(in) :: id INTEGER, INTENT(in) :: save_on RM_SetSpeciesSaveOn = RMF_SetSpeciesSaveOn(id, save_on) -END FUNCTION RM_SetSpeciesSaveOn - -!> Set the temperature for each reaction cell. If @a RM_SetTemperature is not called, -!> worker solutions will have temperatures as defined by initial conditions -!> (@ref RM_InitialPhreeqc2Module and @ref RM_InitialPhreeqcCell2Module). -!> -!> @param id The instance @a id returned from @ref RM_Create. -!> @param t Array of temperatures, in degrees C. Size of array is @a nxyz, where @a nxyz is the number -!> of grid cells in the user's model (@ref RM_GetGridCellCount). -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_InitialPhreeqc2Module, -!> @ref RM_InitialPhreeqcCell2Module, -!> @ref RM_SetPressure. -!> -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> allocate(temperature(nxyz))
-!> temperature = 20.0
-!> status = RM_SetTemperature(id, temperature(1))
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root, workers must be in the loop of @ref RM_MpiWorker. - -INTEGER FUNCTION RM_SetTemperature(id, t) + END FUNCTION RM_SetSpeciesSaveOn + + !> Set the temperature for each reaction cell. If @a RM_SetTemperature is not called, + !> worker solutions will have temperatures as defined by initial conditions + !> (@ref RM_InitialPhreeqc2Module and @ref RM_InitialPhreeqcCell2Module). + !> + !> @param id The instance @a id returned from @ref RM_Create. + !> @param t Array of temperatures, in degrees C. Size of array is @a nxyz, where @a nxyz is the number + !> of grid cells in the user's model (@ref RM_GetGridCellCount). + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_InitialPhreeqc2Module, + !> @ref RM_InitialPhreeqcCell2Module, + !> @ref RM_SetPressure. + !> + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> allocate(temperature(nxyz))
+    !> temperature = 20.0
+    !> status = RM_SetTemperature(id, temperature)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref RM_MpiWorker. + + INTEGER FUNCTION RM_SetTemperature(id, t) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_SetTemperature(id, t) & - BIND(C, NAME='RMF_SetTemperature') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - REAL(KIND=C_DOUBLE), INTENT(in) :: t(*) - END FUNCTION RMF_SetTemperature + INTEGER(KIND=C_INT) FUNCTION RMF_SetTemperature(id, t) & + BIND(C, NAME='RMF_SetTemperature') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + REAL(KIND=C_DOUBLE), INTENT(in) :: t(*) + END FUNCTION RMF_SetTemperature END INTERFACE INTEGER, INTENT(in) :: id - DOUBLE PRECISION, DIMENSION(:), INTENT(in) :: t + real(kind=8), DIMENSION(:), INTENT(in) :: t if (rmf_debug) call Chk_SetTemperature(id, t) RM_SetTemperature = RMF_SetTemperature(id, t) -END FUNCTION RM_SetTemperature + END FUNCTION RM_SetTemperature -SUBROUTINE Chk_SetTemperature(id, t) + SUBROUTINE Chk_SetTemperature(id, t) IMPLICIT NONE INTEGER, INTENT(in) :: id - DOUBLE PRECISION, INTENT(in), DIMENSION(:) :: t + real(kind=8), INTENT(in), DIMENSION(:) :: t INTEGER :: errors errors = 0 errors = errors + Chk_Double1D(id, t, rmf_nxyz, "temperature", "RM_SetTemperature") if (errors .gt. 0) then errors = RM_Abort(id, -3, "Invalid argument in RM_SetTemperature") endif -END SUBROUTINE Chk_SetTemperature - -!> Set current simulation time for the reaction module. -!> @param id The instance @a id returned from @ref RM_Create. -!> @param time Current simulation time, in seconds. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_SetTimeConversion, -!> @ref RM_SetTimeStep. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> status = RM_SetTime(id, time)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root, workers must be in the loop of @ref RM_MpiWorker. - -INTEGER FUNCTION RM_SetTime(id, time) + END SUBROUTINE Chk_SetTemperature + + !> Set current simulation time for the reaction module. + !> @param id The instance @a id returned from @ref RM_Create. + !> @param time Current simulation time, in seconds. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_SetTimeConversion, + !> @ref RM_SetTimeStep. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> status = RM_SetTime(id, time)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref RM_MpiWorker. + + INTEGER FUNCTION RM_SetTime(id, time) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_SetTime(id, time) & - BIND(C, NAME='RMF_SetTime') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - REAL(KIND=C_DOUBLE), INTENT(in) :: time - END FUNCTION RMF_SetTime + INTEGER(KIND=C_INT) FUNCTION RMF_SetTime(id, time) & + BIND(C, NAME='RMF_SetTime') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + REAL(KIND=C_DOUBLE), INTENT(in) :: time + END FUNCTION RMF_SetTime END INTERFACE INTEGER, INTENT(in) :: id - DOUBLE PRECISION, INTENT(in) :: time + real(kind=8), INTENT(in) :: time RM_SetTime = RMF_SetTime(id, time) -END FUNCTION RM_SetTime - -!> Set a factor to convert to user time units. Factor times seconds produces user time units. -!> @param id The instance @a id returned from @ref RM_Create. -!> @param conv_factor Factor to convert seconds to user time units. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_SetTime, -!> @ref RM_SetTimeStep. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> status = RM_SetTimeConversion(id, dble(1.0 / 86400.0)) ! days
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root, workers must be in the loop of @ref RM_MpiWorker. - -INTEGER FUNCTION RM_SetTimeConversion(id, conv_factor) + END FUNCTION RM_SetTime + + !> Set a factor to convert to user time units. Factor times seconds produces user time units. + !> @param id The instance @a id returned from @ref RM_Create. + !> @param conv_factor Factor to convert seconds to user time units. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_SetTime, + !> @ref RM_SetTimeStep. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> status = RM_SetTimeConversion(id, dble(1.0 / 86400.0)) ! days
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref RM_MpiWorker. + + INTEGER FUNCTION RM_SetTimeConversion(id, conv_factor) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_SetTimeConversion(id, conv_factor) & - BIND(C, NAME='RMF_SetTimeConversion') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - REAL(KIND=C_DOUBLE), INTENT(in) :: conv_factor - END FUNCTION RMF_SetTimeConversion + INTEGER(KIND=C_INT) FUNCTION RMF_SetTimeConversion(id, conv_factor) & + BIND(C, NAME='RMF_SetTimeConversion') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + REAL(KIND=C_DOUBLE), INTENT(in) :: conv_factor + END FUNCTION RMF_SetTimeConversion END INTERFACE INTEGER, INTENT(in) :: id - DOUBLE PRECISION, INTENT(in) :: conv_factor + real(kind=8), INTENT(in) :: conv_factor RM_SetTimeConversion = RMF_SetTimeConversion(id, conv_factor) -END FUNCTION RM_SetTimeConversion - -!> Set current time step for the reaction module. This is the length -!> of time over which kinetic reactions are integrated. -!> @param id The instance @a id returned from @ref RM_Create. -!> @param time_step Current time step, in seconds. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_SetTime, -!> @ref RM_SetTimeConversion. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> status = RM_SetTimeStep(id, time_step)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root, workers must be in the loop of @ref RM_MpiWorker. - -INTEGER FUNCTION RM_SetTimeStep(id, time_step) + END FUNCTION RM_SetTimeConversion + + !> Set current time step for the reaction module. This is the length + !> of time over which kinetic reactions are integrated. + !> @param id The instance @a id returned from @ref RM_Create. + !> @param time_step Current time step, in seconds. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_SetTime, + !> @ref RM_SetTimeConversion. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> status = RM_SetTimeStep(id, time_step)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref RM_MpiWorker. + + INTEGER FUNCTION RM_SetTimeStep(id, time_step) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_SetTimeStep(id, time_step) & - BIND(C, NAME='RMF_SetTimeStep') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - REAL(KIND=C_DOUBLE), INTENT(in) :: time_step - END FUNCTION RMF_SetTimeStep + INTEGER(KIND=C_INT) FUNCTION RMF_SetTimeStep(id, time_step) & + BIND(C, NAME='RMF_SetTimeStep') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + REAL(KIND=C_DOUBLE), INTENT(in) :: time_step + END FUNCTION RMF_SetTimeStep END INTERFACE INTEGER, INTENT(in) :: id - DOUBLE PRECISION, INTENT(in) :: time_step + real(kind=8), INTENT(in) :: time_step RM_SetTimeStep = RMF_SetTimeStep(id, time_step) -END FUNCTION RM_SetTimeStep - -!> Sets input units for exchangers. -!> In PHREEQC input, exchangers are defined by moles of exchange sites (@a Mp). -!> @a RM_SetUnitsExchange specifies how the number of moles of exchange sites in a reaction cell (@a Mc) -!> is calculated from the input value (@a Mp). -!> -!> Options are -!> 0, @a Mp is mol/L of RV (default), @a Mc = @a Mp*RV, where RV is the representative volume (@ref RM_SetRepresentativeVolume); -!> 1, @a Mp is mol/L of water in the RV, @a Mc = @a Mp*P*RV, where @a P is porosity (@ref RM_SetPorosity); or -!> 2, @a Mp is mol/L of rock in the RV, @a Mc = @a Mp*(1-P)*RV. -!> -!> If a single EXCHANGE definition is used for cells with different initial porosity, -!> the three options scale quite differently. -!> For option 0, the number of moles of exchangers will be the same regardless of porosity. -!> For option 1, the number of moles of exchangers will be vary directly with porosity and inversely with rock volume. -!> For option 2, the number of moles of exchangers will vary directly with rock volume and inversely with porosity. -!> -!> @param id The instance @a id returned from @ref RM_Create. -!> @param option Units option for exchangers: 0, 1, or 2. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_InitialPhreeqc2Module, -!> @ref RM_InitialPhreeqcCell2Module, -!> @ref RM_SetPorosity, -!> @ref RM_SetRepresentativeVolume. -!> -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> status = RM_SetUnitsExchange(id, 1)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root, workers must be in the loop of @ref RM_MpiWorker. - -INTEGER FUNCTION RM_SetUnitsExchange(id, option) + END FUNCTION RM_SetTimeStep + + !> Sets input units for exchangers. + !> In PHREEQC input, exchangers are defined by moles of exchange sites (@a Mp). + !> @a RM_SetUnitsExchange specifies how the number of moles of exchange sites in a reaction cell (@a Mc) + !> is calculated from the input value (@a Mp). + !> + !> Options are + !> 0, @a Mp is mol/L of RV (default), @a Mc = @a Mp*RV, where RV is the representative volume (@ref RM_SetRepresentativeVolume); + !> 1, @a Mp is mol/L of water in the RV, @a Mc = @a Mp*P*RV, where @a P is porosity (@ref RM_SetPorosity); or + !> 2, @a Mp is mol/L of rock in the RV, @a Mc = @a Mp*(1-P)*RV. + !> + !> If a single EXCHANGE definition is used for cells with different initial porosity, + !> the three options scale quite differently. + !> For option 0, the number of moles of exchangers will be the same regardless of porosity. + !> For option 1, the number of moles of exchangers will be vary directly with porosity and inversely with rock volume. + !> For option 2, the number of moles of exchangers will vary directly with rock volume and inversely with porosity. + !> + !> @param id The instance @a id returned from @ref RM_Create. + !> @param option Units option for exchangers: 0, 1, or 2. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_InitialPhreeqc2Module, + !> @ref RM_InitialPhreeqcCell2Module, + !> @ref RM_SetPorosity, + !> @ref RM_SetRepresentativeVolume. + !> + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> status = RM_SetUnitsExchange(id, 1)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref RM_MpiWorker. + + INTEGER FUNCTION RM_SetUnitsExchange(id, option) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_SetUnitsExchange(id, option) & - BIND(C, NAME='RMF_SetUnitsExchange') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - INTEGER(KIND=C_INT), INTENT(in) :: option - END FUNCTION RMF_SetUnitsExchange + INTEGER(KIND=C_INT) FUNCTION RMF_SetUnitsExchange(id, option) & + BIND(C, NAME='RMF_SetUnitsExchange') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + INTEGER(KIND=C_INT), INTENT(in) :: option + END FUNCTION RMF_SetUnitsExchange END INTERFACE INTEGER, INTENT(in) :: id INTEGER, INTENT(in) :: option RM_SetUnitsExchange = RMF_SetUnitsExchange(id, option) -END FUNCTION RM_SetUnitsExchange - -!> Set input units for gas phases. -!> In PHREEQC input, gas phases are defined by moles of component gases (@a Mp). -!> @a RM_SetUnitsGasPhase specifies how the number of moles of component gases in a reaction cell (@a Mc) -!> is calculated from the input value (@a Mp). -!> -!> Options are -!> 0, @a Mp is mol/L of RV (default), @a Mc = @a Mp*RV, where RV is the representative volume (@ref RM_SetRepresentativeVolume); -!> 1, @a Mp is mol/L of water in the RV, @a Mc = @a Mp*P*RV, where @a P is porosity (@ref RM_SetPorosity); or -!> 2, @a Mp is mol/L of rock in the RV, @a Mc = @a Mp*(1-@a P)*RV. -!> -!> If a single GAS_PHASE definition is used for cells with different initial porosity, -!> the three options scale quite differently. -!> For option 0, the number of moles of a gas component will be the same regardless of porosity. -!> For option 1, the number of moles of a gas component will be vary directly with porosity and inversely with rock volume. -!> For option 2, the number of moles of a gas component will vary directly with rock volume and inversely with porosity. -!> -!> @param id The instance @a id returned from @ref RM_Create. -!> @param option Units option for gas phases: 0, 1, or 2. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_InitialPhreeqc2Module, -!> @ref RM_InitialPhreeqcCell2Module, -!> @ref RM_SetPorosity, -!> @ref RM_SetRepresentativeVolume. -!> -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> status = RM_SetUnitsGasPhase(id, 1)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root, workers must be in the loop of @ref RM_MpiWorker. - -INTEGER FUNCTION RM_SetUnitsGasPhase(id, option) + END FUNCTION RM_SetUnitsExchange + + !> Set input units for gas phases. + !> In PHREEQC input, gas phases are defined by moles of component gases (@a Mp). + !> @a RM_SetUnitsGasPhase specifies how the number of moles of component gases in a reaction cell (@a Mc) + !> is calculated from the input value (@a Mp). + !> + !> Options are + !> 0, @a Mp is mol/L of RV (default), @a Mc = @a Mp*RV, where RV is the representative volume (@ref RM_SetRepresentativeVolume); + !> 1, @a Mp is mol/L of water in the RV, @a Mc = @a Mp*P*RV, where @a P is porosity (@ref RM_SetPorosity); or + !> 2, @a Mp is mol/L of rock in the RV, @a Mc = @a Mp*(1-@a P)*RV. + !> + !> If a single GAS_PHASE definition is used for cells with different initial porosity, + !> the three options scale quite differently. + !> For option 0, the number of moles of a gas component will be the same regardless of porosity. + !> For option 1, the number of moles of a gas component will be vary directly with porosity and inversely with rock volume. + !> For option 2, the number of moles of a gas component will vary directly with rock volume and inversely with porosity. + !> + !> @param id The instance @a id returned from @ref RM_Create. + !> @param option Units option for gas phases: 0, 1, or 2. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_InitialPhreeqc2Module, + !> @ref RM_InitialPhreeqcCell2Module, + !> @ref RM_SetPorosity, + !> @ref RM_SetRepresentativeVolume. + !> + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> status = RM_SetUnitsGasPhase(id, 1)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref RM_MpiWorker. + + INTEGER FUNCTION RM_SetUnitsGasPhase(id, option) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_SetUnitsGasPhase(id, option) & - BIND(C, NAME='RMF_SetUnitsGasPhase') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - INTEGER(KIND=C_INT), INTENT(in) :: option - END FUNCTION RMF_SetUnitsGasPhase + INTEGER(KIND=C_INT) FUNCTION RMF_SetUnitsGasPhase(id, option) & + BIND(C, NAME='RMF_SetUnitsGasPhase') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + INTEGER(KIND=C_INT), INTENT(in) :: option + END FUNCTION RMF_SetUnitsGasPhase END INTERFACE INTEGER, INTENT(in) :: id INTEGER, INTENT(in) :: option RM_SetUnitsGasPhase = RMF_SetUnitsGasPhase(id, option) -END FUNCTION RM_SetUnitsGasPhase - -!> Set input units for kinetic reactants. -!> -!> In PHREEQC input, kinetics are defined by moles of kinetic reactants (@a Mp). -!> @a RM_SetUnitsKinetics specifies how the number of moles of kinetic reactants in a reaction cell (@a Mc) -!> is calculated from the input value (@a Mp). -!> -!> Options are -!> 0, @a Mp is mol/L of RV (default), @a Mc = @a Mp*RV, where RV is the representative volume (@ref RM_SetRepresentativeVolume); -!> 1, @a Mp is mol/L of water in the RV, @a Mc = @a Mp*P*RV, where @a P is porosity (@ref RM_SetPorosity); or -!> 2, @a Mp is mol/L of rock in the RV, @a Mc = @a Mp*(1-@a P)*RV. -!> -!> If a single KINETICS definition is used for cells with different initial porosity, -!> the three options scale quite differently. -!> For option 0, the number of moles of kinetic reactants will be the same regardless of porosity. -!> For option 1, the number of moles of kinetic reactants will be vary directly with porosity and inversely with rock volume. -!> For option 2, the number of moles of kinetic reactants will vary directly with rock volume and inversely with porosity. -!> -!> Note that the volume of water in a cell in the reaction module is equal to the product of -!> porosity (@ref RM_SetPorosity), the saturation (@ref RM_SetSaturation), and representative volume (@ref -!> RM_SetRepresentativeVolume), which is usually less than 1 liter. It is important to write the RATES -!> definitions for homogeneous (aqueous) kinetic reactions to account for the current volume of -!> water, often by calculating the rate of reaction per liter of water and multiplying by the volume -!> of water (Basic function SOLN_VOL). -!> -!> Rates that depend on surface area of solids, are not dependent -!> on the volume of water. However, it is important to get the correct surface area for the kinetic -!> reaction. To scale the surface area with the number of moles, the specific area (m^2 per mole of reactant) -!> can be defined as a parameter (KINETICS; -parm), which is multiplied by the number of moles of -!> reactant (Basic function M) in RATES to obtain the surface area. -!> -!> @param id The instance @a id returned from @ref RM_Create. -!> @param option Units option for kinetic reactants: 0, 1, or 2. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_InitialPhreeqc2Module, -!> @ref RM_InitialPhreeqcCell2Module, -!> @ref RM_SetPorosity, -!> @ref RM_SetRepresentativeVolume, -!> @ref RM_SetSaturation. -!> -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> status = RM_SetUnitsKinetics(id, 1)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root, workers must be in the loop of @ref RM_MpiWorker. - -INTEGER FUNCTION RM_SetUnitsKinetics(id, option) + END FUNCTION RM_SetUnitsGasPhase + + !> Set input units for kinetic reactants. + !> + !> In PHREEQC input, kinetics are defined by moles of kinetic reactants (@a Mp). + !> @a RM_SetUnitsKinetics specifies how the number of moles of kinetic reactants in a reaction cell (@a Mc) + !> is calculated from the input value (@a Mp). + !> + !> Options are + !> 0, @a Mp is mol/L of RV (default), @a Mc = @a Mp*RV, where RV is the representative volume (@ref RM_SetRepresentativeVolume); + !> 1, @a Mp is mol/L of water in the RV, @a Mc = @a Mp*P*RV, where @a P is porosity (@ref RM_SetPorosity); or + !> 2, @a Mp is mol/L of rock in the RV, @a Mc = @a Mp*(1-@a P)*RV. + !> + !> If a single KINETICS definition is used for cells with different initial porosity, + !> the three options scale quite differently. + !> For option 0, the number of moles of kinetic reactants will be the same regardless of porosity. + !> For option 1, the number of moles of kinetic reactants will be vary directly with porosity and inversely with rock volume. + !> For option 2, the number of moles of kinetic reactants will vary directly with rock volume and inversely with porosity. + !> + !> Note that the volume of water in a cell in the reaction module is equal to the product of + !> porosity (@ref RM_SetPorosity), the saturation (@ref RM_SetSaturation), and representative volume (@ref + !> RM_SetRepresentativeVolume), which is usually less than 1 liter. It is important to write the RATES + !> definitions for homogeneous (aqueous) kinetic reactions to account for the current volume of + !> water, often by calculating the rate of reaction per liter of water and multiplying by the volume + !> of water (Basic function SOLN_VOL). + !> + !> Rates that depend on surface area of solids, are not dependent + !> on the volume of water. However, it is important to get the correct surface area for the kinetic + !> reaction. To scale the surface area with the number of moles, the specific area (m^2 per mole of reactant) + !> can be defined as a parameter (KINETICS; -parm), which is multiplied by the number of moles of + !> reactant (Basic function M) in RATES to obtain the surface area. + !> + !> @param id The instance @a id returned from @ref RM_Create. + !> @param option Units option for kinetic reactants: 0, 1, or 2. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_InitialPhreeqc2Module, + !> @ref RM_InitialPhreeqcCell2Module, + !> @ref RM_SetPorosity, + !> @ref RM_SetRepresentativeVolume, + !> @ref RM_SetSaturation. + !> + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> status = RM_SetUnitsKinetics(id, 1)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref RM_MpiWorker. + + INTEGER FUNCTION RM_SetUnitsKinetics(id, option) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_SetUnitsKinetics(id, option) & - BIND(C, NAME='RMF_SetUnitsKinetics') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - INTEGER(KIND=C_INT), INTENT(in) :: option - END FUNCTION RMF_SetUnitsKinetics + INTEGER(KIND=C_INT) FUNCTION RMF_SetUnitsKinetics(id, option) & + BIND(C, NAME='RMF_SetUnitsKinetics') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + INTEGER(KIND=C_INT), INTENT(in) :: option + END FUNCTION RMF_SetUnitsKinetics END INTERFACE INTEGER, INTENT(in) :: id INTEGER, INTENT(in) :: option RM_SetUnitsKinetics = RMF_SetUnitsKinetics(id, option) -END FUNCTION RM_SetUnitsKinetics - -!> Set input units for pure phase assemblages (equilibrium phases). -!> In PHREEQC input, equilibrium phases are defined by moles of each phase (@a Mp). -!> @a RM_SetUnitsPPassemblage specifies how the number of moles of phases in a reaction cell (@a Mc) -!> is calculated from the input value (@a Mp). -!> -!> Options are -!> 0, @a Mp is mol/L of RV (default), @a Mc = @a Mp*RV, where RV is the representative volume (@ref RM_SetRepresentativeVolume); -!> 1, @a Mp is mol/L of water in the RV, @a Mc = @a Mp*P*RV, where @a P is porosity (@ref RM_SetPorosity); or -!> 2, @a Mp is mol/L of rock in the RV, @a Mc = @a Mp*(1-@a P)*RV. -!> -!> If a single EQUILIBRIUM_PHASES definition is used for cells with different initial porosity, -!> the three options scale quite differently. -!> For option 0, the number of moles of a mineral will be the same regardless of porosity. -!> For option 1, the number of moles of a mineral will be vary directly with porosity and inversely with rock volume. -!> For option 2, the number of moles of a mineral will vary directly with rock volume and inversely with porosity. -!> -!> @param id The instance @a id returned from @ref RM_Create. -!> @param option Units option for equilibrium phases: 0, 1, or 2. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_InitialPhreeqc2Module, -!> @ref RM_InitialPhreeqcCell2Module, -!> @ref RM_SetPorosity, -!> @ref RM_SetRepresentativeVolume. -!> -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> status = RM_SetUnitsPPassemblage(id, 1)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root, workers must be in the loop of @ref RM_MpiWorker. - -INTEGER FUNCTION RM_SetUnitsPPassemblage(id, option) + END FUNCTION RM_SetUnitsKinetics + + !> Set input units for pure phase assemblages (equilibrium phases). + !> In PHREEQC input, equilibrium phases are defined by moles of each phase (@a Mp). + !> @a RM_SetUnitsPPassemblage specifies how the number of moles of phases in a reaction cell (@a Mc) + !> is calculated from the input value (@a Mp). + !> + !> Options are + !> 0, @a Mp is mol/L of RV (default), @a Mc = @a Mp*RV, where RV is the representative volume (@ref RM_SetRepresentativeVolume); + !> 1, @a Mp is mol/L of water in the RV, @a Mc = @a Mp*P*RV, where @a P is porosity (@ref RM_SetPorosity); or + !> 2, @a Mp is mol/L of rock in the RV, @a Mc = @a Mp*(1-@a P)*RV. + !> + !> If a single EQUILIBRIUM_PHASES definition is used for cells with different initial porosity, + !> the three options scale quite differently. + !> For option 0, the number of moles of a mineral will be the same regardless of porosity. + !> For option 1, the number of moles of a mineral will be vary directly with porosity and inversely with rock volume. + !> For option 2, the number of moles of a mineral will vary directly with rock volume and inversely with porosity. + !> + !> @param id The instance @a id returned from @ref RM_Create. + !> @param option Units option for equilibrium phases: 0, 1, or 2. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_InitialPhreeqc2Module, + !> @ref RM_InitialPhreeqcCell2Module, + !> @ref RM_SetPorosity, + !> @ref RM_SetRepresentativeVolume. + !> + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> status = RM_SetUnitsPPassemblage(id, 1)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref RM_MpiWorker. + + INTEGER FUNCTION RM_SetUnitsPPassemblage(id, option) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_SetUnitsPPassemblage(id, option) & - BIND(C, NAME='RMF_SetUnitsPPassemblage') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - INTEGER(KIND=C_INT), INTENT(in) :: option - END FUNCTION RMF_SetUnitsPPassemblage + INTEGER(KIND=C_INT) FUNCTION RMF_SetUnitsPPassemblage(id, option) & + BIND(C, NAME='RMF_SetUnitsPPassemblage') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + INTEGER(KIND=C_INT), INTENT(in) :: option + END FUNCTION RMF_SetUnitsPPassemblage END INTERFACE INTEGER, INTENT(in) :: id INTEGER, INTENT(in) :: option RM_SetUnitsPPassemblage = RMF_SetUnitsPPassemblage(id, option) -END FUNCTION RM_SetUnitsPPassemblage - -!> Solution concentration units used by the transport model. -!> Options are 1, mg/L; 2 mol/L; or 3, mass fraction, kg/kgs. -!> PHREEQC defines solutions by the number of moles of each -!> element in the solution. -!> @n@n -!> To convert from mg/L to moles -!> of element in the representative volume of a reaction cell, mg/L is converted to mol/L and -!> multiplied by the solution volume, -!> which is the product of porosity (@ref RM_SetPorosity), saturation (@ref RM_SetSaturation), -!> and representative volume (@ref RM_SetRepresentativeVolume). -!> To convert from mol/L to moles -!> of element in the representative volume of a reaction cell, mol/L is -!> multiplied by the solution volume. -!> To convert from mass fraction to moles -!> of element in the representative volume of a reaction cell, kg/kgs is converted to mol/kgs, multiplied by density -!> (@ref RM_SetDensity) and -!> multiplied by the solution volume. -!> -!> To convert from moles -!> of element in the representative volume of a reaction cell to mg/L, the number of moles of an element is divided by the -!> solution volume resulting in mol/L, and then converted to mg/L. -!> To convert from moles -!> of element in a cell to mol/L, the number of moles of an element is divided by the -!> solution volume resulting in mol/L. -!> To convert from moles -!> of element in a cell to mass fraction, the number of moles of an element is converted to kg and divided -!> by the total mass of the solution. -!> Two options are available for the volume and mass of solution -!> that are used in converting to transport concentrations: (1) the volume and mass of solution are -!> calculated by PHREEQC, or (2) the volume of solution is the product of porosity (@ref RM_SetPorosity), -!> saturation (@ref RM_SetSaturation), and representative volume (@ref RM_SetRepresentativeVolume), -!> and the mass of solution is volume times density as defined by @ref RM_SetDensity. -!> Which option is used is determined by @ref RM_UseSolutionDensityVolume. -!> -!> @param id The instance @a id returned from @ref RM_Create. -!> @param option Units option for solutions: 1, 2, or 3, default is 1, mg/L. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_SetDensity, -!> @ref RM_SetPorosity, -!> @ref RM_SetRepresentativeVolume, -!> @ref RM_SetSaturation, -!> @ref RM_UseSolutionDensityVolume. -!> -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> status = RM_SetUnitsSolution(id, 1)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root, workers must be in the loop of @ref RM_MpiWorker. - -INTEGER FUNCTION RM_SetUnitsSolution(id, option) + END FUNCTION RM_SetUnitsPPassemblage + + !> Solution concentration units used by the transport model. + !> Options are 1, mg/L; 2 mol/L; or 3, mass fraction, kg/kgs. + !> PHREEQC defines solutions by the number of moles of each + !> element in the solution. + !> @n@n + !> To convert from mg/L to moles + !> of element in the representative volume of a reaction cell, mg/L is converted to mol/L and + !> multiplied by the solution volume, + !> which is the product of porosity (@ref RM_SetPorosity), saturation (@ref RM_SetSaturation), + !> and representative volume (@ref RM_SetRepresentativeVolume). + !> To convert from mol/L to moles + !> of element in the representative volume of a reaction cell, mol/L is + !> multiplied by the solution volume. + !> To convert from mass fraction to moles + !> of element in the representative volume of a reaction cell, kg/kgs is converted to mol/kgs, multiplied by density + !> (@ref RM_SetDensity) and + !> multiplied by the solution volume. + !> + !> To convert from moles + !> of element in the representative volume of a reaction cell to mg/L, the number of moles of an element is divided by the + !> solution volume resulting in mol/L, and then converted to mg/L. + !> To convert from moles + !> of element in a cell to mol/L, the number of moles of an element is divided by the + !> solution volume resulting in mol/L. + !> To convert from moles + !> of element in a cell to mass fraction, the number of moles of an element is converted to kg and divided + !> by the total mass of the solution. + !> Two options are available for the volume and mass of solution + !> that are used in converting to transport concentrations: (1) the volume and mass of solution are + !> calculated by PHREEQC, or (2) the volume of solution is the product of porosity (@ref RM_SetPorosity), + !> saturation (@ref RM_SetSaturation), and representative volume (@ref RM_SetRepresentativeVolume), + !> and the mass of solution is volume times density as defined by @ref RM_SetDensity. + !> Which option is used is determined by @ref RM_UseSolutionDensityVolume. + !> + !> @param id The instance @a id returned from @ref RM_Create. + !> @param option Units option for solutions: 1, 2, or 3, default is 1, mg/L. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_SetDensity, + !> @ref RM_SetPorosity, + !> @ref RM_SetRepresentativeVolume, + !> @ref RM_SetSaturation, + !> @ref RM_UseSolutionDensityVolume. + !> + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> status = RM_SetUnitsSolution(id, 1)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref RM_MpiWorker. + + INTEGER FUNCTION RM_SetUnitsSolution(id, option) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_SetUnitsSolution(id, option) & - BIND(C, NAME='RMF_SetUnitsSolution') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - INTEGER(KIND=C_INT), INTENT(in) :: option - END FUNCTION RMF_SetUnitsSolution + INTEGER(KIND=C_INT) FUNCTION RMF_SetUnitsSolution(id, option) & + BIND(C, NAME='RMF_SetUnitsSolution') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + INTEGER(KIND=C_INT), INTENT(in) :: option + END FUNCTION RMF_SetUnitsSolution END INTERFACE INTEGER, INTENT(in) :: id INTEGER, INTENT(in) :: option RM_SetUnitsSolution = RMF_SetUnitsSolution(id, option) -END FUNCTION RM_SetUnitsSolution - -!> Set input units for solid-solution assemblages. -!> In PHREEQC, solid solutions are defined by moles of each component (@a Mp). -!> @a RM_SetUnitsSSassemblage specifies how the number of moles of solid-solution components in a reaction cell (@a Mc) -!> is calculated from the input value (@a Mp). -!> -!> Options are -!> 0, @a Mp is mol/L of RV (default), @a Mc = @a Mp*RV, where RV is the representative volume (@ref RM_SetRepresentativeVolume); -!> 1, @a Mp is mol/L of water in the RV, @a Mc = @a Mp*P*RV, where @a P is porosity (@ref RM_SetPorosity); or -!> 2, @a Mp is mol/L of rock in the RV, @a Mc = @a Mp*(1-@a P)*RV. -!> -!> @param id The instance @a id returned from @ref RM_Create. -!> @param option Units option for solid solutions: 0, 1, or 2. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_InitialPhreeqc2Module, -!> @ref RM_InitialPhreeqcCell2Module, -!> @ref RM_SetPorosity, -!> @ref RM_SetRepresentativeVolume. -!> -!> If a single SOLID_SOLUTION definition is used for cells with different initial porosity, -!> the three options scale quite differently. -!> For option 0, the number of moles of a solid-solution component will be the same regardless of porosity. -!> For option 1, the number of moles of a solid-solution component will be vary directly with porosity and inversely with rock volume. -!> For option 2, the number of moles of a solid-solution component will vary directly with rock volume and inversely with porosity. -!> -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> status = RM_SetUnitsSSassemblage(id, 1)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root, workers must be in the loop of @ref RM_MpiWorker. - -INTEGER FUNCTION RM_SetUnitsSSassemblage(id, option) + END FUNCTION RM_SetUnitsSolution + + !> Set input units for solid-solution assemblages. + !> In PHREEQC, solid solutions are defined by moles of each component (@a Mp). + !> @a RM_SetUnitsSSassemblage specifies how the number of moles of solid-solution components in a reaction cell (@a Mc) + !> is calculated from the input value (@a Mp). + !> + !> Options are + !> 0, @a Mp is mol/L of RV (default), @a Mc = @a Mp*RV, where RV is the representative volume (@ref RM_SetRepresentativeVolume); + !> 1, @a Mp is mol/L of water in the RV, @a Mc = @a Mp*P*RV, where @a P is porosity (@ref RM_SetPorosity); or + !> 2, @a Mp is mol/L of rock in the RV, @a Mc = @a Mp*(1-@a P)*RV. + !> + !> @param id The instance @a id returned from @ref RM_Create. + !> @param option Units option for solid solutions: 0, 1, or 2. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_InitialPhreeqc2Module, + !> @ref RM_InitialPhreeqcCell2Module, + !> @ref RM_SetPorosity, + !> @ref RM_SetRepresentativeVolume. + !> + !> If a single SOLID_SOLUTION definition is used for cells with different initial porosity, + !> the three options scale quite differently. + !> For option 0, the number of moles of a solid-solution component will be the same regardless of porosity. + !> For option 1, the number of moles of a solid-solution component will be vary directly with porosity and inversely with rock volume. + !> For option 2, the number of moles of a solid-solution component will vary directly with rock volume and inversely with porosity. + !> + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> status = RM_SetUnitsSSassemblage(id, 1)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref RM_MpiWorker. + + INTEGER FUNCTION RM_SetUnitsSSassemblage(id, option) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_SetUnitsSSassemblage(id, option) & - BIND(C, NAME='RMF_SetUnitsSSassemblage') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - INTEGER(KIND=C_INT), INTENT(in) :: option - END FUNCTION RMF_SetUnitsSSassemblage + INTEGER(KIND=C_INT) FUNCTION RMF_SetUnitsSSassemblage(id, option) & + BIND(C, NAME='RMF_SetUnitsSSassemblage') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + INTEGER(KIND=C_INT), INTENT(in) :: option + END FUNCTION RMF_SetUnitsSSassemblage END INTERFACE INTEGER, INTENT(in) :: id INTEGER, INTENT(in) :: option RM_SetUnitsSSassemblage = RMF_SetUnitsSSassemblage(id, option) -END FUNCTION RM_SetUnitsSSassemblage - -!> Set input units for surfaces. -!> In PHREEQC input, surfaces are defined by moles of surface sites (@a Mp). -!> @a RM_SetUnitsSurface specifies how the number of moles of surface sites in a reaction cell (@a Mc) -!> is calculated from the input value (@a Mp). -!> -!> Options are -!> 0, @a Mp is mol/L of RV (default), @a Mc = @a Mp*RV, where RV is the representative volume (@ref RM_SetRepresentativeVolume); -!> 1, @a Mp is mol/L of water in the RV, @a Mc = @a Mp*P*RV, where @a P is porosity (@ref RM_SetPorosity); or -!> 2, @a Mp is mol/L of rock in the RV, @a Mc = @a Mp*(1-@a P)*RV. -!> -!> If a single SURFACE definition is used for cells with different initial porosity, -!> the three options scale quite differently. -!> For option 0, the number of moles of surface sites will be the same regardless of porosity. -!> For option 1, the number of moles of surface sites will be vary directly with porosity and inversely with rock volume. -!> For option 2, the number of moles of surface sites will vary directly with rock volume and inversely with porosity. -!> -!> @param id The instance @a id returned from @ref RM_Create. -!> @param option Units option for surfaces: 0, 1, or 2. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_InitialPhreeqc2Module, -!> @ref RM_InitialPhreeqcCell2Module, -!> @ref RM_SetPorosity, -!> @ref RM_SetRepresentativeVolume. -!> -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> status = RM_SetUnitsSurface(id, 1)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root, workers must be in the loop of @ref RM_MpiWorker. - -INTEGER FUNCTION RM_SetUnitsSurface(id, option) + END FUNCTION RM_SetUnitsSSassemblage + + !> Set input units for surfaces. + !> In PHREEQC input, surfaces are defined by moles of surface sites (@a Mp). + !> @a RM_SetUnitsSurface specifies how the number of moles of surface sites in a reaction cell (@a Mc) + !> is calculated from the input value (@a Mp). + !> + !> Options are + !> 0, @a Mp is mol/L of RV (default), @a Mc = @a Mp*RV, where RV is the representative volume (@ref RM_SetRepresentativeVolume); + !> 1, @a Mp is mol/L of water in the RV, @a Mc = @a Mp*P*RV, where @a P is porosity (@ref RM_SetPorosity); or + !> 2, @a Mp is mol/L of rock in the RV, @a Mc = @a Mp*(1-@a P)*RV. + !> + !> If a single SURFACE definition is used for cells with different initial porosity, + !> the three options scale quite differently. + !> For option 0, the number of moles of surface sites will be the same regardless of porosity. + !> For option 1, the number of moles of surface sites will be vary directly with porosity and inversely with rock volume. + !> For option 2, the number of moles of surface sites will vary directly with rock volume and inversely with porosity. + !> + !> @param id The instance @a id returned from @ref RM_Create. + !> @param option Units option for surfaces: 0, 1, or 2. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_InitialPhreeqc2Module, + !> @ref RM_InitialPhreeqcCell2Module, + !> @ref RM_SetPorosity, + !> @ref RM_SetRepresentativeVolume. + !> + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> status = RM_SetUnitsSurface(id, 1)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref RM_MpiWorker. + + INTEGER FUNCTION RM_SetUnitsSurface(id, option) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_SetUnitsSurface(id, option) & - BIND(C, NAME='RMF_SetUnitsSurface') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - INTEGER(KIND=C_INT), INTENT(in) :: option - END FUNCTION RMF_SetUnitsSurface + INTEGER(KIND=C_INT) FUNCTION RMF_SetUnitsSurface(id, option) & + BIND(C, NAME='RMF_SetUnitsSurface') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + INTEGER(KIND=C_INT), INTENT(in) :: option + END FUNCTION RMF_SetUnitsSurface END INTERFACE INTEGER, INTENT(in) :: id INTEGER, INTENT(in) :: option RM_SetUnitsSurface = RMF_SetUnitsSurface(id, option) -END FUNCTION RM_SetUnitsSurface - -!> Set solution concentrations in the reaction cells -!> based on the vector of aqueous species concentrations (@a species_conc). -!> This method is intended for use with multicomponent-diffusion transport calculations, -!> and @ref RM_SetSpeciesSaveOn must be set to @a true. -!> The list of aqueous species is determined by @ref RM_FindComponents and includes all -!> aqueous species that can be made from the set of components. -!> The method determines the total concentration of a component -!> by summing the molarities of the individual species times the stoichiometric -!> coefficient of the element in each species. -!> Solution compositions in the reaction cells are updated with these component concentrations. -!> -!> @param id The instance @a id returned from @ref RM_Create. -!> @param species_conc Array of aqueous species concentrations. Dimension of the array is (@a nxyz, @a nspecies), -!> where @a nxyz is the number of user grid cells (@ref RM_GetGridCellCount), and @a nspecies is the number of aqueous species (@ref RM_GetSpeciesCount). -!> Concentrations are moles per liter. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_FindComponents, -!> @ref RM_GetSpeciesConcentrations, -!> @ref RM_GetSpeciesCount, -!> @ref RM_GetSpeciesD25, -!> @ref RM_GetSpeciesLog10Gammas, -!> @ref RM_GetSpeciesLog10Molalities, -!> @ref RM_GetSpeciesName, -!> @ref RM_GetSpeciesSaveOn, -!> @ref RM_GetSpeciesZ, -!> @ref RM_SetSpeciesSaveOn. -!> -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> status = RM_SetSpeciesSaveOn(id, 1)
-!> ncomps = RM_FindComponents(id)
-!> nspecies = RM_GetSpeciesCount(id)
-!> nxyz = RM_GetGridCellCount(id)
-!> allocate(species_c(nxyz, nspecies))
-!> ...
-!> status = RM_SpeciesConcentrations2Module(id, species_c(1,1))
-!> status = RM_RunCells(id)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root, workers must be in the loop of @ref RM_MpiWorker. - -INTEGER FUNCTION RM_SpeciesConcentrations2Module(id, species_conc) + END FUNCTION RM_SetUnitsSurface + + !> Set solution concentrations in the reaction cells + !> based on the vector of aqueous species concentrations (@a species_conc). + !> This method is intended for use with multicomponent-diffusion transport calculations, + !> and @ref RM_SetSpeciesSaveOn must be set to @a true. + !> The list of aqueous species is determined by @ref RM_FindComponents and includes all + !> aqueous species that can be made from the set of components. + !> The method determines the total concentration of a component + !> by summing the molarities of the individual species times the stoichiometric + !> coefficient of the element in each species. + !> Solution compositions in the reaction cells are updated with these component concentrations. + !> + !> @param id The instance @a id returned from @ref RM_Create. + !> @param species_conc Array of aqueous species concentrations. Dimension of the array is (@a nxyz, @a nspecies), + !> where @a nxyz is the number of user grid cells (@ref RM_GetGridCellCount), and @a nspecies is the number of aqueous species (@ref RM_GetSpeciesCount). + !> Concentrations are moles per liter. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_FindComponents, + !> @ref RM_GetSpeciesConcentrations, + !> @ref RM_GetSpeciesCount, + !> @ref RM_GetSpeciesD25, + !> @ref RM_GetSpeciesLog10Gammas, + !> @ref RM_GetSpeciesLog10Molalities, + !> @ref RM_GetSpeciesName, + !> @ref RM_GetSpeciesSaveOn, + !> @ref RM_GetSpeciesZ, + !> @ref RM_SetSpeciesSaveOn. + !> + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> status = RM_SetSpeciesSaveOn(id, 1)
+    !> ncomps = RM_FindComponents(id)
+    !> nspecies = RM_GetSpeciesCount(id)
+    !> nxyz = RM_GetGridCellCount(id)
+    !> allocate(species_c(nxyz, nspecies))
+    !> ...
+    !> status = RM_SpeciesConcentrations2Module(id, species_c(1,1))
+    !> status = RM_RunCells(id)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref RM_MpiWorker. + + INTEGER FUNCTION RM_SpeciesConcentrations2Module(id, species_conc) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_SpeciesConcentrations2Module(id, species_conc) & - BIND(C, NAME='RMF_SpeciesConcentrations2Module') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - REAL(KIND=C_DOUBLE), INTENT(in) :: species_conc(*) - END FUNCTION RMF_SpeciesConcentrations2Module + INTEGER(KIND=C_INT) FUNCTION RMF_SpeciesConcentrations2Module(id, species_conc) & + BIND(C, NAME='RMF_SpeciesConcentrations2Module') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + REAL(KIND=C_DOUBLE), INTENT(in) :: species_conc(*) + END FUNCTION RMF_SpeciesConcentrations2Module END INTERFACE INTEGER, INTENT(in) :: id - DOUBLE PRECISION, DIMENSION(:,:), INTENT(in) :: species_conc + real(kind=8), DIMENSION(:,:), INTENT(in) :: species_conc if (rmf_debug) call Chk_SpeciesConcentrations2Module(id, species_conc) RM_SpeciesConcentrations2Module = RMF_SpeciesConcentrations2Module(id, species_conc) -END FUNCTION RM_SpeciesConcentrations2Module + END FUNCTION RM_SpeciesConcentrations2Module -SUBROUTINE Chk_SpeciesConcentrations2Module(id, species_conc) + SUBROUTINE Chk_SpeciesConcentrations2Module(id, species_conc) IMPLICIT NONE INTEGER, INTENT(in) :: id - DOUBLE PRECISION, DIMENSION(:,:), INTENT(in) :: species_conc + real(kind=8), DIMENSION(:,:), INTENT(in) :: species_conc INTEGER :: errors, nspecies nspecies = RM_GetSpeciesCount(id) errors = 0 @@ -6489,235 +6835,235 @@ SUBROUTINE Chk_SpeciesConcentrations2Module(id, species_conc) if (errors .gt. 0) then errors = RM_Abort(id, -3, "Invalid argument in RM_SpeciesConcentrations2Module") endif -END SUBROUTINE Chk_SpeciesConcentrations2Module - -!> Save the state of the chemistry in all model cells, including SOLUTIONs, -!> EQUILIBRIUM_PHASES, EXCHANGEs, GAS_PHASEs, KINETICS, SOLID_SOLUTIONs, and SURFACEs. -!> Although not generally used, MIXes, REACTIONs, REACTION_PRESSUREs, and REACTION_TEMPERATUREs -!> will be saved for each cell, if they have been defined in the worker IPhreeqc instances. -!> The distribution of cells among the workers and the chemistry of fully or partially -!> unsaturated cells are also saved. The state is saved in memory; use @ref RM_DumpModule to save the state -!> to file. PhreeqcRM can be reset to this state by using @ref RM_StateApply. -!> A state is identified by an integer, and multiple states can be saved. -!> -!> @param id The instance @a id returned from @ref RM_Create. -!> @param istate Integer identifying the state that is saved. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see @ref RM_DumpModule, -!> @ref RM_StateApply, and -!> @ref RM_StateDelete. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> status = RM_StateSave(id, 1)
-!> ...
-!> status = RM_StateApply(id, 1)
-!> status = RM_StateDelete(id, 1)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root, workers must be in the loop of @ref RM_MpiWorker. - -INTEGER FUNCTION RM_StateSave(id, istate) + END SUBROUTINE Chk_SpeciesConcentrations2Module + + !> Save the state of the chemistry in all model cells, including SOLUTIONs, + !> EQUILIBRIUM_PHASES, EXCHANGEs, GAS_PHASEs, KINETICS, SOLID_SOLUTIONs, and SURFACEs. + !> Although not generally used, MIXes, REACTIONs, REACTION_PRESSUREs, and REACTION_TEMPERATUREs + !> will be saved for each cell, if they have been defined in the worker IPhreeqc instances. + !> The distribution of cells among the workers and the chemistry of fully or partially + !> unsaturated cells are also saved. The state is saved in memory; use @ref RM_DumpModule to save the state + !> to file. PhreeqcRM can be reset to this state by using @ref RM_StateApply. + !> A state is identified by an integer, and multiple states can be saved. + !> + !> @param id The instance @a id returned from @ref RM_Create. + !> @param istate Integer identifying the state that is saved. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see @ref RM_DumpModule, + !> @ref RM_StateApply, and + !> @ref RM_StateDelete. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> status = RM_StateSave(id, 1)
+    !> ...
+    !> status = RM_StateApply(id, 1)
+    !> status = RM_StateDelete(id, 1)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref RM_MpiWorker. + + INTEGER FUNCTION RM_StateSave(id, istate) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_StateSave(id, istate) & - BIND(C, NAME='RMF_StateSave') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - INTEGER(KIND=C_INT), INTENT(in) :: istate - END FUNCTION RMF_StateSave + INTEGER(KIND=C_INT) FUNCTION RMF_StateSave(id, istate) & + BIND(C, NAME='RMF_StateSave') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + INTEGER(KIND=C_INT), INTENT(in) :: istate + END FUNCTION RMF_StateSave END INTERFACE INTEGER, INTENT(in) :: id INTEGER, INTENT(in) :: istate RM_StateSave = RMF_StateSave(id, istate) -END FUNCTION RM_StateSave - -!> Reset the state of the module to a state previously saved with @ref RM_StateSave. -!> The chemistry of all model cells are reset, including SOLUTIONs, -!> EQUILIBRIUM_PHASES, EXCHANGEs, GAS_PHASEs, KINETICS, SOLID_SOLUTIONs, and SURFACEs. -!> MIXes, REACTIONs, REACTION_PRESSUREs, and REACTION_TEMPERATUREs -!> will be reset for each cell, if they were defined in the worker IPhreeqc instances -!> at the time the state was saved. -!> The distribution of cells among the workers and the chemistry of fully or partially -!> unsaturated cells are also reset to the saved state. -!> The state to be applied is identified by an integer. -!> -!> @param id The instance @a id returned from @ref RM_Create. -!> @param istate Integer identifying the state that is to be applied. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see @ref RM_StateSave and -!> @ref RM_StateDelete. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> status = RM_StateSave(id, 1)
-!> ...
-!> status = RM_StateApply(id, 1)
-!> status = RM_StateDelete(id, 1)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root, workers must be in the loop of @ref RM_MpiWorker. - -INTEGER FUNCTION RM_StateApply(id, istate) + END FUNCTION RM_StateSave + + !> Reset the state of the module to a state previously saved with @ref RM_StateSave. + !> The chemistry of all model cells are reset, including SOLUTIONs, + !> EQUILIBRIUM_PHASES, EXCHANGEs, GAS_PHASEs, KINETICS, SOLID_SOLUTIONs, and SURFACEs. + !> MIXes, REACTIONs, REACTION_PRESSUREs, and REACTION_TEMPERATUREs + !> will be reset for each cell, if they were defined in the worker IPhreeqc instances + !> at the time the state was saved. + !> The distribution of cells among the workers and the chemistry of fully or partially + !> unsaturated cells are also reset to the saved state. + !> The state to be applied is identified by an integer. + !> + !> @param id The instance @a id returned from @ref RM_Create. + !> @param istate Integer identifying the state that is to be applied. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see @ref RM_StateSave and + !> @ref RM_StateDelete. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> status = RM_StateSave(id, 1)
+    !> ...
+    !> status = RM_StateApply(id, 1)
+    !> status = RM_StateDelete(id, 1)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref RM_MpiWorker. + + INTEGER FUNCTION RM_StateApply(id, istate) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_StateApply(id, istate) & - BIND(C, NAME='RMF_StateApply') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - INTEGER(KIND=C_INT), INTENT(in) :: istate - END FUNCTION RMF_StateApply + INTEGER(KIND=C_INT) FUNCTION RMF_StateApply(id, istate) & + BIND(C, NAME='RMF_StateApply') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + INTEGER(KIND=C_INT), INTENT(in) :: istate + END FUNCTION RMF_StateApply END INTERFACE INTEGER, INTENT(in) :: id INTEGER, INTENT(in) :: istate RM_StateApply = RMF_StateApply(id, istate) -END FUNCTION RM_StateApply - -!> Delete a state previously saved with @ref RM_StateSave. -!> -!> @param id The instance @a id returned from @ref RM_Create. -!> @param istate Integer identifying the state that is to be deleted. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see @ref RM_StateSave and -!> ref RM_StateApply. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> status = RM_StateSave(id, 1)
-!> ...
-!> status = RM_StateApply(id, 1)
-!> status = RM_StateDelete(id, 1)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root, workers must be in the loop of @ref RM_MpiWorker. - -INTEGER FUNCTION RM_StateDelete(id, istate) + END FUNCTION RM_StateApply + + !> Delete a state previously saved with @ref RM_StateSave. + !> + !> @param id The instance @a id returned from @ref RM_Create. + !> @param istate Integer identifying the state that is to be deleted. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see @ref RM_StateSave and + !> ref RM_StateApply. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> status = RM_StateSave(id, 1)
+    !> ...
+    !> status = RM_StateApply(id, 1)
+    !> status = RM_StateDelete(id, 1)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref RM_MpiWorker. + + INTEGER FUNCTION RM_StateDelete(id, istate) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_StateDelete(id, istate) & - BIND(C, NAME='RMF_StateDelete') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - INTEGER(KIND=C_INT), INTENT(in) :: istate - END FUNCTION RMF_StateDelete + INTEGER(KIND=C_INT) FUNCTION RMF_StateDelete(id, istate) & + BIND(C, NAME='RMF_StateDelete') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + INTEGER(KIND=C_INT), INTENT(in) :: istate + END FUNCTION RMF_StateDelete END INTERFACE INTEGER, INTENT(in) :: id INTEGER, INTENT(in) :: istate RM_StateDelete = RMF_StateDelete(id, istate) -END FUNCTION RM_StateDelete -!> Determines the volume and density to use when converting from the reaction-module concentrations -!> to transport concentrations (@ref RM_GetConcentrations). -!> Two options are available to convert concentration units: -!> (1) the density and solution volume calculated by PHREEQC are used, or -!> (2) the specified density (@ref RM_SetDensity) -!> and solution volume are defined by the product of -!> saturation (@ref RM_SetSaturation), porosity (@ref RM_SetPorosity), -!> and representative volume (@ref RM_SetRepresentativeVolume). -!> Transport models that consider density-dependent flow will probably use the -!> PHREEQC-calculated density and solution volume (default), -!> whereas transport models that assume constant-density flow will probably use -!> specified values of density and solution volume. -!> Only the following databases distributed with PhreeqcRM have molar volume information -!> needed to accurately calculate density and solution volume: phreeqc.dat, Amm.dat, and pitzer.dat. -!> Density is only used when converting to transport units of mass fraction. -!> -!> @param id The instance @a id returned from @ref RM_Create. -!> @param tf @a True indicates that the solution density and volume as -!> calculated by PHREEQC will be used to calculate concentrations. -!> @a False indicates that the solution density set by @ref RM_SetDensity and the volume determined by the -!> product of @ref RM_SetSaturation, @ref RM_SetPorosity, and @ref RM_SetRepresentativeVolume, -!> will be used to calculate concentrations retrieved by @ref RM_GetConcentrations. -!> @see -!> @ref RM_GetConcentrations, -!> @ref RM_SetDensity, -!> @ref RM_SetPorosity, -!> @ref RM_SetRepresentativeVolume, -!> @ref RM_SetSaturation. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> status = RM_UseSolutionDensityVolume(id, 0)
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root, workers must be in the loop of @ref RM_MpiWorker. - -INTEGER FUNCTION RM_UseSolutionDensityVolume(id, tf) + END FUNCTION RM_StateDelete + !> Determines the volume and density to use when converting from the reaction-module concentrations + !> to transport concentrations (@ref RM_GetConcentrations). + !> Two options are available to convert concentration units: + !> (1) the density and solution volume calculated by PHREEQC are used, or + !> (2) the specified density (@ref RM_SetDensity) + !> and solution volume are defined by the product of + !> saturation (@ref RM_SetSaturation), porosity (@ref RM_SetPorosity), + !> and representative volume (@ref RM_SetRepresentativeVolume). + !> Transport models that consider density-dependent flow will probably use the + !> PHREEQC-calculated density and solution volume (default), + !> whereas transport models that assume constant-density flow will probably use + !> specified values of density and solution volume. + !> Only the following databases distributed with PhreeqcRM have molar volume information + !> needed to accurately calculate density and solution volume: phreeqc.dat, Amm.dat, and pitzer.dat. + !> Density is only used when converting to transport units of mass fraction. + !> + !> @param id The instance @a id returned from @ref RM_Create. + !> @param tf @a True indicates that the solution density and volume as + !> calculated by PHREEQC will be used to calculate concentrations. + !> @a False indicates that the solution density set by @ref RM_SetDensity and the volume determined by the + !> product of @ref RM_SetSaturation, @ref RM_SetPorosity, and @ref RM_SetRepresentativeVolume, + !> will be used to calculate concentrations retrieved by @ref RM_GetConcentrations. + !> @see + !> @ref RM_GetConcentrations, + !> @ref RM_SetDensity, + !> @ref RM_SetPorosity, + !> @ref RM_SetRepresentativeVolume, + !> @ref RM_SetSaturation. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> status = RM_UseSolutionDensityVolume(id, 0)
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root, workers must be in the loop of @ref RM_MpiWorker. + + INTEGER FUNCTION RM_UseSolutionDensityVolume(id, tf) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_UseSolutionDensityVolume(id, tf) & - BIND(C, NAME='RMF_UseSolutionDensityVolume') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - INTEGER(KIND=C_INT), INTENT(in) :: tf - END FUNCTION RMF_UseSolutionDensityVolume + INTEGER(KIND=C_INT) FUNCTION RMF_UseSolutionDensityVolume(id, tf) & + BIND(C, NAME='RMF_UseSolutionDensityVolume') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + INTEGER(KIND=C_INT), INTENT(in) :: tf + END FUNCTION RMF_UseSolutionDensityVolume END INTERFACE INTEGER, INTENT(in) :: id INTEGER, INTENT(in) :: tf RM_UseSolutionDensityVolume = RMF_UseSolutionDensityVolume(id, tf) -END FUNCTION RM_UseSolutionDensityVolume - -!> Print a warning message to the screen and the log file. -!> @param id The instance @a id returned from @ref RM_Create. -!> @param warn_str String to be printed. -!> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). -!> @see -!> @ref RM_ErrorMessage, -!> @ref RM_LogMessage, -!> @ref RM_OpenFiles, -!> @ref RM_OutputMessage, -!> @ref RM_ScreenMessage. -!> @par Fortran Example: -!> @htmlonly -!> -!>
-!> status = RM_WarningMessage(id, "Parameter is out of range, using default")
-!> 
-!>
-!> @endhtmlonly -!> @par MPI: -!> Called by root and (or) workers; only root writes to the log file. - -INTEGER FUNCTION RM_WarningMessage(id, warn_str) + END FUNCTION RM_UseSolutionDensityVolume + + !> Print a warning message to the screen and the log file. + !> @param id The instance @a id returned from @ref RM_Create. + !> @param warn_str String to be printed. + !> @retval IRM_RESULT 0 is success, negative is failure (See @ref RM_DecodeError). + !> @see + !> @ref RM_ErrorMessage, + !> @ref RM_LogMessage, + !> @ref RM_OpenFiles, + !> @ref RM_OutputMessage, + !> @ref RM_ScreenMessage. + !> @par Fortran Example: + !> @htmlonly + !> + !>
+    !> status = RM_WarningMessage(id, "Parameter is out of range, using default")
+    !> 
+ !>
+ !> @endhtmlonly + !> @par MPI: + !> Called by root and (or) workers; only root writes to the log file. + + INTEGER FUNCTION RM_WarningMessage(id, warn_str) USE ISO_C_BINDING IMPLICIT NONE INTERFACE - INTEGER(KIND=C_INT) FUNCTION RMF_WarningMessage(id, warn_str) & - BIND(C, NAME='RMF_WarningMessage') - USE ISO_C_BINDING - IMPLICIT NONE - INTEGER(KIND=C_INT), INTENT(in) :: id - CHARACTER(KIND=C_CHAR), INTENT(in) :: warn_str(*) - END FUNCTION RMF_WarningMessage + INTEGER(KIND=C_INT) FUNCTION RMF_WarningMessage(id, warn_str) & + BIND(C, NAME='RMF_WarningMessage') + USE ISO_C_BINDING + IMPLICIT NONE + INTEGER(KIND=C_INT), INTENT(in) :: id + CHARACTER(KIND=C_CHAR), INTENT(in) :: warn_str(*) + END FUNCTION RMF_WarningMessage END INTERFACE INTEGER, INTENT(in) :: id CHARACTER(len=*), INTENT(in) :: warn_str RM_WarningMessage = RMF_WarningMessage(id, trim(warn_str)//C_NULL_CHAR) -END FUNCTION RM_WarningMessage + END FUNCTION RM_WarningMessage -INTEGER FUNCTION Chk_Double1D(id, t, n1, var, func) + INTEGER FUNCTION Chk_Double1D(id, t, n1, var, func) IMPLICIT NONE INTEGER, INTENT(in) :: id - DOUBLE PRECISION, INTENT(in), DIMENSION(:) :: t + real(kind=8), INTENT(in), DIMENSION(:) :: t INTEGER, INTENT(in) :: n1 CHARACTER(len=*), INTENT(in) :: var, func CHARACTER(len=200) :: error_string @@ -6727,15 +7073,15 @@ INTEGER FUNCTION Chk_Double1D(id, t, n1, var, func) if (t1 .lt. n1) then errors = errors + 1 write(error_string, '(A,A,A,I8,A,A)') "Dimension of ", var, " is less than ", n1, " in ", func - status = RM_ErrorMessage(id, trim(error_string)) - endif + status = RM_ErrorMessage(id, trim(error_string)) + endif Chk_Double1D = errors -END FUNCTION Chk_Double1D + END FUNCTION Chk_Double1D -INTEGER FUNCTION Chk_Double2D(id, t, n1, n2, var, func) + INTEGER FUNCTION Chk_Double2D(id, t, n1, n2, var, func) IMPLICIT NONE INTEGER, INTENT(in) :: id - DOUBLE PRECISION, INTENT(in), DIMENSION(:,:) :: t + real(kind=8), INTENT(in), DIMENSION(:,:) :: t INTEGER, INTENT(in) :: n1, n2 CHARACTER(len=*), INTENT(in) :: var, func CHARACTER(len=200) :: error_string @@ -6746,17 +7092,17 @@ INTEGER FUNCTION Chk_Double2D(id, t, n1, n2, var, func) if (t2 .ne. n2) then errors = errors + 1 write(error_string, '(A,A,A,I8,A,A)') "Second dimension of ", var, " is not equal to ", n2, " in ", func - status = RM_ErrorMessage(id, trim(error_string)) + status = RM_ErrorMessage(id, trim(error_string)) endif if (t1 .lt. n1) then errors = errors + 1 write(error_string, '(A,A,A,I8,A,A)') "First dimension of ", var, " is less than ", n1, " in ", func - status = RM_ErrorMessage(id, trim(error_string)) - endif + status = RM_ErrorMessage(id, trim(error_string)) + endif Chk_Double2D = errors -END FUNCTION Chk_Double2D + END FUNCTION Chk_Double2D -INTEGER FUNCTION Chk_Integer1D(id, t, n1, var, func) + INTEGER FUNCTION Chk_Integer1D(id, t, n1, var, func) IMPLICIT NONE INTEGER RMF_ErrorMessage INTEGER, INTENT(in) :: id @@ -6770,12 +7116,12 @@ INTEGER FUNCTION Chk_Integer1D(id, t, n1, var, func) if (t1 .lt. n1) then errors = errors + 1 write(error_string, '(A,A,A,I8,A,A)') "Dimension of ", var, " is less than ", n1, " in ", func - status = RM_ErrorMessage(id, trim(error_string)) - endif + status = RM_ErrorMessage(id, trim(error_string)) + endif Chk_Integer1D = errors -END FUNCTION Chk_Integer1D + END FUNCTION Chk_Integer1D -INTEGER FUNCTION Chk_Integer2D(id, t, n1, n2, var, func) + INTEGER FUNCTION Chk_Integer2D(id, t, n1, n2, var, func) IMPLICIT NONE INTEGER, INTENT(in) :: id INTEGER, INTENT(in), DIMENSION(:,:) :: t @@ -6789,16 +7135,15 @@ INTEGER FUNCTION Chk_Integer2D(id, t, n1, n2, var, func) if (t2 .ne. n2) then errors = errors + 1 write(error_string, '(A,A,A,I8,A,A)') "Second dimension of ", var, " is not equal to ", n2, " in ", func - status = RM_ErrorMessage(id, trim(error_string)) + status = RM_ErrorMessage(id, trim(error_string)) endif if (t1 .lt. n1) then errors = errors + 1 write(error_string, '(A,A,A,I8,A,A)') "First dimension of ", var, " is less than ", n1, " in ", func - status = RM_ErrorMessage(id, trim(error_string)) - endif + status = RM_ErrorMessage(id, trim(error_string)) + endif Chk_Integer2D = errors -END FUNCTION Chk_Integer2D + END FUNCTION Chk_Integer2D -END MODULE PhreeqcRM + END MODULE PhreeqcRM - diff --git a/src/RM_interface_C.h b/src/RM_interface_C.h index 22539403c..2e280e199 100644 --- a/src/RM_interface_C.h +++ b/src/RM_interface_C.h @@ -550,7 +550,8 @@ IRM_DLL_EXPORT int RM_GetCurrentSelectedOutputUserNumber(int id); /** Transfer solution densities from the reaction cells to the array given in the argument list (@a density). -Densities are those calculated by the reaction module. +Densities are those calculated by the reaction module. This method always +returns the calculated densities; @ref RM_SetDensity does not affect the result. Only the following databases distributed with PhreeqcRM have molar volume information needed to accurately calculate density: phreeqc.dat, Amm.dat, and pitzer.dat. @@ -1295,6 +1296,8 @@ IRM_DLL_EXPORT int RM_GetNthSelectedOutputUserNumber(int id, int n); /** Returns a vector of saturations (@a sat) as calculated by the reaction module. +This method always returns solution_volume/(rv * porosity); the method +@ref RM_SetSaturation has no effect on the values returned. Reactions will change the volume of solution in a cell. The transport code must decide whether to ignore or account for this change in solution volume due to reactions. Following reactions, the cell saturation is calculated as solution volume (@ref RM_GetSolutionVolume) diff --git a/src/RM_interface_F.cpp b/src/RM_interface_F.cpp index a84b0cc1d..b6877b1bb 100644 --- a/src/RM_interface_F.cpp +++ b/src/RM_interface_F.cpp @@ -2,11 +2,15 @@ #include "mpi.h" #endif #include "BMI_Var.h" +#include "BMIPhreeqcRM.h" #include "PhreeqcRM.h" #include "RM_interface_F.h" #include "IPhreeqcPhastLib.h" #include "Phreeqc.h" #include "PHRQ_io.h" +#ifdef USE_YAML +#include "YAMLPhreeqcRM.h" +#endif #include #include @@ -840,6 +844,7 @@ RMF_GetGfw(int *id, double * gfw) } return IRM_BADINSTANCE; } + /* ---------------------------------------------------------------------- */ int RMF_GetGridCellCount(int * id) @@ -853,6 +858,17 @@ RMF_GetGridCellCount(int * id) } return IRM_BADINSTANCE; } +#ifdef USE_YAML +/* ---------------------------------------------------------------------- */ +int +RMF_GetGridCellCountYAML(const char* config_file) +/* ---------------------------------------------------------------------- */ +{ + // Returns the number of grid cells extracted from YAML file + + return PhreeqcRM::GetGridCellCountYAML(config_file); +} +#endif /* ---------------------------------------------------------------------- */ int RMF_GetIPhreeqcId(int * id, int * i) @@ -919,7 +935,59 @@ RMF_GetNthSelectedOutputUserNumber(int * id, int * i) PhreeqcRM * Reaction_module_ptr = PhreeqcRM::GetInstance(*id); if (Reaction_module_ptr) { - return Reaction_module_ptr->GetNthSelectedOutputUserNumber(*i - 1); + return Reaction_module_ptr->GetNthSelectedOutputUserNumber(*i); + } + return IRM_BADINSTANCE; +} +/* ---------------------------------------------------------------------- */ +IRM_RESULT +RMF_GetPorosity(int* id, double* porosity) +/* ---------------------------------------------------------------------- */ +{ + // Retrieves porosity for all grid nodes in sat + // size of sat must be the number of grid nodes + PhreeqcRM* Reaction_module_ptr = PhreeqcRM::GetInstance(*id); + if (Reaction_module_ptr) + { + IRM_RESULT return_value = IRM_OK; + std::vector porosity_vector; + porosity_vector = Reaction_module_ptr->GetPorosity(); + if ((int)porosity_vector.size() == Reaction_module_ptr->GetGridCellCount()) + { + memcpy(porosity, &porosity_vector.front(), (size_t)(Reaction_module_ptr->GetGridCellCount() * sizeof(double))); + } + else + { + porosity_vector.resize(Reaction_module_ptr->GetGridCellCount(), INACTIVE_CELL_VALUE); + return_value = IRM_FAIL; + } + return return_value; + } + return IRM_BADINSTANCE; +} +/* ---------------------------------------------------------------------- */ +IRM_RESULT +RMF_GetPressure(int* id, double* pressure) +/* ---------------------------------------------------------------------- */ +{ + // Retrieves pressure for all grid nodes in sat + // size of sat must be the number of grid nodes + PhreeqcRM* Reaction_module_ptr = PhreeqcRM::GetInstance(*id); + if (Reaction_module_ptr) + { + IRM_RESULT return_value = IRM_OK; + std::vector pressure_vector; + pressure_vector = Reaction_module_ptr->GetPressure(); + if ((int)pressure_vector.size() == Reaction_module_ptr->GetGridCellCount()) + { + memcpy(pressure, &pressure_vector.front(), (size_t)(Reaction_module_ptr->GetGridCellCount() * sizeof(double))); + } + else + { + pressure_vector.resize(Reaction_module_ptr->GetGridCellCount(), INACTIVE_CELL_VALUE); + return_value = IRM_FAIL; + } + return return_value; } return IRM_BADINSTANCE; } @@ -1209,6 +1277,32 @@ RMF_GetStartCell(int *id, int *sc) return IRM_BADINSTANCE; } /* ---------------------------------------------------------------------- */ +IRM_RESULT +RMF_GetTemperature(int* id, double* temperature) +/* ---------------------------------------------------------------------- */ +{ + // Retrieves porosity for all grid nodes in sat + // size of sat must be the number of grid nodes + PhreeqcRM* Reaction_module_ptr = PhreeqcRM::GetInstance(*id); + if (Reaction_module_ptr) + { + IRM_RESULT return_value = IRM_OK; + std::vector temperature_vector; + temperature_vector = Reaction_module_ptr->GetTemperature(); + if ((int)temperature_vector.size() == Reaction_module_ptr->GetGridCellCount()) + { + memcpy(temperature, &temperature_vector.front(), (size_t)(Reaction_module_ptr->GetGridCellCount() * sizeof(double))); + } + else + { + temperature_vector.resize(Reaction_module_ptr->GetGridCellCount(), INACTIVE_CELL_VALUE); + return_value = IRM_FAIL; + } + return return_value; + } + return IRM_BADINSTANCE; +} +/* ---------------------------------------------------------------------- */ int RMF_GetThreadCount(int * id) /* ---------------------------------------------------------------------- */ diff --git a/src/RM_interface_F.h b/src/RM_interface_F.h index 7dd297b91..c0092eff7 100644 --- a/src/RM_interface_F.h +++ b/src/RM_interface_F.h @@ -13,7 +13,6 @@ #if defined(__cplusplus) extern "C" { #endif - IRM_DLL_EXPORT IRM_RESULT RMF_Abort(int *id, int *result, const char * err_str); IRM_DLL_EXPORT IRM_RESULT RMF_CloseFiles(int *id); IRM_DLL_EXPORT int RMF_Concentrations2Utility(int *id, double *c, int *n, double *tc, double *p_atm); @@ -29,8 +28,6 @@ IRM_DLL_EXPORT int RMF_GetChemistryCellCount(int *id); IRM_DLL_EXPORT IRM_RESULT RMF_GetComponent(int * id, int * num, char *chem_name, int *l1); IRM_DLL_EXPORT int RMF_GetComponentCount(int * id); IRM_DLL_EXPORT int RMF_GetCurrentSelectedOutputUserNumber(int* id); - - IRM_DLL_EXPORT int RMF_GetExchangeSpeciesCount(int * id); IRM_DLL_EXPORT IRM_RESULT RMF_GetExchangeSpeciesName(int * id, int * num, char *name, int *l1); IRM_DLL_EXPORT IRM_RESULT RMF_GetExchangeName(int * id, int * num, char *name, int *l1); @@ -50,8 +47,6 @@ IRM_DLL_EXPORT IRM_RESULT RMF_GetSolidSolutionName(int * id, int * num, char *na IRM_DLL_EXPORT int RMF_GetSICount(int * id); IRM_DLL_EXPORT IRM_RESULT RMF_GetSIName(int * id, int * num, char *name, int *l1); - - IRM_DLL_EXPORT IRM_RESULT RMF_GetConcentrations(int *id, double *c); IRM_DLL_EXPORT IRM_RESULT RMF_GetDensity(int *id, double *density); IRM_DLL_EXPORT IRM_RESULT RMF_GetEndCell(int *id, int *ec); @@ -63,11 +58,16 @@ IRM_DLL_EXPORT IRM_RESULT RMF_GetGasCompPressures(int* id, double* p); IRM_DLL_EXPORT IRM_RESULT RMF_GetGasCompPhi(int* id, double* phi); IRM_DLL_EXPORT IRM_RESULT RMF_GetGasPhaseVolume(int* id, double* v); IRM_DLL_EXPORT IRM_RESULT RMF_GetGfw(int *id, double * gfw); +#ifdef USE_YAML +IRM_DLL_EXPORT int RMF_GetGridCellCountYAML(const char* config_file); +#endif IRM_DLL_EXPORT int RMF_GetGridCellCount(int *id); IRM_DLL_EXPORT int RMF_GetIPhreeqcId(int *id, int *i); IRM_DLL_EXPORT int RMF_GetMpiMyself(int *id); IRM_DLL_EXPORT int RMF_GetMpiTasks(int *id); IRM_DLL_EXPORT int RMF_GetNthSelectedOutputUserNumber(int *id, int *i); +IRM_DLL_EXPORT IRM_RESULT RMF_GetPorosity(int* id, double* porosity); +IRM_DLL_EXPORT IRM_RESULT RMF_GetPressure(int* id, double* pressure); IRM_DLL_EXPORT IRM_RESULT RMF_GetSaturation(int *id, double *sat); IRM_DLL_EXPORT IRM_RESULT RMF_GetSelectedOutput(int *id, double *so); IRM_DLL_EXPORT int RMF_GetSelectedOutputColumnCount(int *id); @@ -84,11 +84,14 @@ IRM_DLL_EXPORT IRM_RESULT RMF_GetSpeciesName(int *id, int *i, char * name, int * IRM_DLL_EXPORT int RMF_GetSpeciesSaveOn(int *id); IRM_DLL_EXPORT IRM_RESULT RMF_GetSpeciesZ(int *id, double *z); IRM_DLL_EXPORT IRM_RESULT RMF_GetStartCell(int *id, int *sc); +IRM_DLL_EXPORT IRM_RESULT RMF_GetTemperature(int* id, double* temperature); IRM_DLL_EXPORT int RMF_GetThreadCount(int *id); IRM_DLL_EXPORT double RMF_GetTime(int *id); IRM_DLL_EXPORT double RMF_GetTimeConversion(int *id); IRM_DLL_EXPORT double RMF_GetTimeStep(int *id); +#ifdef USE_YAML IRM_DLL_EXPORT IRM_RESULT RMF_InitializeYAML(int* id, const char* yaml_name); +#endif IRM_DLL_EXPORT IRM_RESULT RMF_InitialPhreeqc2Concentrations( int *id, double *c, diff --git a/src/VarManager.cpp b/src/VarManager.cpp new file mode 100644 index 000000000..4b5e7b0a4 --- /dev/null +++ b/src/VarManager.cpp @@ -0,0 +1,1409 @@ +#include "VarManager.h" +#include "RMVARS.h" +#include +#include +VarManager::VarManager(PhreeqcRM* rm_ptr_in) +{ + this->VariantMap[RMVARS::ComponentCount] = + BMIVariant(&VarManager::ComponentCount_Var, "ComponentCount"); + this->VariantMap[RMVARS::Components] = + BMIVariant(&VarManager::Components_Var, "Components"); + this->VariantMap[RMVARS::Concentrations] = + BMIVariant(&VarManager::Concentrations_Var, "Concentrations"); + this->VariantMap[RMVARS::Density] = + BMIVariant(&VarManager::Density_Var, "Density"); + this->VariantMap[RMVARS::ErrorString] = + BMIVariant(&VarManager::ErrorString_Var, "ErrorString"); + this->VariantMap[RMVARS::FilePrefix] = + BMIVariant(&VarManager::FilePrefix_Var, "FilePrefix"); + this->VariantMap[RMVARS::Gfw] = + BMIVariant(&VarManager::Gfw_Var, "Gfw"); + this->VariantMap[RMVARS::GridCellCount] = + BMIVariant(&VarManager::GridCellCount_Var, "GridCellCount"); + //this->VariantMap[RMVARS::InputVarNames] = + // BMIVariant(&VarManager::InputVarNames_Var, "InputVarNames"); + this->VariantMap[RMVARS::NthSelectedOutput] = + BMIVariant(&VarManager::NthSelectedOutput_Var, "NthSelectedOutput"); + //this->VariantMap[RMVARS::OutputVarNames] = + // BMIVariant(&VarManager::OutputVarNames_Var, "OutputVarNames"); + this->VariantMap[RMVARS::Saturation] = + BMIVariant(&VarManager::Saturation_Var, "Saturation"); + this->VariantMap[RMVARS::SelectedOutput] = + BMIVariant(&VarManager::SelectedOutput_Var, "SelectedOutput"); + this->VariantMap[RMVARS::SelectedOutputColumnCount] = + BMIVariant(&VarManager::SelectedOutputColumnCount_Var, "SelectedOutputColumnCount"); + this->VariantMap[RMVARS::SelectedOutputCount] = + BMIVariant(&VarManager::SelectedOutputCount_Var, "SelectedOutputCount"); + this->VariantMap[RMVARS::SelectedOutputHeadings] = + BMIVariant(&VarManager::SelectedOutputHeadings_Var, "SelectedOutputHeadings"); + this->VariantMap[RMVARS::SelectedOutputRowCount] = + BMIVariant(&VarManager::SelectedOutputRowCount_Var, "SelectedOutputRowCount"); + this->VariantMap[RMVARS::SolutionVolume] = + BMIVariant(&VarManager::SolutionVolume_Var, "SolutionVolume"); + this->VariantMap[RMVARS::Time] = + BMIVariant(&VarManager::Time_Var, "Time"); + this->VariantMap[RMVARS::TimeStep] = + BMIVariant(&VarManager::TimeStep_Var, "TimeStep"); + this->VariantMap[RMVARS::CurrentSelectedOutputUserNumber] = + BMIVariant(&VarManager::CurrentSelectedOutputUserNumber_Var, "CurrentSelectedOutputUserNumber"); + this->VariantMap[RMVARS::Porosity] = + BMIVariant(&VarManager::Porosity_Var, "Porosity"); + this->VariantMap[RMVARS::Pressure] = + BMIVariant(&VarManager::Pressure_Var, "Pressure"); + this->VariantMap[RMVARS::SelectedOutputOn] = + BMIVariant(&VarManager::SelectedOutputOn_Var, "SelectedOutputOn"); + this->VariantMap[RMVARS::Temperature] = + BMIVariant(&VarManager::Temperature_Var, "Temperature"); + ///!!!VarFunction x = &VarManager::ComponentCount_var; + ///!!! (this->*x)(rm_ptr); // Remember this !!!/// + //auto it = VariantMap.begin(); + //VarFunction x = it->second.GetFn(); + //(this->*x)(); + rm_ptr = rm_ptr_in; + this->task = VarManager::VAR_TASKS::no_op; + this->CurrentVar = RMVARS::NotFound; + //auto it = VarVariantMap.begin(); + //VarFunction x = it->second.GetFn(rm_ptr); + //x(rm_ptr); + // Make EnumMap + for (auto it = VariantMap.begin(); it != VariantMap.end(); it++) + { + std::string name_lc = it->second.GetName(); + std::transform(name_lc.begin(), name_lc.end(), name_lc.begin(), tolower); + EnumMap[name_lc] = it->first; + } +} +void VarManager::RM2BMIUpdate(RMVARS v_enum) +{ + if (this->PointerSet.size() == 0) return; + //RMVARS v_enum = this->GetEnum(name); + if (this->GetCurrentVar() == v_enum) return; + auto it = this->VariantMap.find(v_enum); + if (it != VariantMap.end()) + { + this->task = VarManager::VAR_TASKS::RMUpdate; + VarFunction f = it->second.GetFn(); + (this->*f)(); + } + return; +} +RMVARS VarManager::GetEnum(const std::string name) +{ + std::string name_lc = name; + std::transform(name_lc.begin(), name_lc.end(), name_lc.begin(), tolower); + auto m_it = EnumMap.find(name_lc); + if (m_it != EnumMap.end()) + { + return m_it->second; + } + return RMVARS::NotFound; +} +VarManager::VarFunction VarManager::GetFn(RMVARS v_enum) +{ + auto it = this->GetVariantMap().find(v_enum); + if (it != this->GetVariantMap().end()) + { + //VarManager::VarFunction f = it->second.GetFn(); + //VarFunction*(f)(); + return it->second.GetFn(); + } + return NULL; +} +//VarManager::VarFunction VarManager::GetFn(RMVARS v_enum) +//{ +// //this->var_man->VarExchange.Clear(); +// //std::string name_lc = name; +// //std::transform(name_lc.begin(), name_lc.end(), name_lc.begin(), tolower); +// auto it = VariantMap.find(v_enum); +// if (it == VariantMap.end()) +// { +// std::ostringstream oss; +// oss << "Unknown variable enum: " << (int) v_enum; +// rm_ptr->ErrorMessage(oss.str()); +// return NULL; +// } +// +// //VarManager::VAR_TASKS task_save = this->task; +// //this->task = VarManager::VAR_TASKS::no_op; +// BMIVariant & bv = it->second; +// ////this->task = task_save; +// //if (this->VarExchange.GetNotImplementedRef()) +// //{ +// // std::ostringstream oss; +// // oss << "Not implemented for variable: " << bv.GetName(); +// // this->ErrorMessage(oss.str()); +// // return NULL; +// //} +// if (this->task == VarManager::VAR_TASKS::GetVar) +// { +// if (!this->VarExchange.GetHasGetter()) +// { +// std::ostringstream oss; +// oss << "Cannot get variable: " << bv.GetName(); +// rm_ptr->ErrorMessage(oss.str()); +// return NULL; +// } +// } +// if (this->task == VarManager::VAR_TASKS::SetVar) +// { +// if (!this->VarExchange.GetHasSetter()) +// { +// std::ostringstream oss; +// oss << "Cannot set variable: " << bv.GetName(); +// rm_ptr->ErrorMessage(oss.str()); +// return NULL; +// } +// } +// if (this->task == VarManager::VAR_TASKS::GetPtr) +// { +// if (!this->VarExchange.GetHasPtr()) +// { +// std::ostringstream oss; +// oss << "Cannot get a pointer to variable: " << bv.GetName(); +// rm_ptr->ErrorMessage(oss.str()); +// return NULL; +// } +// } +// return it->second; +//} + +//// Start_var +void VarManager::ComponentCount_Var() +{ + RMVARS VARS_myself = RMVARS::ComponentCount; + this->SetCurrentVar(VARS_myself); + BMIVariant& bv = this->VariantMap[VARS_myself]; + if (!bv.GetInitialized()) + { + int Itemsize = (int)sizeof(int); + int Nbytes = (int)sizeof(int); + //std::string units, set, get, ptr, Nbytes, Itemsize + bv.SetBasic("count", false, true, true, Nbytes, Itemsize); + bv.SetTypes("int", "integer", "int"); + bv.SetIVar(rm_ptr->GetComponentCount()); + bv.SetInitialized(true); + } + switch (this->task) + { + case VarManager::VAR_TASKS::GetPtr: + { + int v = rm_ptr->GetComponentCount(); + bv.SetIVar(v); + bv.SetVoidPtr((void*)(bv.GetIVarPtr())); + this->PointerSet.insert(VARS_myself); + break; + } + case VarManager::VAR_TASKS::GetVar: + { + int v = rm_ptr->GetComponentCount(); + bv.SetIVar(v); + break; + } + case VarManager::VAR_TASKS::SetVar: + assert(false); + break; + case VarManager::VAR_TASKS::RMUpdate: + { + assert(false); + break; + } + case VarManager::VAR_TASKS::Update: + { + assert(false); + break; + } + case VarManager::VAR_TASKS::Info: + case VarManager::VAR_TASKS::no_op: + break; + } + this->VarExchange.CopyScalars(bv); + this->SetCurrentVar(RMVARS::NotFound); +} +void VarManager::Components_Var() +{ + RMVARS VARS_myself = RMVARS::Components; + this->SetCurrentVar(VARS_myself); + BMIVariant& bv = this->VariantMap[VARS_myself]; + if (!bv.GetInitialized()) + { + std::vector comps = rm_ptr->GetComponents(); + size_t size = 0; + for (size_t i = 0; i < comps.size(); i++) + { + if (comps[i].size() > size) size = comps[i].size(); + } + int Itemsize = (int)size; + int Nbytes = (int)(size * comps.size()); + //name, std::string units, set, get, ptr, Nbytes, Itemsize + bv.SetBasic("names", false, true, false, Nbytes, Itemsize); + bv.SetTypes("std::vector", "character(len=:),allocatable,dimension(:)", ""); + bv.SetStringVector(rm_ptr->GetComponents()); + bv.SetInitialized(true); + } + switch (this->task) + { + case VarManager::VAR_TASKS::GetPtr: + { + std::vector CharVector; + std::vector& Components = bv.GetStringVectorRef(); + for (size_t i = 0; i < Components.size(); i++) + { + CharVector.push_back(Components[i].c_str()); + } + bv.SetCharVector(CharVector); + break; + } + case VarManager::VAR_TASKS::GetVar: + { + const std::vector& v = rm_ptr->GetComponents(); + this->VarExchange.SetStringVector(v); + break; + } + case VarManager::VAR_TASKS::SetVar: + assert(false); + break; + case VarManager::VAR_TASKS::RMUpdate: + { + assert(false); + break; + } + case VarManager::VAR_TASKS::Update: + { + assert(false); + break; + } + case VarManager::VAR_TASKS::Info: + case VarManager::VAR_TASKS::no_op: + break; + } + this->VarExchange.CopyScalars(bv); + this->SetCurrentVar(RMVARS::NotFound); +} +void VarManager::Concentrations_Var() +{ + RMVARS VARS_myself = RMVARS::Concentrations; + this->SetCurrentVar(VARS_myself); + BMIVariant& bv = this->VariantMap[VARS_myself]; + if (!bv.GetInitialized()) + { + int Itemsize = (int)sizeof(double); + int Nbytes = (int)sizeof(double) * + rm_ptr->GetGridCellCount() * rm_ptr->GetComponentCount(); + //name, std::string units, set, get, ptr, Nbytes, Itemsize + int option = rm_ptr->GetUnitsSolution(); + std::string units; + switch (option) + { + case 1: + units = "mg/L"; + break; + case 2: + units = "mol/L"; + break; + case 3: + units = "kg/kgs"; + break; + } + bv.SetBasic(units, true, true, true, Nbytes, Itemsize); + bv.SetTypes("double", "real(kind=8)", ""); + rm_ptr->GetConcentrations(bv.GetDoubleVectorRef()); + rm_ptr->GetConcentrations(this->VarExchange.GetDoubleVectorRef()); + bv.SetInitialized(true); + } + switch (this->task) + { + case VarManager::VAR_TASKS::GetPtr: + { + rm_ptr->GetConcentrations(this->VarExchange.GetDoubleVectorRef()); + bv.SetDoubleVector(this->VarExchange.GetDoubleVectorRef()); + bv.SetVoidPtr((void*)(bv.GetDoubleVectorPtr())); + this->PointerSet.insert(VARS_myself); + this->UpdateSet.insert(VARS_myself); + break; + } + case VarManager::VAR_TASKS::GetVar: + case VarManager::VAR_TASKS::Update: + case VarManager::VAR_TASKS::RMUpdate: + { + rm_ptr->GetConcentrations(this->VarExchange.GetDoubleVectorRef()); + bv.SetDoubleVector(this->VarExchange.GetDoubleVectorRef()); + break; + } + case VarManager::VAR_TASKS::SetVar: + rm_ptr->SetConcentrations(this->VarExchange.GetDoubleVectorRef()); + bv.SetDoubleVector(this->VarExchange.GetDoubleVectorRef()); + break; + case VarManager::VAR_TASKS::no_op: + case VarManager::VAR_TASKS::Info: + break; + } + this->VarExchange.CopyScalars(bv); + this->SetCurrentVar(RMVARS::NotFound); +} +void VarManager::Density_Var() +{ + this->SetCurrentVar(RMVARS::Density); + BMIVariant& bv = this->VariantMap[RMVARS::Density]; + if (!bv.GetInitialized()) + { + int Itemsize = sizeof(double); + int Nbytes = Itemsize * rm_ptr->GetGridCellCount(); + //name, std::string units, set, get, ptr, Nbytes, Itemsize + bv.SetBasic("kg L-1", true, true, true, Nbytes, Itemsize); + bv.SetTypes("double", "real(kind=8)", ""); + rm_ptr->GetDensity(this->VarExchange.GetDoubleVectorRef()); + rm_ptr->GetDensity(bv.GetDoubleVectorRef()); + bv.SetInitialized(true); + } + switch (this->task) + { + case VarManager::VAR_TASKS::GetPtr: + { + rm_ptr->GetDensity(this->VarExchange.GetDoubleVectorRef()); + bv.SetDoubleVector(this->VarExchange.GetDoubleVectorRef()); + bv.SetVoidPtr((void*)(bv.GetDoubleVectorPtr())); + this->PointerSet.insert(RMVARS::Density); + this->UpdateSet.insert(RMVARS::Density); + break; + } + case VarManager::VAR_TASKS::GetVar: + case VarManager::VAR_TASKS::Update: + case VarManager::VAR_TASKS::RMUpdate: + { + rm_ptr->GetDensity(this->VarExchange.GetDoubleVectorRef()); + bv.SetDoubleVector(this->VarExchange.GetDoubleVectorRef()); + break; + } + case VarManager::VAR_TASKS::SetVar: + rm_ptr->SetDensity(this->VarExchange.GetDoubleVectorRef()); + // don't update density vector, only get solution densities + //bv.SetDoubleVector(this->VarExchange.GetDoubleVectorRef()); + break; + case VarManager::VAR_TASKS::no_op: + case VarManager::VAR_TASKS::Info: + break; + } + this->VarExchange.CopyScalars(bv); + this->SetCurrentVar(RMVARS::NotFound); +} +void VarManager::ErrorString_Var() +{ + RMVARS VARS_myself = RMVARS::ErrorString; + this->SetCurrentVar(VARS_myself); + BMIVariant& bv = this->VariantMap[VARS_myself]; + if (!bv.GetInitialized()) + { + int Itemsize = (int)rm_ptr->GetErrorString().size(); + int Nbytes = Itemsize; + //name, std::string units, set, get, ptr, Nbytes, Itemsize + bv.SetBasic("error", false, true, false, Nbytes, Itemsize); + bv.SetTypes("std::string", "character", ""); + this->VarExchange.GetStringRef() = rm_ptr->GetErrorString(); + bv.GetStringRef() = rm_ptr->GetErrorString(); + bv.SetInitialized(true); + } + switch (this->task) + { + case VarManager::VAR_TASKS::GetPtr: + { + assert(false); + break; + } + case VarManager::VAR_TASKS::GetVar: + case VarManager::VAR_TASKS::Update: + case VarManager::VAR_TASKS::RMUpdate: + { + this->VarExchange.GetStringRef() = rm_ptr->GetErrorString(); + bv.GetStringRef() = rm_ptr->GetErrorString(); + bv.SetItemsize(bv.GetStringRef().size()); + break; + } + case VarManager::VAR_TASKS::SetVar: + assert(false); + break; + case VarManager::VAR_TASKS::no_op: + case VarManager::VAR_TASKS::Info: + break; + } + this->VarExchange.CopyScalars(bv); + this->SetCurrentVar(RMVARS::NotFound); +} +void VarManager::FilePrefix_Var() +{ + RMVARS VARS_myself = RMVARS::FilePrefix; + this->SetCurrentVar(VARS_myself); + BMIVariant& bv = this->VariantMap[VARS_myself]; + //if (!bv.GetInitialized()) + //{ + int Itemsize = (int)rm_ptr->GetFilePrefix().size(); + int Nbytes = Itemsize; + //name, std::string units, set, get, ptr, Nbytes, Itemsize + bv.SetBasic("prefix", true, true, false, Nbytes, Itemsize); + bv.SetTypes("std::string", "character", ""); + //this->VarExchange.GetStringRef() = rm_ptr->GetFilePrefix(); + bv.GetStringRef() = rm_ptr->GetFilePrefix(); + //bv.SetInitialized(true); + //} + switch (this->task) + { + case VarManager::VAR_TASKS::GetPtr: + { + assert(false); + break; + } + case VarManager::VAR_TASKS::GetVar: + case VarManager::VAR_TASKS::Update: + case VarManager::VAR_TASKS::RMUpdate: + { + //int Itemsize = (int)rm_ptr->GetFilePrefix().size(); + //int Nbytes = Itemsize; + ////name, std::string units, set, get, ptr, Nbytes, Itemsize + //bv.SetBasic("prefix", true, true, false, Nbytes, Itemsize); + //bv.SetTypes("std::string", "character", ""); + this->VarExchange.GetStringRef() = rm_ptr->GetFilePrefix(); + bv.GetStringRef() = rm_ptr->GetFilePrefix(); + break; + } + case VarManager::VAR_TASKS::SetVar: + { + int Itemsize = (int)this->VarExchange.GetStringRef().size(); + int Nbytes = Itemsize; + //name, std::string units, set, get, ptr, Nbytes, Itemsize + bv.SetBasic("prefix", true, true, false, Nbytes, Itemsize); + //bv.SetTypes("std::string", "character", ""); + rm_ptr->SetFilePrefix(this->VarExchange.GetStringRef()); + bv.GetStringRef() = this->VarExchange.GetStringRef(); + break; + } + case VarManager::VAR_TASKS::no_op: + case VarManager::VAR_TASKS::Info: + break; + } + this->VarExchange.CopyScalars(bv); + this->SetCurrentVar(RMVARS::NotFound); +} +void VarManager::Gfw_Var() +{ + RMVARS VARS_myself = RMVARS::Gfw; + this->SetCurrentVar(RMVARS::Gfw); + BMIVariant& bv = this->VariantMap[VARS_myself]; + if (!bv.GetInitialized()) + { + int Itemsize = sizeof(double); + int Nbytes = Itemsize * rm_ptr->GetComponentCount(); + //name, std::string units, set, get, ptr, Nbytes, Itemsize + bv.SetBasic("g mol-1", false, true, true, Nbytes, Itemsize); + bv.SetTypes("double", "real(kind=8)", ""); + this->VarExchange.GetDoubleVectorRef() = rm_ptr->GetGfw(); + bv.GetDoubleVectorRef() = rm_ptr->GetGfw(); + bv.SetInitialized(true); + } + switch (this->task) + { + case VarManager::VAR_TASKS::GetPtr: + { + this->VarExchange.GetDoubleVectorRef() = rm_ptr->GetGfw(); + bv.SetDoubleVector(this->VarExchange.GetDoubleVectorRef()); + bv.SetVoidPtr((void*)(bv.GetDoubleVectorPtr())); + this->PointerSet.insert(VARS_myself); + break; + } + case VarManager::VAR_TASKS::GetVar: + case VarManager::VAR_TASKS::Update: + case VarManager::VAR_TASKS::RMUpdate: + { + this->VarExchange.GetDoubleVectorRef() = rm_ptr->GetGfw(); + bv.SetDoubleVector(this->VarExchange.GetDoubleVectorRef()); + break; + } + case VarManager::VAR_TASKS::SetVar: + assert(false); + break; + case VarManager::VAR_TASKS::no_op: + case VarManager::VAR_TASKS::Info: + break; + } + this->VarExchange.CopyScalars(bv); + this->SetCurrentVar(RMVARS::NotFound); +} +void VarManager::GridCellCount_Var() +{ + RMVARS VARS_myself = RMVARS::GridCellCount; + this->SetCurrentVar(VARS_myself); + BMIVariant& bv = this->VariantMap[VARS_myself]; + if (!bv.GetInitialized()) + { + int Itemsize = (int)sizeof(int); + int Nbytes = (int)sizeof(int); + //std::string units, set, get, ptr, Nbytes, Itemsize + bv.SetBasic("count", false, true, true, Nbytes, Itemsize); + bv.SetTypes("int", "integer", "int"); + bv.SetIVar(rm_ptr->GetGridCellCount()); + bv.SetInitialized(true); + } + switch (this->task) + { + case VarManager::VAR_TASKS::GetPtr: + { + int v = rm_ptr->GetGridCellCount(); + bv.SetIVar(v); + bv.SetVoidPtr((void*)(bv.GetIVarPtr())); + this->PointerSet.insert(VARS_myself); + break; + } + case VarManager::VAR_TASKS::GetVar: + { + int v = rm_ptr->GetGridCellCount(); + bv.SetIVar(v); + this->PointerSet.insert(VARS_myself); + break; + } + case VarManager::VAR_TASKS::SetVar: + assert(false); + break; + case VarManager::VAR_TASKS::RMUpdate: + { + assert(false); + break; + } + case VarManager::VAR_TASKS::Update: + { + assert(false); + break; + } + case VarManager::VAR_TASKS::Info: + case VarManager::VAR_TASKS::no_op: + break; + } + this->VarExchange.CopyScalars(bv); + this->SetCurrentVar(RMVARS::NotFound); +} +// +//void VarManager::InputVarNames_Var() // Implement in BRMPhreeqcRM TODO??? +// +void VarManager::NthSelectedOutput_Var() +{ + RMVARS VARS_myself = RMVARS::NthSelectedOutput; + this->SetCurrentVar(VARS_myself); + BMIVariant& bv = this->VariantMap[VARS_myself]; + if (!bv.GetInitialized()) + { + int Itemsize = (int)sizeof(int); + int Nbytes = (int)sizeof(int); + //std::string units, set, get, ptr, Nbytes, Itemsize + bv.SetBasic("id", true, false, false, Nbytes, Itemsize); + bv.SetTypes("int", "integer", "int"); + bv.SetIVar(-1); + bv.SetInitialized(true); + } + switch (this->task) + { + case VarManager::VAR_TASKS::GetPtr: + case VarManager::VAR_TASKS::GetVar: + { + assert(false); + break; + } + case VarManager::VAR_TASKS::SetVar: + { + int v = *this->VarExchange.GetIVarPtr(); + rm_ptr->SetNthSelectedOutput(v); + break; + } + case VarManager::VAR_TASKS::RMUpdate: + case VarManager::VAR_TASKS::Update: + { + assert(false); + break; + } + case VarManager::VAR_TASKS::Info: + case VarManager::VAR_TASKS::no_op: + break; + } + this->VarExchange.CopyScalars(bv); + this->SetCurrentVar(RMVARS::NotFound); +} +// +//void VarManager::OutputVarNames_Var() // Implement in BRMPhreeqcRM TODO??? +// +void VarManager::Saturation_Var() +{ + RMVARS VARS_myself = RMVARS::Saturation; + this->SetCurrentVar(VARS_myself); + BMIVariant& bv = this->VariantMap[VARS_myself]; + if (!bv.GetInitialized()) + { + int Itemsize = sizeof(double); + int Nbytes = Itemsize * rm_ptr->GetGridCellCount(); + //name, std::string units, set, get, ptr, Nbytes, Itemsize + bv.SetBasic("unitless", true, true, true, Nbytes, Itemsize); + bv.SetTypes("double", "real(kind=8)", ""); + rm_ptr->GetSaturation(this->VarExchange.GetDoubleVectorRef()); + rm_ptr->GetSaturation(bv.GetDoubleVectorRef()); + bv.SetInitialized(true); + } + switch (this->task) + { + case VarManager::VAR_TASKS::GetPtr: + { + rm_ptr->GetSaturation(this->VarExchange.GetDoubleVectorRef()); + bv.SetDoubleVector(this->VarExchange.GetDoubleVectorRef()); + bv.SetVoidPtr((void*)(bv.GetDoubleVectorPtr())); + this->PointerSet.insert(VARS_myself); + this->UpdateSet.insert(VARS_myself); + break; + } + case VarManager::VAR_TASKS::GetVar: + case VarManager::VAR_TASKS::Update: + case VarManager::VAR_TASKS::RMUpdate: + { + rm_ptr->GetSaturation(this->VarExchange.GetDoubleVectorRef()); + bv.SetDoubleVector(this->VarExchange.GetDoubleVectorRef()); + break; + } + case VarManager::VAR_TASKS::SetVar: + rm_ptr->SetSaturation(this->VarExchange.GetDoubleVectorRef()); + bv.SetDoubleVector(this->VarExchange.GetDoubleVectorRef()); + break; + case VarManager::VAR_TASKS::no_op: + case VarManager::VAR_TASKS::Info: + break; + } + this->VarExchange.CopyScalars(bv); + this->SetCurrentVar(RMVARS::NotFound); +} +void VarManager::SelectedOutput_Var() +{ + RMVARS VARS_myself = RMVARS::SelectedOutput; + this->SetCurrentVar(VARS_myself); + BMIVariant& bv = this->VariantMap[VARS_myself]; + if (!bv.GetInitialized()) + { + int Itemsize = (int)sizeof(double); + int Nbytes = Itemsize * rm_ptr->GetSelectedOutputRowCount() * + rm_ptr->GetSelectedOutputColumnCount(); + //name, std::string units, set, get, ptr, Nbytes, Itemsize + bv.SetBasic("user specified", false, true, false, Nbytes, Itemsize); + bv.SetTypes("double", "real(kind=8)", ""); + } + switch (this->task) + { + case VarManager::VAR_TASKS::GetPtr: + { + assert(false); + break; + } + case VarManager::VAR_TASKS::GetVar: + { + rm_ptr->GetSelectedOutput(this->VarExchange.GetDoubleVectorRef()); + rm_ptr->GetSelectedOutput(bv.GetDoubleVectorRef()); + break; + } + case VarManager::VAR_TASKS::Update: + case VarManager::VAR_TASKS::RMUpdate: + assert(false); + break; + case VarManager::VAR_TASKS::SetVar: + assert(false); + break; + case VarManager::VAR_TASKS::no_op: + case VarManager::VAR_TASKS::Info: + break; + } + this->VarExchange.CopyScalars(bv); + this->SetCurrentVar(RMVARS::NotFound); +} +void VarManager::SelectedOutputColumnCount_Var() +{ + RMVARS VARS_myself = RMVARS::SelectedOutputColumnCount; + this->SetCurrentVar(VARS_myself); + BMIVariant& bv = this->VariantMap[VARS_myself]; + if (!bv.GetInitialized()) + { + int Itemsize = (int)sizeof(int); + int Nbytes = (int)sizeof(int); + //std::string units, set, get, ptr, Nbytes, Itemsize + bv.SetBasic("count", false, true, false, Nbytes, Itemsize); + bv.SetTypes("int", "integer", "int"); + bv.SetIVar(rm_ptr->GetSelectedOutputColumnCount()); + bv.SetInitialized(true); + } + switch (this->task) + { + case VarManager::VAR_TASKS::GetPtr: + { + assert(false); + break; + } + case VarManager::VAR_TASKS::GetVar: + { + int v = rm_ptr->GetSelectedOutputColumnCount(); + bv.SetIVar(v); + break; + } + case VarManager::VAR_TASKS::SetVar: + assert(false); + break; + case VarManager::VAR_TASKS::RMUpdate: + { + assert(false); + break; + } + case VarManager::VAR_TASKS::Update: + { + assert(false); + break; + } + case VarManager::VAR_TASKS::Info: + case VarManager::VAR_TASKS::no_op: + break; + } + this->VarExchange.CopyScalars(bv); + this->SetCurrentVar(RMVARS::NotFound); +} +void VarManager::SelectedOutputCount_Var() +{ + RMVARS VARS_myself = RMVARS::SelectedOutputCount; + this->SetCurrentVar(VARS_myself); + BMIVariant& bv = this->VariantMap[VARS_myself]; + if (!bv.GetInitialized()) + { + int Itemsize = (int)sizeof(int); + int Nbytes = (int)sizeof(int); + //std::string units, set, get, ptr, Nbytes, Itemsize + bv.SetBasic("count", false, true, false, Nbytes, Itemsize); + bv.SetTypes("int", "integer", "int"); + bv.SetIVar(rm_ptr->GetSelectedOutputCount()); + bv.SetInitialized(true); + } + switch (this->task) + { + case VarManager::VAR_TASKS::GetPtr: + { + assert(false); + break; + } + case VarManager::VAR_TASKS::GetVar: + { + int v = rm_ptr->GetSelectedOutputCount(); + bv.SetIVar(v); + break; + } + case VarManager::VAR_TASKS::SetVar: + assert(false); + break; + case VarManager::VAR_TASKS::RMUpdate: + { + assert(false); + break; + } + case VarManager::VAR_TASKS::Update: + { + assert(false); + break; + } + case VarManager::VAR_TASKS::Info: + case VarManager::VAR_TASKS::no_op: + break; + } + this->VarExchange.CopyScalars(bv); + this->SetCurrentVar(RMVARS::NotFound); +} +void VarManager::SelectedOutputHeadings_Var() +{ + RMVARS VARS_myself = RMVARS::SelectedOutputHeadings; + this->SetCurrentVar(VARS_myself); + BMIVariant& bv = this->VariantMap[VARS_myself]; + if (!bv.GetInitialized()) + { + rm_ptr->GetSelectedOutputHeadings(bv.GetStringVectorRef()); + this->VarExchange.GetStringVectorRef() = bv.GetStringVectorRef(); + std::vector headings = bv.GetStringVectorRef(); + size_t size = 0; + for (size_t i = 0; i < headings.size(); i++) + { + if (headings[i].size() > size) size = headings[i].size(); + } + int Itemsize = (int)size; + int Nbytes = (int)(size * headings.size()); + //name, std::string units, set, get, ptr, Nbytes, Itemsize + bv.SetBasic("names", false, true, false, Nbytes, Itemsize); + bv.SetTypes("std::vector", "character(len=:),allocatable,dimension(:)", ""); + bv.SetInitialized(true); + } + switch (this->task) + { + case VarManager::VAR_TASKS::GetPtr: + { + assert(false); + //std::vector CharVector; + //std::vector& Components = bv.GetStringVectorRef(); + //for (size_t i = 0; i < Components.size(); i++) + //{ + // CharVector.push_back(Components[i].c_str()); + //} + //bv.SetCharVector(CharVector); + //this->PointerSet.insert(VARS_myself); + //this->UpdateSet.insert(VARS_myself); + break; + } + case VarManager::VAR_TASKS::GetVar: + { + rm_ptr->GetSelectedOutputHeadings(bv.GetStringVectorRef()); + this->VarExchange.SetStringVector(bv.GetStringVectorRef()); + std::vector& headings = bv.GetStringVectorRef(); + size_t size = 0; + for (size_t i = 0; i < headings.size(); i++) + { + if (headings[i].size() > size) size = headings[i].size(); + } + bv.SetItemsize(size); + break; + } + case VarManager::VAR_TASKS::SetVar: + assert(false); + break; + case VarManager::VAR_TASKS::RMUpdate: + { + assert(false); + break; + } + case VarManager::VAR_TASKS::Update: + { + assert(false); + break; + } + case VarManager::VAR_TASKS::Info: + case VarManager::VAR_TASKS::no_op: + break; + } + this->VarExchange.CopyScalars(bv); + this->SetCurrentVar(RMVARS::NotFound); +} +void VarManager::SelectedOutputRowCount_Var() +{ + RMVARS VARS_myself = RMVARS::SelectedOutputRowCount; + this->SetCurrentVar(VARS_myself); + BMIVariant& bv = this->VariantMap[VARS_myself]; + if (!bv.GetInitialized()) + { + int Itemsize = (int)sizeof(int); + int Nbytes = (int)sizeof(int); + //std::string units, set, get, ptr, Nbytes, Itemsize + bv.SetBasic("count", false, true, false, Nbytes, Itemsize); + bv.SetTypes("int", "integer", "int"); + bv.SetIVar(rm_ptr->GetSelectedOutputRowCount()); + bv.SetInitialized(true); + } + switch (this->task) + { + case VarManager::VAR_TASKS::GetPtr: + { + assert(false); + break; + } + case VarManager::VAR_TASKS::GetVar: + { + int v = rm_ptr->GetSelectedOutputRowCount(); + bv.SetIVar(v); + break; + } + case VarManager::VAR_TASKS::SetVar: + assert(false); + break; + case VarManager::VAR_TASKS::RMUpdate: + { + assert(false); + break; + } + case VarManager::VAR_TASKS::Update: + { + assert(false); + break; + } + case VarManager::VAR_TASKS::Info: + case VarManager::VAR_TASKS::no_op: + break; + } + this->VarExchange.CopyScalars(bv); + this->SetCurrentVar(RMVARS::NotFound); +} +void VarManager::SolutionVolume_Var() +{ + RMVARS VARS_myself = RMVARS::SolutionVolume; + this->SetCurrentVar(VARS_myself); + BMIVariant& bv = this->VariantMap[VARS_myself]; + if (!bv.GetInitialized()) + { + int Itemsize = sizeof(double); + int Nbytes = Itemsize * rm_ptr->GetGridCellCount(); + //name, std::string units, set, get, ptr, Nbytes, Itemsize + bv.SetBasic("L", false, true, true, Nbytes, Itemsize); + bv.SetTypes("double", "real(kind=8)", ""); + this->VarExchange.GetDoubleVectorRef() = rm_ptr->GetSolutionVolume(); + bv.GetDoubleVectorRef() = rm_ptr->GetSolutionVolume(); + bv.SetInitialized(true); + } + switch (this->task) + { + case VarManager::VAR_TASKS::GetPtr: + { + this->VarExchange.GetDoubleVectorRef() = rm_ptr->GetSolutionVolume(); + bv.SetDoubleVector(this->VarExchange.GetDoubleVectorRef()); + bv.SetVoidPtr((void*)(bv.GetDoubleVectorPtr())); + this->PointerSet.insert(VARS_myself); + this->UpdateSet.insert(VARS_myself); + break; + } + case VarManager::VAR_TASKS::GetVar: + case VarManager::VAR_TASKS::Update: + case VarManager::VAR_TASKS::RMUpdate: + { + this->VarExchange.GetDoubleVectorRef() = rm_ptr->GetSolutionVolume(); + bv.SetDoubleVector(this->VarExchange.GetDoubleVectorRef()); + break; + } + case VarManager::VAR_TASKS::SetVar: + assert(false); + break; + case VarManager::VAR_TASKS::no_op: + case VarManager::VAR_TASKS::Info: + break; + } + this->VarExchange.CopyScalars(bv); + this->SetCurrentVar(RMVARS::NotFound); +} +void VarManager::Time_Var() +{ + RMVARS VARS_myself = RMVARS::Time; + this->SetCurrentVar(VARS_myself); + BMIVariant& bv = this->VariantMap[VARS_myself]; + if (!bv.GetInitialized()) + { + int Itemsize = sizeof(double); + int Nbytes = Itemsize; + //name, std::string units, set, get, ptr, Nbytes, Itemsize + bv.SetBasic("s", true, true, true, Nbytes, Itemsize); + bv.SetTypes("double", "real(kind=8)", ""); + this->VarExchange.SetDVar(rm_ptr->GetTime()); + bv.SetDVar(rm_ptr->GetTime()); + bv.SetInitialized(true); + } + switch (this->task) + { + case VarManager::VAR_TASKS::GetPtr: + { + this->VarExchange.SetDVar(rm_ptr->GetTime()); + bv.SetDVar(rm_ptr->GetTime()); + bv.SetVoidPtr((void*)(bv.GetDVarPtr())); + this->PointerSet.insert(VARS_myself); + this->UpdateSet.insert(VARS_myself); + break; + } + case VarManager::VAR_TASKS::GetVar: + case VarManager::VAR_TASKS::Update: + case VarManager::VAR_TASKS::RMUpdate: + { + this->VarExchange.SetDVar(rm_ptr->GetTime()); + bv.SetDVar(rm_ptr->GetTime()); + break; + } + case VarManager::VAR_TASKS::SetVar: + rm_ptr->SetTime(*this->VarExchange.GetDVarPtr()); + bv.SetDVar(*this->VarExchange.GetDVarPtr()); + break; + case VarManager::VAR_TASKS::no_op: + case VarManager::VAR_TASKS::Info: + break; + } + this->VarExchange.CopyScalars(bv); + this->SetCurrentVar(RMVARS::NotFound); +} +void VarManager::TimeStep_Var() +{ + RMVARS VARS_myself = RMVARS::TimeStep; + this->SetCurrentVar(VARS_myself); + BMIVariant& bv = this->VariantMap[VARS_myself]; + if (!bv.GetInitialized()) + { + int Itemsize = sizeof(double); + int Nbytes = Itemsize; + //name, std::string units, set, get, ptr, Nbytes, Itemsize + bv.SetBasic("s", true, true, true, Nbytes, Itemsize); + bv.SetTypes("double", "real(kind=8)", ""); + this->VarExchange.SetDVar(rm_ptr->GetTimeStep()); + bv.SetDVar(rm_ptr->GetTimeStep()); + bv.SetInitialized(true); + } + switch (this->task) + { + case VarManager::VAR_TASKS::GetPtr: + { + this->VarExchange.SetDVar(rm_ptr->GetTimeStep()); + bv.SetDVar(rm_ptr->GetTimeStep()); + bv.SetVoidPtr((void*)(bv.GetDVarPtr())); + this->PointerSet.insert(VARS_myself); + this->UpdateSet.insert(VARS_myself); + break; + } + case VarManager::VAR_TASKS::GetVar: + case VarManager::VAR_TASKS::Update: + case VarManager::VAR_TASKS::RMUpdate: + { + this->VarExchange.SetDVar(rm_ptr->GetTimeStep()); + bv.SetDVar(rm_ptr->GetTimeStep()); + break; + } + case VarManager::VAR_TASKS::SetVar: + rm_ptr->SetTimeStep(*this->VarExchange.GetDVarPtr()); + bv.SetDVar(*this->VarExchange.GetDVarPtr()); + break; + case VarManager::VAR_TASKS::no_op: + case VarManager::VAR_TASKS::Info: + break; + } + this->VarExchange.CopyScalars(bv); + this->SetCurrentVar(RMVARS::NotFound); +} +void VarManager::CurrentSelectedOutputUserNumber_Var() +{ + RMVARS VARS_myself = RMVARS::CurrentSelectedOutputUserNumber; + this->SetCurrentVar(VARS_myself); + BMIVariant& bv = this->VariantMap[VARS_myself]; + if (!bv.GetInitialized()) + { + int Itemsize = (int)sizeof(int); + int Nbytes = (int)sizeof(int); + //std::string units, set, get, ptr, Nbytes, Itemsize + bv.SetBasic("id", false, true, false, Nbytes, Itemsize); + bv.SetTypes("int", "integer", "int"); + bv.SetIVar(rm_ptr->GetCurrentSelectedOutputUserNumber()); + bv.SetInitialized(true); + } + switch (this->task) + { + case VarManager::VAR_TASKS::GetPtr: + { + assert(false); + break; + } + case VarManager::VAR_TASKS::GetVar: + { + int v = rm_ptr->GetCurrentSelectedOutputUserNumber(); + bv.SetIVar(v); + break; + } + case VarManager::VAR_TASKS::SetVar: + assert(false); + break; + case VarManager::VAR_TASKS::RMUpdate: + { + assert(false); + break; + } + case VarManager::VAR_TASKS::Update: + { + assert(false); + break; + } + case VarManager::VAR_TASKS::Info: + case VarManager::VAR_TASKS::no_op: + break; + } + this->VarExchange.CopyScalars(bv); + this->SetCurrentVar(RMVARS::NotFound); +} +void VarManager::Porosity_Var() +{ + RMVARS VARS_myself = RMVARS::Porosity; + this->SetCurrentVar(VARS_myself); + BMIVariant& bv = this->VariantMap[VARS_myself]; + if (!bv.GetInitialized()) + { + int Itemsize = sizeof(double); + int Nbytes = Itemsize * rm_ptr->GetGridCellCount(); + //name, std::string units, set, get, ptr, Nbytes, Itemsize + bv.SetBasic("unitless", true, true, true, Nbytes, Itemsize); + bv.SetTypes("double", "real(kind=8)", ""); + this->VarExchange.GetDoubleVectorRef() = rm_ptr->GetPorosity(); + bv.GetDoubleVectorRef() = rm_ptr->GetPorosity(); + bv.SetInitialized(true); + } + switch (this->task) + { + case VarManager::VAR_TASKS::GetPtr: + { + this->VarExchange.GetDoubleVectorRef() = rm_ptr->GetPorosity(); + bv.SetDoubleVector(this->VarExchange.GetDoubleVectorRef()); + bv.SetVoidPtr((void*)(bv.GetDoubleVectorPtr())); + this->PointerSet.insert(VARS_myself); + this->UpdateSet.insert(VARS_myself); + break; + } + case VarManager::VAR_TASKS::GetVar: + case VarManager::VAR_TASKS::Update: + case VarManager::VAR_TASKS::RMUpdate: + { + this->VarExchange.GetDoubleVectorRef() = rm_ptr->GetPorosity(); + bv.SetDoubleVector(this->VarExchange.GetDoubleVectorRef()); + break; + } + case VarManager::VAR_TASKS::SetVar: + rm_ptr->SetPorosity(this->VarExchange.GetDoubleVectorRef()); + bv.SetDoubleVector(this->VarExchange.GetDoubleVectorRef()); + break; + case VarManager::VAR_TASKS::no_op: + case VarManager::VAR_TASKS::Info: + break; + } + this->VarExchange.CopyScalars(bv); + this->SetCurrentVar(RMVARS::NotFound); +} +void VarManager::Pressure_Var() +{ + RMVARS VARS_myself = RMVARS::Pressure; + this->SetCurrentVar(VARS_myself); + BMIVariant& bv = this->VariantMap[VARS_myself]; + if (!bv.GetInitialized()) + { + int Itemsize = sizeof(double); + int Nbytes = Itemsize * rm_ptr->GetGridCellCount(); + //name, std::string units, set, get, ptr, Nbytes, Itemsize + bv.SetBasic("atm", true, true, true, Nbytes, Itemsize); + bv.SetTypes("double", "real(kind=8)", ""); + this->VarExchange.GetDoubleVectorRef() = rm_ptr->GetPressure(); + bv.GetDoubleVectorRef() = rm_ptr->GetPressure(); + bv.SetInitialized(true); + } + switch (this->task) + { + case VarManager::VAR_TASKS::GetPtr: + { + this->VarExchange.GetDoubleVectorRef() = rm_ptr->GetPressure(); + bv.SetDoubleVector(this->VarExchange.GetDoubleVectorRef()); + bv.SetVoidPtr((void*)(bv.GetDoubleVectorPtr())); + this->PointerSet.insert(VARS_myself); + this->UpdateSet.insert(VARS_myself); + break; + } + case VarManager::VAR_TASKS::GetVar: + case VarManager::VAR_TASKS::Update: + case VarManager::VAR_TASKS::RMUpdate: + { + this->VarExchange.GetDoubleVectorRef() = rm_ptr->GetPressure(); + bv.SetDoubleVector(this->VarExchange.GetDoubleVectorRef()); + break; + } + case VarManager::VAR_TASKS::SetVar: + rm_ptr->SetPressure(this->VarExchange.GetDoubleVectorRef()); + bv.SetDoubleVector(this->VarExchange.GetDoubleVectorRef()); + break; + case VarManager::VAR_TASKS::no_op: + case VarManager::VAR_TASKS::Info: + break; + } + this->VarExchange.CopyScalars(bv); + this->SetCurrentVar(RMVARS::NotFound); +} +void VarManager::SelectedOutputOn_Var() +{ + RMVARS VARS_myself = RMVARS::SelectedOutputOn; + this->SetCurrentVar(VARS_myself); + BMIVariant& bv = this->VariantMap[VARS_myself]; + if (!bv.GetInitialized()) + { + int Itemsize = (int)sizeof(bool); + int Nbytes = (int)sizeof(bool); + //std::string units, set, get, ptr, Nbytes, Itemsize + bv.SetBasic("bool", true, true, true, Nbytes, Itemsize); + bv.SetTypes("bool", "logical", ""); + bv.SetBVar(rm_ptr->GetSelectedOutputOn()); + bv.SetInitialized(true); + } + switch (this->task) + { + case VarManager::VAR_TASKS::GetPtr: + { + int v = rm_ptr->GetSelectedOutputOn(); + bv.SetBVar(v); + bv.SetVoidPtr((void*)(bv.GetBVarPtr())); + this->PointerSet.insert(VARS_myself); + this->UpdateSet.insert(VARS_myself); + break; + } + case VarManager::VAR_TASKS::Update: + case VarManager::VAR_TASKS::RMUpdate: + case VarManager::VAR_TASKS::GetVar: + { + bool v = rm_ptr->GetSelectedOutputOn(); + bv.SetBVar(v); + break; + } + case VarManager::VAR_TASKS::SetVar: + { + bool v = this->VarExchange.GetBVar(); + bv.SetBVar(v); + rm_ptr->SetSelectedOutputOn(v); + break; + } + case VarManager::VAR_TASKS::Info: + case VarManager::VAR_TASKS::no_op: + break; + } + this->VarExchange.CopyScalars(bv); + this->SetCurrentVar(RMVARS::NotFound); +} +void VarManager::Temperature_Var() +{ + RMVARS VARS_myself = RMVARS::Temperature; + this->SetCurrentVar(VARS_myself); + BMIVariant& bv = this->VariantMap[VARS_myself]; + if (!bv.GetInitialized()) + { + int Itemsize = sizeof(double); + int Nbytes = Itemsize * rm_ptr->GetGridCellCount(); + //name, std::string units, set, get, ptr, Nbytes, Itemsize + bv.SetBasic("C", true, true, true, Nbytes, Itemsize); + bv.SetTypes("double", "real(kind=8)", ""); + this->VarExchange.GetDoubleVectorRef() = rm_ptr->GetTemperature(); + bv.GetDoubleVectorRef() = rm_ptr->GetTemperature(); + bv.SetInitialized(true); + } + switch (this->task) + { + case VarManager::VAR_TASKS::GetPtr: + { + this->VarExchange.GetDoubleVectorRef() = rm_ptr->GetTemperature(); + bv.SetDoubleVector(this->VarExchange.GetDoubleVectorRef()); + bv.SetVoidPtr((void*)(bv.GetDoubleVectorPtr())); + this->PointerSet.insert(VARS_myself); + this->UpdateSet.insert(VARS_myself); + break; + } + case VarManager::VAR_TASKS::GetVar: + case VarManager::VAR_TASKS::Update: + case VarManager::VAR_TASKS::RMUpdate: + { + this->VarExchange.GetDoubleVectorRef() = rm_ptr->GetTemperature(); + bv.SetDoubleVector(this->VarExchange.GetDoubleVectorRef()); + break; + } + case VarManager::VAR_TASKS::SetVar: + rm_ptr->SetTemperature(this->VarExchange.GetDoubleVectorRef()); + bv.SetDoubleVector(this->VarExchange.GetDoubleVectorRef()); + break; + case VarManager::VAR_TASKS::no_op: + case VarManager::VAR_TASKS::Info: + break; + } + this->VarExchange.CopyScalars(bv); + this->SetCurrentVar(RMVARS::NotFound); +} +/// end_ +//////////////////////////////// + +#ifdef SKIP + + +void VarManager::InputVarNames_var(PhreeqcRM* rm_ptr) +{ + static bool initialized = false; + static std::vector InputVarNames; + static std::vector CharVector; + // + PhreeqcRM::BMI_TASKS task_save = rm_ptr->task; + std::vector names = rm_ptr->GetInputVarNames(); + rm_ptr->task = task_save; + size_t size = 0; + for (size_t i = 0; i < names.size(); i++) + { + if (names[i].size() > size) size = names[i].size(); + } + int Itemsize = (int)size; + int Nbytes = (int)(size * names.size()); + //name, std::string units, set, get, ptr, Nbytes, Itemsize + BMI_Var bv = BMI_Var("InputVarNames", "names", false, true, false, Nbytes, Itemsize); + bv.SetTypes("std::vector", "character(len=:),allocatable,dimension(:)", ""); + rm_ptr->var_man->VarExchange = bv; + switch (rm_ptr->task) + { + case VarManager::VAR_TASKS::GetPtr: + { + if (!initialized) + { + InputVarNames = rm_ptr->GetInputVarNames(); + initialized = true; + for (size_t i = 0; i < InputVarNames.size(); i++) + { + CharVector.push_back(InputVarNames[i].c_str()); + } + } + rm_ptr->var_man->VarExchange.SetCharVector(CharVector); + break; + } + case VarManager::VAR_TASKS::GetVar: + rm_ptr->var_man->VarExchange.StringVector = rm_ptr->GetInputVarNames(); + rm_ptr->var_man->VarExchange = bv; + break; + case VarManager::VAR_TASKS::SetVar: + rm_ptr->var_man->VarExchange.NotImplemented = true; + break; + case VarManager::VAR_TASKS::Info: + break; + case VarManager::VAR_TASKS::no_op: + break; + } +} +void VarManager::OutputVarNames_var(PhreeqcRM* rm_ptr) +{ + static bool initialized = false; + static std::vector OutputVarNames; + static std::vector CharVector; + // + PhreeqcRM::BMI_TASKS task_save = rm_ptr->task; + std::vector names = rm_ptr->GetOutputVarNames(); + rm_ptr->task = task_save; + size_t size = 0; + for (size_t i = 0; i < names.size(); i++) + { + if (names[i].size() > size) size = names[i].size(); + } + int Itemsize = (int)size; + int Nbytes = (int)(size * names.size()); + //name, std::string units, set, get, ptr, Nbytes, Itemsize + BMI_Var bv = BMI_Var("OutputVarNames", "names", false, true, false, Nbytes, Itemsize); + bv.SetTypes("std::vector", "character(len=:),allocatable,dimension(:)", ""); + rm_ptr->var_man->VarExchange = bv; + switch (rm_ptr->task) + { + case VarManager::VAR_TASKS::GetPtr: + { + if (!initialized) + { + OutputVarNames = rm_ptr->GetOutputVarNames(); + initialized = true; + for (size_t i = 0; i < OutputVarNames.size(); i++) + { + CharVector.push_back(OutputVarNames[i].c_str()); + } + } + rm_ptr->var_man->VarExchange.SetCharVector(CharVector); + break; + } + case VarManager::VAR_TASKS::GetVar: + rm_ptr->var_man->VarExchange.StringVector = rm_ptr->GetOutputVarNames(); + rm_ptr->var_man->VarExchange = bv; + break; + case VarManager::VAR_TASKS::SetVar: + rm_ptr->var_man->VarExchange.NotImplemented = true; + break; + case VarManager::VAR_TASKS::Info: + break; + case VarManager::VAR_TASKS::no_op: + break; + } +} +#endif + + +////////////////// diff --git a/src/VarManager.h b/src/VarManager.h new file mode 100644 index 000000000..fb2cc32bc --- /dev/null +++ b/src/VarManager.h @@ -0,0 +1,119 @@ +#if !defined(VARMANAGER_H_INCLUDED) +#define VARMANAGER_H_INCLUDED +#include +#include +#include +#include +#include +#include +#include "PhreeqcRM.h" +#include "RMVARS.h" +//class PhreeqcRM; +#include "BMI_Var.h" + + +class IRM_DLL_EXPORT VarManager +{ +public: + enum class VAR_TASKS { + RMUpdate, + Update, + GetPtr, + GetVar, + SetVar, + //Init, + Info, + no_op + }; + //enum class RMVARS { + // NotFound, + // ComponentCount, + // Components, + // Concentrations, + // Density, + // ErrorString, + // FilePrefix, + // Gfw, + // GridCellCount, + // InputVarNames, + // NthSelectedOutput, + // OutputVarNames, + // Saturation, + // SelectedOutput, + // SelectedOutputColumnCount, + // SelectedOutputCount, + // SelectedOutputHeadings, + // SelectedOutputRowCount, + // SolutionVolume, + // Time, + // TimeStep, + // CurrentSelectedOutputUserNumber, + // Porosity, + // Pressure, + // SelectedOutputOn, + // Temperature + //}; + // Constructor + VarManager(PhreeqcRM* rm_ptr); + // Data + PhreeqcRM* rm_ptr; +public: + BMIVariant VarExchange; + std::set PointerSet; + std::set UpdateSet; + RMVARS CurrentVar; + std::map < std::string, RMVARS> EnumMap; + VAR_TASKS task; + std::map VariantMap; + // Methods + RMVARS GetEnum(std::string name); + void RM2BMIUpdate(RMVARS v_enum); + + + RMVARS GetCurrentVar() { return this->CurrentVar; } + std::map & GetVariantMap() { return this->VariantMap; } + void SetCurrentVar(RMVARS v) { this->CurrentVar = v; } + // Function pointer definition + typedef void (VarManager::* VarFunction)(void); + void ExecFn(RMVARS v_enum) { + VarFunction f = this->GetFn(v_enum); + ((*this).*f)(); + } + //!typedef void (VarManager::* VarFunction)(PhreeqcRM* rm_ptr); + //typedef VarManager* (*NewDogFunction)(void); + //typedef void (VarManager::* VarFunction)(PhreeqcRM* rm_ptr); // function pointer type + //typedef std::map VarFunction_map; + //VarFunction_map FnMap; + //void test() { VarFunction x = VarManager::Concentrations_var; + //VarVariant vv; + //vv.SetFn(VarFux); + VarFunction GetFn(RMVARS v_enum); + // Var functions + void ComponentCount_Var(); + void Components_Var(); + void Concentrations_Var(); + void Density_Var(); + void ErrorString_Var(); + void FilePrefix_Var(); + void Gfw_Var(); + void GridCellCount_Var(); + //void InputVarNames_Var(); + void NthSelectedOutput_Var(); + //void OutputVarNames_Var(); + void Saturation_Var(); + void SelectedOutput_Var(); + void SelectedOutputColumnCount_Var(); + void SelectedOutputCount_Var(); + void SelectedOutputHeadings_Var(); + void SelectedOutputRowCount_Var(); + void SolutionVolume_Var(); + void Time_Var(); + void TimeStep_Var(); + void CurrentSelectedOutputUserNumber_Var(); + void Porosity_Var(); + void Pressure_Var(); + void SelectedOutputOn_Var(); + void Temperature_Var(); +}; +#endif + diff --git a/src/YAMLPhreeqcRM.cpp b/src/YAMLPhreeqcRM.cpp index a29f40f90..6304aa968 100644 --- a/src/YAMLPhreeqcRM.cpp +++ b/src/YAMLPhreeqcRM.cpp @@ -6,15 +6,37 @@ #include #include "YAMLPhreeqcRM.h" +std::map YAMLPhreeqcRM::Instances; +std::mutex YAMLPhreeqcRM::InstancesLock; +size_t YAMLPhreeqcRM::InstancesIndex = 0; + YAMLPhreeqcRM::YAMLPhreeqcRM() { + InstancesLock.lock(); + this->Index = YAMLPhreeqcRM::InstancesIndex++; + std::map::value_type instance(this->Index, this); + YAMLPhreeqcRM::Instances.insert(instance); + InstancesLock.unlock(); +} +YAMLPhreeqcRM::~YAMLPhreeqcRM() +{ + InstancesLock.lock(); + std::map::iterator it = YAMLPhreeqcRM::Instances.find(this->Index); + if (it != YAMLPhreeqcRM::Instances.end()) + { + YAMLPhreeqcRM::Instances.erase(it); + } + InstancesLock.unlock(); } -void YAMLPhreeqcRM::clear() +void YAMLPhreeqcRM::Clear() { YAML::Node empty; YAML_doc = empty; } - +int YAMLPhreeqcRM::GetId(void)const +{ + return (int)this->Index; +} void YAMLPhreeqcRM::WriteYAMLDoc(std::string file_name) { std::ofstream ofs = std::ofstream(file_name.c_str(), std::ofstream::out); @@ -31,9 +53,12 @@ void YAMLPhreeqcRM::YAMLCreateMapping(std::vector< int >& grid2chem) YAML_doc["CreateMapping"] = grid2chem; return; }; -void YAMLPhreeqcRM::YAMLDumpModule() +void YAMLPhreeqcRM::YAMLDumpModule(bool dump_on, bool append) { - YAML_doc["YAMLDumpModule"] = ""; + YAML::Node node; + node["dump_on"] = dump_on; + node["append"] = append; + YAML_doc["YAMLDumpModule"] = node; return; } void YAMLPhreeqcRM::YAMLFindComponents() @@ -326,5 +351,51 @@ void YAMLPhreeqcRM::YAMLWarningMessage(std::string warnstr) return; } // +// helper functions +// +int +YAMLPhreeqcRMLib::CreateYAMLPhreeqcRM(void) +{ + int n = IRM_OUTOFMEMORY; + YAMLPhreeqcRM* YAMLPhreeqcRMPtr; + try + { + YAMLPhreeqcRMPtr = new YAMLPhreeqcRM; + n = (int)YAMLPhreeqcRMPtr->Index; + } + catch (const std::bad_alloc&) + { + return IRM_OUTOFMEMORY; + } + return n; +} +IRM_RESULT +YAMLPhreeqcRMLib::DestroyYAMLPhreeqcRM(int id) +{ + IRM_RESULT retval = IRM_BADINSTANCE; + if (id >= 0) + { + if (YAMLPhreeqcRM* ptr = YAMLPhreeqcRMLib::GetInstance(id)) + { + delete ptr; + retval = IRM_OK; + } + } + return retval; +} + +YAMLPhreeqcRM* +YAMLPhreeqcRMLib::GetInstance(int id) +{ + YAMLPhreeqcRM* instance = 0; + YAMLPhreeqcRM::InstancesLock.lock(); + std::map::iterator it = YAMLPhreeqcRM::Instances.find(size_t(id)); + if (it != YAMLPhreeqcRM::Instances.end()) + { + instance = (*it).second; + } + YAMLPhreeqcRM::InstancesLock.unlock(); + return instance; +} #endif \ No newline at end of file diff --git a/src/YAMLPhreeqcRM.h b/src/YAMLPhreeqcRM.h index 799fe374d..384d0c425 100644 --- a/src/YAMLPhreeqcRM.h +++ b/src/YAMLPhreeqcRM.h @@ -2,10 +2,14 @@ /*! @file YAMLPhreeqcRM.h @brief YAMLPhreeqcRM C++ Documentation */ +#ifndef INC_YAMLPHREEQCRM_H +#define INC_YAMLPHREEQCRM_H #include +#include #include #include "yaml-cpp/yaml.h" -#pragma once +#include "IrmResult.h" +//#pragma once #if defined(_WINDLL) #define IRM_DLL_EXPORT __declspec(dllexport) @@ -18,17 +22,24 @@ * * @brief YAML helper class */ - class IRM_DLL_EXPORT YAMLPhreeqcRM { private: YAML::Node YAML_doc; + std::map method_map; +protected: + friend class YAMLPhreeqcRMLib; + static std::map Instances; + static std::mutex InstancesLock; + static size_t InstancesIndex; + size_t Index; public: /** Constructor */ YAMLPhreeqcRM(); + ~YAMLPhreeqcRM(); /** Clears all definitions from the YAML document. @par C++ Example: @@ -43,7 +54,12 @@ class IRM_DLL_EXPORT YAMLPhreeqcRM
@endhtmlonly */ - void clear(); + void Clear(); /** + * Retrieves the id of this object. Each instance receives an id which is incremented for each instance + * starting with the value zero. + * @return The id. + */ + int GetId(void)const; /** Returns a constant reference to the YAML document. @par C++ Example: @@ -149,7 +165,7 @@ yrm.YAMLCloseFiles();
@endhtmlonly */ - void YAMLDumpModule(); + void YAMLDumpModule(bool dump_on, bool append); /** Inserts data into the YAML document for the PhreeqcRM method FindComponents. When the YAML document is written to file it can be processed by the method InitializeYAML to @@ -407,8 +423,9 @@ yrm.YAMLCloseFiles(); When the YAML document is written to file it can be processed by the method InitializeYAML to initialize a PhreeqcRM instance. @par - RunCells runs a reactions for all cells in the reaction module. - During initialization, RunCells can be used to equilibrate each solution with all reacts in a cell while + RunCells runs reactions for all cells in the reaction module. + During initialization, RunCells can be used to equilibrate + each solution with all reactants in a cell while using a time step of zero (@ref YAMLSetTimeStep) to avoid kinetic reactions. Other properties that may need to be initialized before RunCells is invoked include porosity (@ref YAMLSetPorosity), @@ -537,9 +554,9 @@ yrm.YAMLRunString(true, false, true, input.c_str()); When the YAML document is written to file it can be processed by the method InitializeYAML to initialize a PhreeqcRM instance. @par - SetConcentrations uses the vector of concentrations (@a c) to set the moles of components in each reaction cell. - For YAML initialization, it is unlikely that accurate concentrations are available unless previously calculated - concentrations are available. + The only way to use this method is to have pre-calculated PHREEQC solution concentrations, + which is not common. Concentrations are normally initialized + with @ref YAMLInitialPhreeqc2Module or @ref YAMLInitialPhreeqcCell2Module. @param c Vector of component concentrations. Size of vector is @a ncomps times @a nxyz, where @a ncomps is the number of components as determined by FindComponents or GetComponentCount and @@ -752,7 +769,8 @@ yrm.YAMLRunString(true, false, true, input.c_str()); */ void YAMLSetGasPhaseVolume(std::vector< double > gas_volume); /** -Inserts data into the YAML document to define the number of cells. +Inserts data into the YAML document to define the number of cells in the +user's model. Once the YAML document is written, the number of model cells can be extracted with the method GetGridCellCountYAML. GetGridCellCountYAML is NOT a PhreeqcRM method; it is a global method and must be used BEFORE the PhreeqcRM instance @@ -1165,8 +1183,6 @@ node "SetGridCellCount:", GetGridCellCountYAML will return zero.
@endhtmlonly - @par MPI: - Called by root and (or) workers. */ void YAMLSetTemperature(std::vector< double > t); /** @@ -1542,7 +1558,7 @@ node "SetGridCellCount:", GetGridCellCountYAML will return zero. @htmlonly
-	yrm.YAMLGetSpeciesConcentrations(c);
+	yrm.YAMLSetSpeciesConcentrations(c);
 	
@endhtmlonly @@ -1681,14 +1697,23 @@ node "SetGridCellCount:", GetGridCellCountYAML will return zero. @htmlonly
-	phreeqc_rm.WarningMessage("Need to check these definitions.");
+	yrm.YAMLWarningMessage("Need to check these definitions.");
 	
@endhtmlonly */ void YAMLWarningMessage(std::string warnstr); // data -private: - std::map method_map; + }; +class YAMLPhreeqcRMLib +{ +public: + //static void CleanupYAMLPhreeqcRMInstances(void); + static int CreateYAMLPhreeqcRM(void); + static IRM_RESULT DestroyYAMLPhreeqcRM(int n); + static YAMLPhreeqcRM* GetInstance(int n); +}; + +#endif // INC_YAMLPHREEQCRM_H #endif \ No newline at end of file diff --git a/src/YAML_interface.F90 b/src/YAML_interface.F90 new file mode 100644 index 000000000..0d3ead56b --- /dev/null +++ b/src/YAML_interface.F90 @@ -0,0 +1,2702 @@ +#ifdef USE_YAML +MODULE YAML_interface + contains +!> Creates a YAMLPhreeqcRM instance with a YAML document that is ready to +!> for writing data for initiation of a PhreeqcRM instance. +!> @retval id Id of the new YAMLPhreeqcRM instance. +!> @see +!> @ref DestroyYAMLPhreeqcRM. +!> @par Fortran Example: +!> @htmlonly +!> +!>
+!> ! Create YAMLPhreeqcRM document
+!> id = CreateYAMLPhreeqcRM() 
+!> 
+!>
+!> @endhtmlonly + INTEGER FUNCTION CreateYAMLPhreeqcRM() + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION CreateYAMLPhreeqcRM_F() & + BIND(C, NAME='CreateYAMLPhreeqcRM_F') + USE ISO_C_BINDING + IMPLICIT NONE + END FUNCTION CreateYAMLPhreeqcRM_F + END INTERFACE + CreateYAMLPhreeqcRM = CreateYAMLPhreeqcRM_F() + END FUNCTION CreateYAMLPhreeqcRM +!> Deletes the YAMLPhreeqcRM instance and all data. +!> @param id The instance id returned from @ref CreateYAMLPhreeqcRM. +!> @retval IRM_RESULT Zero indicates success, negative indicates failure. +!> @see +!> @ref YAMLClear. +!> @par Fortran Example: +!> @htmlonly +!> +!>
+!> YAML_filename = "AdvectBMI_f90.yaml"
+!> status = WriteYAMLDoc(id, YAML_filename)
+!> status = YAMLClear(id)  
+!> status = DestroyYAMLPhreeqcRM(id)
+!> 
+!>
+!> @endhtmlonly + INTEGER FUNCTION DestroyYAMLPhreeqcRM(id) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION DestroyYAMLPhreeqcRM_F(id) & + BIND(C, NAME='DestroyYAMLPhreeqcRM_F') + USE ISO_C_BINDING + IMPLICIT NONE + integer(kind=C_INT), intent(in) :: id + END FUNCTION DestroyYAMLPhreeqcRM_F + END INTERFACE + integer, intent(in) :: id + DestroyYAMLPhreeqcRM = DestroyYAMLPhreeqcRM_F(id) + END FUNCTION DestroyYAMLPhreeqcRM +!> Writes YAML document to file. +!> @param id The instance id returned from @ref CreateYAMLPhreeqcRM. +!> @param file_name Name of file to write YAML document. +!> @retval IRM_RESULT Zero indicates success, negative indicates failure. +!> @see +!> @ref DestroyYAMLPhreeqcRM, @ref YAMLClear. +!> @par Fortran Example: +!> @htmlonly +!> +!>
+!> YAML_filename = "AdvectBMI_f90.yaml"
+!> status = WriteYAMLDoc(id, YAML_filename)
+!> status = YAMLClear(id)  
+!> status = DestroyYAMLPhreeqcRM(id)
+!> 
+!>
+!> @endhtmlonly + INTEGER FUNCTION WriteYAMLDoc(id, file_name) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION WriteYAMLDoc_F(id, file_name) & + BIND(C, NAME='WriteYAMLDoc_F') + USE ISO_C_BINDING + IMPLICIT NONE + integer(kind=C_INT), intent(in) :: id + character(KIND=C_CHAR), intent(in) :: file_name(*) + END FUNCTION WriteYAMLDoc_F + END INTERFACE + integer, intent(in) :: id + character(len=*), intent(in) :: file_name + WriteYAMLDoc = WriteYAMLDoc_F(id, trim(file_name)//C_NULL_CHAR) + END FUNCTION WriteYAMLDoc +!> Clears all definitions from the YAML document. +!> @param id The instance id returned from @ref CreateYAMLPhreeqcRM. +!> @retval IRM_RESULT Zero indicates success, negative indicates failure. +!> @see +!> @ref DestroyYAMLPhreeqcRM. +!> @par Fortran Example: +!> @htmlonly +!> +!>
+!> YAML_filename = "AdvectBMI_f90.yaml"
+!> status = WriteYAMLDoc(id, YAML_filename)
+!> status = YAMLClear(id)  
+!> status = DestroyYAMLPhreeqcRM(id)
+!> 
+!>
+!> @endhtmlonly + INTEGER FUNCTION YAMLClear(id) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION YAMLClear_F(id) & + BIND(C, NAME='YAMLClear_F') + USE ISO_C_BINDING + IMPLICIT NONE + integer(kind=C_INT), intent(in) :: id + END FUNCTION YAMLClear_F + END INTERFACE + integer, intent(in) :: id + YAMLClear = YAMLClear_F(id) + END FUNCTION YAMLClear +!> Inserts data into the YAML document for the PhreeqcRM method CloseFiles. +!> When the YAML document is written to file it can be processed by the method InitializeYAML to +!> initialize a PhreeqcRM instance. +!> @param id The instance id returned from @ref CreateYAMLPhreeqcRM. +!> @retval IRM_RESULT Zero indicates success, negative indicates failure. +!> @par +!> CloseFiles closes the output and log files. +!> @par Fortran Example: +!> @htmlonly +!> +!>
+!> status = YAMLCloseFiles(id)
+!> 
+!>
+!> @endhtmlonly + INTEGER FUNCTION YAMLCloseFiles(id) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION YAMLCloseFiles_F(id) & + BIND(C, NAME='YAMLCloseFiles_F') + USE ISO_C_BINDING + IMPLICIT NONE + integer(kind=C_INT), intent(in) :: id + END FUNCTION YAMLCloseFiles_F + END INTERFACE + integer, intent(in) :: id + YAMLCloseFiles = YAMLCloseFiles_F(id) + END FUNCTION YAMLCloseFiles +!> Inserts data into the YAML document for the PhreeqcRM method CreateMapping. +!> When the YAML document is written to file it can be processed by the method InitializeYAML to +!> initialize a PhreeqcRM instance. +!> @param id The instance id returned from @ref CreateYAMLPhreeqcRM. +!> @param grid2chem Integer array of mapping from user's model grid to cells +!> for which chemistry will be run. +!> @retval IRM_RESULT Zero indicates success, negative indicates failure. +!> @par +!> CreateMapping +!> provides a mapping from grid cells in the user's model to reaction cells for which chemistry needs to be run. +!> The mapping is used to eliminate inactive cells and to use symmetry to decrease the number of cells +!> for which chemistry must be run. +!> The array @a grid2chem of size @a nxyz (the number of grid cells) +!> must contain the set of all integers 0 <= @a i < @a count_chemistry, +!> where @a count_chemistry is a number less than or equal to @a nxyz. +!> Inactive cells are assigned a negative integer. +!> The mapping may be many-to-one to account for symmetry. +!> Default is a one-to-one mapping--all user grid cells are reaction cells +!> (equivalent to @a grid2chem values of 0,1,2,3,...,nxyz-1). +!> @param grid2chem A vector of integers: Nonnegative is a reaction-cell number (0 based), +!> negative is an inactive cell. Vector is of size @a nxyz (number of grid cells). +!> @par Fortran Example: +!> @htmlonly +!> +!>
+!> ! Demonstation of mapping, two equivalent rows by symmetry
+!> ! zero-based indexing
+!> integer, allocatable, dimension(:) :: grid2chem
+!> allocate(grid2chem(nxyz))
+!> grid2chem = -1
+!> do i = 1, nxyz / 2 
+!> 	 grid2chem(i) = i - 1
+!> 	 grid2chem(i + nxyz / 2) = i - 1
+!> enddo
+!> status = YAMLCreateMapping(id, grid2chem)
+!> 
+!>
+!> @endhtmlonly + INTEGER FUNCTION YAMLCreateMapping(id, grid2chem) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION YAMLCreateMapping_F(id, grid2chem, l) & + BIND(C, NAME='YAMLCreateMapping_F') + USE ISO_C_BINDING + IMPLICIT NONE + integer(kind=C_INT), intent(in) :: id + integer(kind=C_INT), intent(in) :: grid2chem + integer(kind=C_INT), intent(in) :: l + END FUNCTION YAMLCreateMapping_F + END INTERFACE + integer, intent(in) :: id + integer, allocatable, dimension(:), intent(in) :: grid2chem + YAMLCreateMapping = YAMLCreateMapping_F(id, grid2chem(1), size(grid2chem)) + END FUNCTION YAMLCreateMapping +!> Inserts data into the YAML document for the PhreeqcRM method DumpModule. +!> When the YAML document is written to file it can be processed by the method InitializeYAML to +!> initialize a PhreeqcRM instance. +!> @param id The instance id returned from @ref CreateYAMLPhreeqcRM. +!> @param dump_on Signal for writing the dump file, true or false. +!> @param append Signal to append to the contents of the dump file, true or false. +!> @retval IRM_RESULT Zero indicates success, negative indicates failure. +!> @par +!> DumpModule writes the contents of all workers to file in _RAW formats (see appendix of PHREEQC version 3 manual), +!> including SOLUTIONs and all reactants. +!> @see @ref YAMLSetDumpFileName. +!> @par Fortran Example: +!> @htmlonly +!> +!>
+!> logical dump_on, append
+!> dump_on = .true.
+!> append = .false.
+!> status = YAMLSetDumpFileName(id, "Advect_cpp.dmp")
+!> status = YAMLDumpModule(id, dump_on, append)
+!> 
+!>
+!> @endhtmlonly + INTEGER FUNCTION YAMLDumpModule(id, dump_on, append) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION YAMLDumpModule_F(id, idump_on, iappend) & + BIND(C, NAME='YAMLDumpModule_F') + USE ISO_C_BINDING + IMPLICIT NONE + integer, intent(in) :: id + integer(kind=C_INT), intent(in) :: idump_on, iappend + END FUNCTION YAMLDumpModule_F + END INTERFACE + integer, intent(in) :: id + logical, intent(in) :: dump_on, append + integer :: idump_on, iappend + idump_on = 0 + iappend = 0 + if (dump_on) idump_on = 1 + if (append) iappend = 1 + YAMLDumpModule = YAMLDumpModule_F(id, idump_on, iappend) + END FUNCTION YAMLDumpModule +!> Inserts data into the YAML document for the PhreeqcRM method FindComponents. +!> When the YAML document is written to file it can be processed by the method InitializeYAML to +!> initialize a PhreeqcRM instance. +!> @param id The instance id returned from @ref CreateYAMLPhreeqcRM. +!> @retval IRM_RESULT Zero indicates success, negative indicates failure. +!> @par +!> FindComponents accumulates a list of elements. Elements are those that have been +!> defined in a solution or any other reactant +!> (EQUILIBRIUM_PHASE, KINETICS, and others), including charge imbalance. +!> This method can be called multiple times and the list that is created is cummulative. +!> The list is the set of components that needs to be transported. By default the list +!> includes water, excess H and excess O (the H and O not contained in water); +!> alternatively, the list may be set to contain total H and total O (@ref YAMLSetComponentH2O), +!> which requires transport results to be accurate to eight or nine significant digits. +!> If multicomponent diffusion (MCD) is to be modeled, +!> there is a capability to retrieve aqueous species concentrations +!> and to set new solution concentrations after +!> MCD by using individual species concentrations +!> (@ref YAMLSpeciesConcentrations2Module). +!> To use these methods, the save-species property needs to be turned on (@ref YAMLSetSpeciesSaveOn). +!> If the save-species property is on, FindComponents will generate +!> a list of aqueous species, +!> their diffusion coefficients at 25 C, +!> and their charge. +!> @see +!> @ref YAMLSetComponentH2O, +!> @ref YAMLSetSpeciesSaveOn, +!> @ref YAMLSpeciesConcentrations2Module. +!> @par +!> The FindComponents method also generates lists of reactants--equilibrium phases, +!> exchangers, gas components, kinetic reactants, solid solution components, and surfaces. +!> The lists are cumulative, including all reactants that were +!> defined in the initial phreeqc instance at any time FindComponents was called. +!> In addition, a list of phases is generated for which saturation indices may be calculated from the +!> cumulative list of components. +!> @par Fortran Example: +!> @htmlonly +!> +!>
+!> status = YAMLRunFile(id, yaml_file)
+!> status = YAMLFindComponents(id)
+!> 
+!>
+!> @endhtmlonly + INTEGER FUNCTION YAMLFindComponents(id) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION YAMLFindComponents_F(id) & + BIND(C, NAME='YAMLFindComponents_F') + USE ISO_C_BINDING + IMPLICIT NONE + integer(kind=C_INT), intent(in) :: id + END FUNCTION YAMLFindComponents_F + END INTERFACE + integer, intent(in) :: id + YAMLFindComponents = YAMLFindComponents_F(id) + END FUNCTION YAMLFindComponents +!> Inserts data into the YAML document for the PhreeqcRM method InitialPhreeqc2Module. +!> When the YAML document is written to file it can be processed by the method InitializeYAML to +!> initialize a PhreeqcRM instance. +!> @param id The instance id returned from @ref CreateYAMLPhreeqcRM. +!> @param ic1 Vector of solution and reactant index numbers that refer to +!> definitions in the InitialPhreeqc instance. +!> @retval IRM_RESULT Zero indicates success, negative indicates failure. +!> @par +!> InitialPhreeqc2Module transfers solutions and reactants from the InitialPhreeqc +!> instance to the reaction-module workers. +!> @a ic1 is used to select initial conditions, including solutions and reactants, +!> for each cell of the model, without mixing. +!> @a ic1 is dimensioned 7 times @a nxyz, where @a nxyz is the +!> number of grid cells in the user's model. +!> The dimension of 7 refers to solutions and reactants in the following order: +!> (0) SOLUTIONS, (1) EQUILIBRIUM_PHASES, (2) EXCHANGE, (3) SURFACE, (4) GAS_PHASE, +!> (5) SOLID_SOLUTIONS, and (6) KINETICS. +!> The definition initial_solution1[3*nxyz + 99] = 2, indicates that +!> cell 99 (0 based) contains the SURFACE definition (index 3) defined by SURFACE 2 +!> in the InitialPhreeqc instance. +!> +!> Size is 7 times @a nxyz. The order of definitions is given above. +!> Negative values are ignored, resulting in no definition of that entity for that cell. +!> @see @ref YAMLInitialPhreeqcCell2Module, +!> @ref YAMLInitialPhreeqc2Module_mix. +!> @par Fortran Example: +!> @htmlonly +!> +!>
+!> integer, allocatable, dimension(:,:) :: ic1
+!> allocate(ic1(nxyz,7))
+!> do i = 1, nxyz
+!> 	ic1(i,1) = 1     ! Solution 1
+!> 	ic1(i,2) = -1    ! Equilibrium phases none
+!> 	ic1(i,3) = 1     ! Exchange 1
+!> 	ic1(i,4) = -1    ! Surface none
+!> 	ic1(i,5) = -1    ! Gas phase none
+!> 	ic1(i,6) = -1    ! Solid solutions none
+!> 	ic1(i,7) = -1    ! Kinetics none
+!> enddo
+!> status = YAMLInitialPhreeqc2Module_mix(id, ic1) 
+!> 
+!>
+!> @endhtmlonly + INTEGER FUNCTION YAMLInitialPhreeqc2Module(id, ic1) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION YAMLInitialPhreeqc2Module_F(id, ic1, dim) & + BIND(C, NAME='YAMLInitialPhreeqc2Module_F') + USE ISO_C_BINDING + IMPLICIT NONE + integer(kind=C_INT), intent(in) :: id + integer(kind=C_INT), intent(in) :: ic1 + integer(kind=C_INT), intent(in) :: dim + END FUNCTION YAMLInitialPhreeqc2Module_F + END INTERFACE + integer, intent(in) :: id + integer, allocatable, dimension(:,:), intent(in) :: ic1 + integer :: l + l = size(ic1,1)*size(ic1,2) + YAMLInitialPhreeqc2Module = YAMLInitialPhreeqc2Module_F(id, ic1(1,1), l) + END FUNCTION YAMLInitialPhreeqc2Module +!> Inserts data into the YAML document for the PhreeqcRM method InitialPhreeqc2Module. +!> When the YAML document is written to file it can be processed by the method InitializeYAML to +!> initialize a PhreeqcRM instance. +!> @param id The instance id returned from @ref CreateYAMLPhreeqcRM. +!> @param ic1 Vector of solution and reactant index numbers that refer to +!> definitions in the InitialPhreeqc instance. +!> Size is 7 times @a nxyz, where @a nxyz is the number of grid cells in the user's model. +!> The order of reactants is given below and in the example. +!> Negative values are ignored, resulting in no definition of that entity for that cell. +!> @param ic2 Vector of solution and reactant index numbers that refer to +!> definitions in the InitialPhreeqc instance. +!> Nonnegative values of @a ic2 result in mixing with the entities defined in @a ic1. +!> Negative values result in no mixing. +!> Size is 7 times @a nxyz. +!> @param f1 Fraction of @a ic1 that mixes with (1 - @a f1) +!> of @a ic2. +!> Size is 7 times @a nxyz. +!> @retval IRM_RESULT Zero indicates success, negative indicates failure. +!> @par +!> InitialPhreeqc2Module transfers solutions and reactants from the InitialPhreeqc instance to +!> the reaction-module workers, possibly with mixing. +!> In its simplest form, @a ic1 is used to select initial conditions, including solutions and reactants, +!> for each cell of the model, without mixing. +!> The dimension of 7 refers to solutions and reactants in the following order: +!> (0) SOLUTIONS, (1) EQUILIBRIUM_PHASES, (2) EXCHANGE, (3) SURFACE, (4) GAS_PHASE, +!> (5) SOLID_SOLUTIONS, and (6) KINETICS. +!> The definition ic1[3*nxyz + 99] = 2, indicates that +!> cell 99 (0 based) contains the SURFACE definition (index 3) defined by SURFACE 2 +!> in the InitialPhreeqc instance (either by RunFile or RunString). +!> @n@n +!> It is also possible to mix solutions and reactants to obtain the initial conditions +!> for cells. For mixing, +!> @a initials_conditions2 contains numbers for a second entity that mixes with +!> the entity defined in @a ic1. +!> @a f1 contains the mixing fraction for @a ic1, +!> whereas (1 - @a f1) is the mixing fraction for @a ic2. +!> The definitions ic1[3*nxyz + 99] = 2, initial_solution2[3*nxyz + 99] = 3, +!> f1[3*nxyz + 99] = 0.25 indicates that +!> cell 99 (0 based) contains a mixture of 0.25 SURFACE 2 and 0.75 SURFACE 3, +!> where the surface compositions have been defined in the InitialPhreeqc instance. +!> If the user number in @a ic2 is negative, no mixing occurs. +!> +!> @see @ref YAMLInitialPhreeqcCell2Module, +!> @ref YAMLInitialPhreeqc2Module. +!> @par Fortran Example: +!> @htmlonly +!> +!>
+!> integer, allocatable, dimension(:,:) :: ic1
+!> integer, allocatable, dimension(:,:) :: ic2
+!> real(kind=8), allocatable, dimension(:,:) :: f1
+!> allocate(ic1(nxyz,7), ic2(nxyz,7), f1(nxyz,7))
+!> ic1 = -1
+!> ic2 = -1
+!> f1 = 1.0d0
+!> do i = 1, nxyz
+!> 	ic1(i,1) = 1     ! Solution 1
+!> 	ic1(i,2) = -1    ! Equilibrium phases none
+!> 	ic1(i,3) = 1     ! Exchange 1
+!> 	ic1(i,4) = -1    ! Surface none
+!> 	ic1(i,5) = -1    ! Gas phase none
+!> 	ic1(i,6) = -1    ! Solid solutions none
+!> 	ic1(i,7) = -1    ! Kinetics none
+!> enddo
+!> status = YAMLInitialPhreeqc2Module_mix(id, ic1, ic2, f1) 
+!> 
+!>
+!> @endhtmlonly + INTEGER FUNCTION YAMLInitialPhreeqc2Module_mix(id, ic1, ic2, f1) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION YAMLInitialPhreeqc2Module_mix_F(id, ic1, ic2, f1, dim) & + BIND(C, NAME='YAMLInitialPhreeqc2Module_mix_F') + USE ISO_C_BINDING + IMPLICIT NONE + integer(kind=C_INT), intent(in) :: id + integer(kind=C_INT), intent(in) :: ic1 + integer(kind=C_INT), intent(in) :: ic2 + real(kind=C_DOUBLE), intent(in) :: f1 + integer(kind=C_INT), intent(in) :: dim + END FUNCTION YAMLInitialPhreeqc2Module_mix_F + END INTERFACE + integer, intent(in) :: id + integer, allocatable, dimension(:,:), intent(in) :: ic1 + integer, allocatable, dimension(:,:), intent(in) :: ic2 + real(kind=8), allocatable, dimension(:,:), intent(in) :: f1 + integer :: l1, l2, l3 + l1 = size(ic1,1)*size(ic1,2) + l2 = size(ic2,1)*size(ic2,2) + l3 = size(f1,1)*size(f1,2) + if ((l1 .ne. l2) .or. (l1 .ne. l3)) then + stop "Dimension error in YAMLInitialPhreeqc2Module" + endif + YAMLInitialPhreeqc2Module_mix = YAMLInitialPhreeqc2Module_mix_F(id, ic1(1,1), ic2(1,1), f1(1,1), l1) + END FUNCTION YAMLInitialPhreeqc2Module_mix +!> Inserts data into the YAML document for the PhreeqcRM method InitialPhreeqcCell2Module. +!> When the YAML document is written to file it can be processed by the method InitializeYAML to +!> initialize a PhreeqcRM instance. +!> @param id The instance id returned from @ref CreateYAMLPhreeqcRM. +!> @param n Number that refers to a solution or MIX and associated +!> reactants in the InitialPhreeqc instance. +!> @param cell_numbers A vector of grid-cell numbers (user's grid-cell numbering system) that +!> will be populated with cell @a n from the InitialPhreeqc instance. +!> @retval IRM_RESULT Zero indicates success, negative indicates failure. +!> @par +!> InitialPhreeqcCell2Module uses a cell numbered @a n in the InitialPhreeqc instance to +!> populate a series of transport cells. +!> All reactants with the number @a n are transferred along with the solution. +!> If MIX @a n exists, it is used for the definition of the solution. +!> If @a n is negative, @a n is redefined to be the largest solution or MIX number +!> in the InitialPhreeqc instance. +!> All reactants for each cell in the list @a cell_numbers are removed before the cell +!> definition is copied from the InitialPhreeqc instance to the workers. +!> +!> @see @ref YAMLInitialPhreeqc2Module, +!> @ref @ref YAMLInitialPhreeqc2Module_mix. +!> @par Fortran Example: +!> @htmlonly +!> +!>
+!> integer, allocatable, dimension(:) :: module_cells
+!> allocate(module_cells(2))
+!> module_cells(1) = 18
+!> module_cells(2) = 19
+!> status = YAMLInitialPhreeqcCell2Module(id, -1, module_cells)
+!> 
+!>
+!> @endhtmlonly + INTEGER FUNCTION YAMLInitialPhreeqcCell2Module(id, n, cell_numbers) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION YAMLInitialPhreeqcCell2Module_F(id, n, cell_numbers, dim) & + BIND(C, NAME='YAMLInitialPhreeqcCell2Module_F') + USE ISO_C_BINDING + IMPLICIT NONE + integer(kind=C_INT), intent(in) :: id + integer(kind=C_INT), intent(in) :: n + integer(kind=C_INT), intent(in) :: cell_numbers + integer(kind=C_INT), intent(in) :: dim + END FUNCTION YAMLInitialPhreeqcCell2Module_F + END INTERFACE + integer, intent(in) :: id + integer, intent(in) :: n + integer, allocatable, dimension(:), intent(in) :: cell_numbers + integer :: l + l = size(cell_numbers) + YAMLInitialPhreeqcCell2Module = YAMLInitialPhreeqcCell2Module_F(id, n, cell_numbers(1), l) + END FUNCTION YAMLInitialPhreeqcCell2Module +!> Inserts data into the YAML document for the PhreeqcRM method LoadDatabase. +!> When the YAML document is written to file it can be processed by the method InitializeYAML to +!> initialize a PhreeqcRM instance. +!> @param id The instance id returned from @ref CreateYAMLPhreeqcRM. +!> @param file_name String containing the database name. +!> @retval IRM_RESULT Zero indicates success, negative indicates failure. +!> @par +!> LoadDatabase loads a database for all IPhreeqc instances--workers, InitialPhreeqc, and Utility. All definitions +!> of the reaction module are cleared (SOLUTION_SPECIES, PHASES, SOLUTIONs, etc.), and the database is read. +!> +!> @par Fortran Example: +!> @htmlonly +!> +!>
+!> status = YAMLLoadDatabase(id, "phreeqc.dat") 
+!> 
+!>
+!> @endhtmlonly + INTEGER FUNCTION YAMLLoadDatabase(id, file_name) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION YAMLLoadDatabase_F(id, file_name) & + BIND(C, NAME='YAMLLoadDatabase_F') + USE ISO_C_BINDING + IMPLICIT NONE + integer(kind=C_INT), intent(in) :: id + character(KIND=C_CHAR), intent(in) :: file_name(*) + END FUNCTION YAMLLoadDatabase_F + END INTERFACE + integer, intent(in) :: id + character(len=*), intent(in) :: file_name + YAMLLoadDatabase = YAMLLoadDatabase_F(id, trim(file_name)//C_NULL_CHAR) + END FUNCTION YAMLLoadDatabase +!> Inserts data into the YAML document for the PhreeqcRM method LogMessage. +!> When the YAML document is written to file it can be processed by the method InitializeYAML to +!> initialize a PhreeqcRM instance. +!> @param id The instance id returned from @ref CreateYAMLPhreeqcRM. +!> @param str String to be printed. +!> @retval IRM_RESULT Zero indicates success, negative indicates failure. +!> @par +!> LogMessage prints a message to the log file. +!> @see @ref YAMLOutputMessage, @ref YAMLScreenMessage, @ref YAMLWarningMessage. +!> @par Fortran Example: +!> @htmlonly +!> +!>
+!> status = YAMLLogMessage(id, "Finished section 1 of initialization")
+!> 
+!>
+!> @endhtmlonly + INTEGER FUNCTION YAMLLogMessage(id, str) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION YAMLLogMessage_F(id, str) & + BIND(C, NAME='YAMLLogMessage_F') + USE ISO_C_BINDING + IMPLICIT NONE + integer(kind=C_INT), intent(in) :: id + character(KIND=C_CHAR), intent(in) :: str(*) + END FUNCTION YAMLLogMessage_F + END INTERFACE + integer, intent(in) :: id + character(len=*), intent(in) :: str + YAMLLogMessage = YAMLLogMessage_F(id, trim(str)//C_NULL_CHAR) + END FUNCTION YAMLLogMessage +!> Inserts data into the YAML document for the PhreeqcRM method OpenFiles. +!> When the YAML document is written to file it can be processed by the method InitializeYAML to +!> initialize a PhreeqcRM instance. +!> @param id The instance id returned from @ref CreateYAMLPhreeqcRM. +!> @retval IRM_RESULT Zero indicates success, negative indicates failure. +!> @par +!> OpenFiles opens the output and log files. Files are named prefix.chem.txt and prefix.log.txt +!> based on the prefix defined by @ref YAMLSetFilePrefix. +!> @see @ref YAMLSetFilePrefix, @ref YAMLCloseFiles, +!> @ref YAMLLogMessage, @ref YAMLOutputMessage, and @ref YAMLWarningMessage. +!> @par Fortran Example: +!> @htmlonly +!> +!>
+!> status = YAMLSetFilePrefix(id, "Advect_cpp")
+!> status = YAMLOpenFiles(id)
+!> 
+!>
+!> @endhtmlonly + INTEGER FUNCTION YAMLOpenFiles(id) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION YAMLOpenFiles_F(id) & + BIND(C, NAME='YAMLOpenFiles_F') + USE ISO_C_BINDING + IMPLICIT NONE + integer(kind=C_INT), intent(in) :: id + END FUNCTION YAMLOpenFiles_F + END INTERFACE + integer, intent(in) :: id + YAMLOpenFiles = YAMLOpenFiles_F(id) + END FUNCTION YAMLOpenFiles +!> Inserts data into the YAML document for the PhreeqcRM method OutputMessage. +!> When the YAML document is written to file it can be processed by the method InitializeYAML to +!> initialize a PhreeqcRM instance. +!> @param id The instance id returned from @ref CreateYAMLPhreeqcRM. +!> @param str String to be printed. +!> @retval IRM_RESULT Zero indicates success, negative indicates failure. +!> @par +!> OutputMessage prints a message to the output file. +!> @see @ref YAMLLogMessage, @ref YAMLScreenMessage, @ref YAMLWarningMessage. +!> @par Fortran Example: +!> @htmlonly +!> +!>
+!> status = YAMLOutputMessage(id, "Finished section 1 of initialization")
+!> 
+!>
+!> @endhtmlonly + INTEGER FUNCTION YAMLOutputMessage(id, str) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION YAMLOutputMessage_F(id, str) & + BIND(C, NAME='YAMLOutputMessage_F') + USE ISO_C_BINDING + IMPLICIT NONE + integer(kind=C_INT), intent(in) :: id + character(KIND=C_CHAR), intent(in) :: str(*) + END FUNCTION YAMLOutputMessage_F + END INTERFACE + integer, intent(in) :: id + character(len=*), intent(in) :: str + YAMLOutputMessage = YAMLOutputMessage_F(id, trim(str)//C_NULL_CHAR) + END FUNCTION YAMLOutputMessage +!> Inserts data into the YAML document for the PhreeqcRM method RunCells. +!> When the YAML document is written to file it can be processed by the method InitializeYAML to +!> initialize a PhreeqcRM instance. +!> @param id The instance id returned from @ref CreateYAMLPhreeqcRM. +!> @retval IRM_RESULT Zero indicates success, negative indicates failure. +!> @par +!> RunCells runs reactions for all cells in the reaction module. +!> During initialization, RunCells can be used to equilibrate each solution with all +!> reactants in a cell while +!> using a time step of zero (@ref YAMLSetTimeStep) to avoid kinetic reactions. +!> Other properties that may need to be initialized before RunCells is invoked +!> include porosity (@ref YAMLSetPorosity), +!> saturation (@ref YAMLSetSaturation), +!> temperature (@ref YAMLSetTemperature), and pressure (@ref YAMLSetPressure). +!> +!> @see @ref YAMLSetPorosity, +!> @ref YAMLSetPressure, @ref YAMLSetSaturation, @ref YAMLSetTemperature, @ref YAMLSetTimeStep. +!> @par Fortran Example: +!> @htmlonly +!> +!>
+!> status = YAMLSetTimeStep(id, 0.0)
+!> status = YAMLRunCells(id)
+!> 
+!>
+!> @endhtmlonly + INTEGER FUNCTION YAMLRunCells(id) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION YAMLRunCells_F(id) & + BIND(C, NAME='YAMLRunCells_F') + USE ISO_C_BINDING + IMPLICIT NONE + integer(kind=C_INT), intent(in) :: id + END FUNCTION YAMLRunCells_F + END INTERFACE + integer, intent(in) :: id + YAMLRunCells = YAMLRunCells_F(id) + END FUNCTION YAMLRunCells +!> Inserts data into the YAML document for the PhreeqcRM method RunFile. +!> When the YAML document is written to file it can be processed by the method InitializeYAML to +!> initialize a PhreeqcRM instance. +!> @param id The instance id returned from @ref CreateYAMLPhreeqcRM. +!> @param workers @a True, the workers will run the file; @a False, the workers will not run the file. +!> @param initial_phreeqc @a True, the InitialPhreeqc instance will run the file; @a False, the InitialPhreeqc will not run the file. +!> @param utility @a True, the Utility instance will run the file; @a False, the Utility instance will not run the file. +!> @param chemistry_name Name of the file to run. +!> @retval IRM_RESULT Zero indicates success, negative indicates failure. +!> @par +!> RunFile runs a PHREEQC input file. The first three arguments determine which IPhreeqc instances will run +!> the file--the workers, the InitialPhreeqc instance, and (or) the Utility instance. Input +!> files that modify the thermodynamic database should be run by all three sets of instances. +!> Files with SELECTED_OUTPUT definitions that will be used during the time-stepping loop need to +!> be run by the workers. Files that contain initial conditions or boundary conditions should +!> be run by the InitialPhreeqc instance. +!> @see @ref YAMLRunString. +!> @par Fortran Example: +!> @htmlonly +!> +!>
+!> status = YAMLRunFile(id, .true., .true., .true., "advect.pqi")
+!> 
+!>
+!> @endhtmlonly + INTEGER FUNCTION YAMLRunFile(id, workers, initial_phreeqc, utility, file_name) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION YAMLRunFile_F(id, iworkers, iinitial_phreeqc, iutility, file_name) & + BIND(C, NAME='YAMLRunFile_F') + USE ISO_C_BINDING + IMPLICIT NONE + integer(kind=C_INT), intent(in) :: id + integer(kind=C_INT), intent(in) :: iworkers, iinitial_phreeqc, iutility + character(KIND=C_CHAR), intent(in) :: file_name(*) + END FUNCTION YAMLRunFile_F + END INTERFACE + integer, intent(in) :: id + logical, intent(in) :: workers, initial_phreeqc, utility + integer :: iworkers, iinitial_phreeqc, iutility + character(len=*), intent(in) :: file_name + iworkers = 0 + iinitial_phreeqc = 0 + iutility = 0 + if (workers) iworkers = 1 + if (initial_phreeqc) iinitial_phreeqc = 1 + if (utility) iutility = 1 + + YAMLRunFile = YAMLRunFile_F(id, iworkers, iinitial_phreeqc, iutility, trim(file_name)//C_NULL_CHAR) + END FUNCTION YAMLRunFile +!> Inserts data into the YAML document for the PhreeqcRM method RunString. +!> When the YAML document is written to file it can be processed by the method InitializeYAML to +!> initialize a PhreeqcRM instance. +!> @param id The instance id returned from @ref CreateYAMLPhreeqcRM. +!> @param workers @a True, the workers will run the string; @a False, the workers will not run the string. +!> @param initial_phreeqc @a True, the InitialPhreeqc instance will run the string; @a False, the InitialPhreeqc will not run the string. +!> @param utility @a True, the Utility instance will run the string; @a False, the Utility instance will not run the string. +!> @param input_string String containing PHREEQC input. +!> @retval IRM_RESULT Zero indicates success, negative indicates failure. +!> @par +!> RunString runs a PHREEQC input string. The first three arguments determine which +!> IPhreeqc instances will run +!> the string--the workers, the InitialPhreeqc instance, and (or) the Utility instance. Input +!> strings that modify the thermodynamic database should be run by all three sets of instances. +!> Strings with SELECTED_OUTPUT definitions that will be used during the time-stepping loop need to +!> be run by the workers. Strings that contain initial conditions or boundary conditions should +!> be run by the InitialPhreeqc instance. +!> @see @ref YAMLRunFile. +!> @par C++ Example: +!> @htmlonly +!> +!>
+!> input = "DELETE; -all"
+!> status = YAMLRunString(id, .true., .true., .true., "advect.pqi")
+!> 
+!>
+!> @endhtmlonly + INTEGER FUNCTION YAMLRunString(id, workers, initial_phreeqc, utility, input_string) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION YAMLRunString_F(id, iworkers, iinitial_phreeqc, iutility, input_string) & + BIND(C, NAME='YAMLRunString_F') + USE ISO_C_BINDING + IMPLICIT NONE + integer(kind=C_INT), intent(in) :: id + integer(kind=C_INT), intent(in) :: iworkers, iinitial_phreeqc, iutility + character(KIND=C_CHAR), intent(in) :: input_string(*) + END FUNCTION YAMLRunString_F + END INTERFACE + integer, intent(in) :: id + logical, intent(in) :: workers, initial_phreeqc, utility + integer :: iworkers, iinitial_phreeqc, iutility + character(len=*), intent(in) :: input_string + iworkers = 0 + iinitial_phreeqc = 0 + iutility = 0 + if (workers) iworkers = 1 + if (initial_phreeqc) iinitial_phreeqc = 1 + if (utility) iutility = 1 + YAMLRunString = YAMLRunString_F(id, iworkers, iinitial_phreeqc, iutility, trim(input_string)//C_NULL_CHAR) + END FUNCTION YAMLRunString +!> Inserts data into the YAML document for the PhreeqcRM method ScreenMessage. +!> When the YAML document is written to file it can be processed by the method InitializeYAML to +!> initialize a PhreeqcRM instance. +!> @param id The instance id returned from @ref CreateYAMLPhreeqcRM. +!> @param str String to be printed. +!> @retval IRM_RESULT Zero indicates success, negative indicates failure. +!> @par +!> ScreenMessage prints a message to the screen. +!> @see @ref YAMLLogMessage, @ref YAMLOutputMessage, @ref YAMLWarningMessage. +!> @par Fortran Example: +!> @htmlonly +!> +!>
+!> string = "Beginning to process YAML for initial conditions"
+!> status = YAMLScreenMessage(id, string)
+!> 
+!>
+!> @endhtmlonly + INTEGER FUNCTION YAMLScreenMessage(id, str) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION YAMLScreenMessage_F(id, str) & + BIND(C, NAME='YAMLScreenMessage_F') + USE ISO_C_BINDING + IMPLICIT NONE + integer(kind=C_INT), intent(in) :: id + character(KIND=C_CHAR), intent(in) :: str(*) + END FUNCTION YAMLScreenMessage_F + END INTERFACE + integer, intent(in) :: id + character(len=*), intent(in) :: str + YAMLScreenMessage = YAMLScreenMessage_F(id, trim(str)//C_NULL_CHAR) + END FUNCTION YAMLScreenMessage +!> Inserts data into the YAML document for the PhreeqcRM method SetComponentH2O. +!> When the YAML document is written to file it can be processed by the method InitializeYAML to +!> initialize a PhreeqcRM instance. +!> @param id The instance id returned from @ref CreateYAMLPhreeqcRM. +!> @param tf @a True (default), excess H, excess O, and water are included in the component list; +!> @a False, total H and O are included in the component list. +!> @retval IRM_RESULT Zero indicates success, negative indicates failure. +!> @par +!> SetComponentH2O selects whether to include H2O in the component list. +!> The concentrations of H and O must be known +!> accurately (8 to 10 significant digits) for the numerical method of +!> PHREEQC to produce accurate pH and pe values. +!> Because most of the H and O are in the water species, +!> it may be more robust (require less accuracy in transport) to +!> transport the excess H and O (the H and O not in water) and water. +!> The default setting (@a true) is to include water, excess H, and excess O as components. +!> A setting of @a false will include total H and total O as components. +!> YAMLSetComponentH2O must be called before @ref YAMLFindComponents. +!> @see @ref YAMLFindComponents. +!> @par Fortran Example: +!> @htmlonly +!> +!>
+!> status = YAMLSetComponentH2O(id, .false.)
+!> 
+!>
+!> @endhtmlonly + INTEGER FUNCTION YAMLSetComponentH2O(id, tf) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION YAMLSetComponentH2O_F(id, itf) & + BIND(C, NAME='YAMLSetComponentH2O_F') + USE ISO_C_BINDING + IMPLICIT NONE + integer(kind=C_INT), intent(in) :: id + integer(kind=C_INT), intent(in) :: itf + END FUNCTION YAMLSetComponentH2O_F + END INTERFACE + integer, intent(in) :: id + logical, intent(in) :: tf + integer :: itf + itf = 0 + if (tf) itf = 1 + YAMLSetComponentH2O = YAMLSetComponentH2O_F(id, itf) + END FUNCTION YAMLSetComponentH2O +!> Inserts data into the YAML document for the PhreeqcRM method SetConcentrations. +!> When the YAML document is written to file it can be processed by the method InitializeYAML to +!> initialize a PhreeqcRM instance. +!> @param id The instance id returned from @ref CreateYAMLPhreeqcRM. +!> @param c Vector of component concentrations. Size of vector is @a ncomps times @a nxyz, +!> where @a ncomps is the number of components as determined +!> by FindComponents or GetComponentCount and +!> @a nxyz is the number of grid cells in the user's model. +!> @retval IRM_RESULT Zero indicates success, negative indicates failure. +!> @par +!> The only way to use this method is to have pre-calculated PHREEQC solution concentrations, +!> which is not common. Concentrations are normally initialized +!> with @ref YAMLInitialPhreeqc2Module or @ref YAMLInitialPhreeqcCell2Module. +!> @see @ref YAMLSetDensity, @ref YAMLSetPorosity, @ref YAMLSetRepresentativeVolume, +!> @ref YAMLSetSaturation, @ref YAMLSetUnitsSolution. +!> @par C++ Example: +!> @htmlonly +!> +!>
+!> status = YAMLSetConcentrations(id, c)
+!> 
+!>
+!> @endhtmlonly + INTEGER FUNCTION YAMLSetConcentrations(id, c) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION YAMLSetConcentrations_F(id, c, dim) & + BIND(C, NAME='YAMLSetConcentrations_F') + USE ISO_C_BINDING + IMPLICIT NONE + integer(kind=C_INT), intent(in) :: id + real(kind=C_DOUBLE), intent(in) :: c + integer(kind=C_INT), intent(in) :: dim + END FUNCTION YAMLSetConcentrations_F + END INTERFACE + integer, intent(in) :: id + real(kind=8), allocatable, dimension(:,:), intent(in) :: c + integer :: dim + dim = size(c,1)*size(c,2) + YAMLSetConcentrations = YAMLSetConcentrations_F(id, c(1,1), dim) + END FUNCTION YAMLSetConcentrations +!> Inserts data into the YAML document for the PhreeqcRM method SetCurrentSelectedOutputUserNumber. +!> When the YAML document is written to file it can be processed by the method InitializeYAML to +!> initialize a PhreeqcRM instance. +!> @param id The instance id returned from @ref CreateYAMLPhreeqcRM. +!> @param n_user User number of the SELECTED_OUTPUT data block that is to be used. +!> @retval IRM_RESULT Zero indicates success, negative indicates failure. +!> @par +!> SetCurrentSelectedOutputUserNumber selects the current selected output by user number. +!> The user may define multiple SELECTED_OUTPUT +!> data blocks for the workers. A user number is specified for each data block. The value of +!> the argument @a n_user selects which of the SELECTED_OUTPUT definitions will be used +!> for selected-output operations. +!> @see +!> @ref YAMLSetNthSelectedOutput, +!> @ref YAMLSetSelectedOutputOn. +!> @par Fortran Example: +!> @htmlonly +!> +!>
+!> status = YAMLSetCurrentSelectedOutputUserNumber(id, n_user)
+!> 
+!>
+!> @endhtmlonly + INTEGER FUNCTION YAMLSetCurrentSelectedOutputUserNumber(id, n) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION YAMLSetCurrentSelectedOutputUserNumber_F(id, n) & + BIND(C, NAME='YAMLSetCurrentSelectedOutputUserNumber_F') + USE ISO_C_BINDING + IMPLICIT NONE + integer(kind=C_INT), intent(in) :: id + integer(kind=C_INT), intent(in) :: n + END FUNCTION YAMLSetCurrentSelectedOutputUserNumber_F + END INTERFACE + integer, intent(in) :: id + integer, intent(in) :: n + YAMLSetCurrentSelectedOutputUserNumber = YAMLSetCurrentSelectedOutputUserNumber_F(id, n) + END FUNCTION YAMLSetCurrentSelectedOutputUserNumber +!> Inserts data into the YAML document for the PhreeqcRM method SetDensity. +!> When the YAML document is written to file it can be processed by the method InitializeYAML to +!> initialize a PhreeqcRM instance. +!> +!> @param id The instance id returned from @ref CreateYAMLPhreeqcRM. +!> @param density Vector of densities. Size of vector is @a nxyz, where @a nxyz is the number +!> of grid cells in the user's model. +!> @retval IRM_RESULT Zero indicates success, negative indicates failure. +!> @par +!> SetDensity sets the density for each reaction cell. These density values are used +!> when converting from transported mass-fraction concentrations (@ref YAMLSetUnitsSolution) to +!> produce per liter concentrations during a call to SetConcentrations. +!> They are also used when converting from reaction-cell concentrations to transport concentrations, +!> if UseSolutionDensityVolume is set to @a false. +!> +!> @see +!> @ref YAMLSetUnitsSolution, @ref YAMLUseSolutionDensityVolume. +!> @par Fortran Example: +!> @htmlonly +!> +!>
+!> real(kind=8), allocatable, dimension(:)   :: density
+!> allocate(density(nxyz))
+!> por = 1.0d0
+!> status = YAMLSetDensity(id, por)
+!> 
+!>
+!> @endhtmlonly + INTEGER FUNCTION YAMLSetDensity(id, density) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION YAMLSetDensity_F(id, density, dim) & + BIND(C, NAME='YAMLSetDensity_F') + USE ISO_C_BINDING + IMPLICIT NONE + integer(kind=C_INT), intent(in) :: id + real(kind=C_DOUBLE), intent(in) :: density + integer(kind=C_INT), intent(in) :: dim + END FUNCTION YAMLSetDensity_F + END INTERFACE + integer, intent(in) :: id + real(kind=8), allocatable, dimension(:), intent(in) :: density + YAMLSetDensity = YAMLSetDensity_F(id, density(1), size(density)) + END FUNCTION YAMLSetDensity +!> Inserts data into the YAML document for the PhreeqcRM method SetDumpFileName. +!> When the YAML document is written to file it can be processed by the method InitializeYAML to +!> initialize a PhreeqcRM instance. +!> @param id The instance id returned from @ref CreateYAMLPhreeqcRM. +!> @param dump_name Name of dump file. +!> @retval IRM_RESULT Zero indicates success, negative indicates failure. +!> @par +!> SetDumpFileName sets the name of the dump file. It is the name used by the method DumpModule. +!> @see @ref YAMLDumpModule. +!> @par Fortran Example: +!> @htmlonly +!> +!>
+!> logical dump_on, append
+!> status = YAMLSetDumpFileName(id, "Advect_cpp.dmp")
+!> dump_on = .true.
+!> append = .false.
+!> status = YAMLDumpModule(id, dump_on, append)
+!> 
+!>
+!> @endhtmlonly + INTEGER FUNCTION YAMLSetDumpFileName(id, file_name) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION YAMLSetDumpFileName_F(id, file_name) & + BIND(C, NAME='YAMLSetDumpFileName_F') + USE ISO_C_BINDING + IMPLICIT NONE + integer(kind=C_INT), intent(in) :: id + character(KIND=C_CHAR), intent(in) :: file_name(*) + END FUNCTION YAMLSetDumpFileName_F + END INTERFACE + integer, intent(in) :: id + character(len=*), intent(in) :: file_name + YAMLSetDumpFileName = YAMLSetDumpFileName_F(id, trim(file_name)//C_NULL_CHAR) + END FUNCTION YAMLSetDumpFileName +!> Inserts data into the YAML document for the PhreeqcRM method SetErrorHandlerMode. +!> When the YAML document is written to file it can be processed by the method InitializeYAML to +!> initialize a PhreeqcRM instance +!> @param id The instance id returned from @ref CreateYAMLPhreeqcRM. +!> @param mode Error handling mode: 0, 1, or 2. +!> @retval IRM_RESULT Zero indicates success, negative indicates failure. +!> @par +!> SetErrorHandlerMode sets the action to be taken when the reaction module encounters an error. +!> Options are 0, return to calling program with an error return code (default); +!> 1, throw an exception, in C++, the exception can be caught, for C and Fortran, the program will exit; or +!> 2, attempt to exit gracefully. +!> @par Fortran Example: +!> @htmlonly +!> +!>
+!> status = YAMLSetErrorHandlerMode(id, 1)
+!> 
+!>
+!> @endhtmlonly + INTEGER FUNCTION YAMLSetErrorHandlerMode(id, n) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION YAMLSetErrorHandlerMode_F(id, n) & + BIND(C, NAME='YAMLSetErrorHandlerMode_F') + USE ISO_C_BINDING + IMPLICIT NONE + integer(kind=C_INT), intent(in) :: id + integer(kind=C_INT), intent(in) :: n + END FUNCTION YAMLSetErrorHandlerMode_F + END INTERFACE + integer, intent(in) :: id + integer, intent(in) :: n + YAMLSetErrorHandlerMode = YAMLSetErrorHandlerMode_F(id, n) + END FUNCTION YAMLSetErrorHandlerMode +!> Inserts data into the YAML document for the PhreeqcRM method SetErrorOn. +!> When the YAML document is written to file it can be processed by the method InitializeYAML to +!> initialize a PhreeqcRM instance. +!> @param id The instance id returned from @ref CreateYAMLPhreeqcRM. +!> @param tf @a True, enable error messages; @a False, disable error messages. Default is true. +!> @retval IRM_RESULT Zero indicates success, negative indicates failure. +!> @par +!> SetErrorOn sets the property that controls whether error messages are generated and displayed. +!> Messages include PHREEQC "ERROR" messages, and +!> any messages written with the method ErrorMessage. +!> +!> @see @ref YAMLLogMessage, @ref YAMLOutputMessage, @ref YAMLScreenMessage. +!> @par Fortran Example: +!> @htmlonly +!> +!>
+!> status = YAMLSetErrorOn(id, .true.)
+!> 
+!>
+!> @endhtmlonly + INTEGER FUNCTION YAMLSetErrorOn(id, tf) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION YAMLSetErrorOn_F(id, itf) & + BIND(C, NAME='YAMLSetErrorOn_F') + USE ISO_C_BINDING + IMPLICIT NONE + integer(kind=C_INT), intent(in) :: id + integer(kind=C_INT), intent(in) :: itf + END FUNCTION YAMLSetErrorOn_F + END INTERFACE + integer, intent(in) :: id + logical, intent(in) :: tf + integer :: itf + itf = 0 + if (tf) itf = 1 + YAMLSetErrorOn = YAMLSetErrorOn_F(id, itf) + END FUNCTION YAMLSetErrorOn +!> Inserts data into the YAML document for the PhreeqcRM method SetFilePrefix. +!> When the YAML document is written to file it can be processed by the method InitializeYAML to +!> initialize a PhreeqcRM instance. +!> @param id The instance id returned from @ref CreateYAMLPhreeqcRM. +!> @param prefix Prefix used when opening the output and log files. +!> @retval IRM_RESULT Zero indicates success, negative indicates failure. +!> @par +!> SetFilePrefix sets the prefix for the output (prefix.chem.txt) and log (prefix.log.txt) files. +!> These files are opened by the method OpenFiles. +!> @see @ref YAMLOpenFiles, @ref YAMLCloseFiles. +!> @par Fortran Example: +!> @htmlonly +!> +!>
+!> status = YAMLSetFilePrefix(id, "Advect_cpp")
+!> status = YAMLOpenFiles(id)
+!> 
+!>
+!> @endhtmlonly + INTEGER FUNCTION YAMLSetFilePrefix(id, prefix) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION YAMLSetFilePrefix_F(id, prefix) & + BIND(C, NAME='YAMLSetFilePrefix_F') + USE ISO_C_BINDING + IMPLICIT NONE + integer(kind=C_INT), intent(in) :: id + character(KIND=C_CHAR), intent(in) :: prefix(*) + END FUNCTION YAMLSetFilePrefix_F + END INTERFACE + integer, intent(in) :: id + character(len=*), intent(in) :: prefix + YAMLSetFilePrefix = YAMLSetFilePrefix_F(id, trim(prefix)//C_NULL_CHAR) + END FUNCTION YAMLSetFilePrefix +!> Inserts data into the YAML document for the PhreeqcRM method SetGasCompMoles. +!> When the YAML document is written to file it can be processed by the method InitializeYAML to +!> initialize a PhreeqcRM instance. +!> @param id The instance id returned from @ref CreateYAMLPhreeqcRM. +!> @param gas_moles Vector of moles of gas components. +!> @retval IRM_RESULT Zero indicates success, negative indicates failure. +!> @par +!> SetGasCompMoles transfers moles of gas components from +!> the vector given in the argument list (@a gas_moles) to each reaction cell. +!> +!> Dimension of the vector is set to @a ngas_comps times @a nxyz, +!> where, @a ngas_comps is the result of GetGasComponentsCount, +!> and @a nxyz is the number of user grid cells. +!> If the number of moles is set to a negative number, the gas component will +!> not be defined for the GAS_PHASE of the reaction cell. +!> +!> @see +!> @ref YAMLFindComponents, +!> @ref YAMLSetGasPhaseVolume. +!> @par Fortran Example: +!> @htmlonly +!> +!>
+!> real(kind=8), allocatable, dimension(:,:) :: gas_moles
+!> allocate(gas_moles(nxyz*ngas))
+!> status = YAMLSetGasCompMoles(id, gas_moles)
+!> 
+!>
+!> @endhtmlonly + INTEGER FUNCTION YAMLSetGasCompMoles(id, gas_moles) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION YAMLSetGasCompMoles_F(id, gas_moles, dim) & + BIND(C, NAME='YAMLSetGasCompMoles_F') + USE ISO_C_BINDING + IMPLICIT NONE + integer(kind=C_INT), intent(in) :: id + real(kind=C_DOUBLE), intent(in) :: gas_moles + integer(kind=C_INT), intent(in) :: dim + END FUNCTION YAMLSetGasCompMoles_F + END INTERFACE + integer, intent(in) :: id + real(kind=8), allocatable, dimension(:,:), intent(in) :: gas_moles + integer :: dim + dim = size(gas_moles,1)*size(gas_moles,2) + YAMLSetGasCompMoles = YAMLSetGasCompMoles_F(id, gas_moles(1,1), dim) + END FUNCTION YAMLSetGasCompMoles +!> Inserts data into the YAML document for the PhreeqcRM method SetGasPhaseVolume. +!> When the YAML document is written to file it can be processed by the method InitializeYAML to +!> initialize a PhreeqcRM instance. +!> @param id The instance id returned from @ref CreateYAMLPhreeqcRM. +!> @param gas_volume Vector of volumes for each gas phase. +!> @retval IRM_RESULT Zero indicates success, negative indicates failure. +!> @par +!> SetGasPhaseVolume transfers volumes of gas phases from +!> the vector given in the argument list (@a gas_volume) to each reaction cell. +!> The gas-phase volume affects the gas-component pressures calculated for fixed-volume +!> gas phases. If a gas-phase volume is defined with this methood +!> for a GAS_PHASE in a cell, +!> the gas phase is forced to be a fixed-volume gas phase. +!> +!> Dimension of the vector is @a nxyz, +!> where @a nxyz is the number of user grid cells. +!> If the volume is set to a negative number for a cell, the gas-phase volume for that cell is +!> not changed. +!> +!> @see +!> @ref YAMLFindComponents, +!> @ref YAMLSetGasCompMoles. +!> @par Fortran Example: +!> @htmlonly +!> +!>
+!> real(kind=8), allocatable, dimension(:) :: gas_volume
+!> allocate(gas_volume(nxyz))
+!> status = YAMLSetGasPhaseVolume(id, gas_volume)
+!> 
+!>
+!> @endhtmlonly + INTEGER FUNCTION YAMLSetGasPhaseVolume(id, gas_volume) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION YAMLSetGasPhaseVolume_F(id, gas_volume, dim) & + BIND(C, NAME='YAMLSetGasPhaseVolume_F') + USE ISO_C_BINDING + IMPLICIT NONE + integer(kind=C_INT), intent(in) :: id + real(kind=C_DOUBLE), intent(in) :: gas_volume + integer(kind=C_INT), intent(in) :: dim + END FUNCTION YAMLSetGasPhaseVolume_F + END INTERFACE + integer, intent(in) :: id + real(kind=8), allocatable, dimension(:), intent(in) :: gas_volume + YAMLSetGasPhaseVolume = YAMLSetGasPhaseVolume_F(id, gas_volume(1), size(gas_volume)) + END FUNCTION YAMLSetGasPhaseVolume +!> Inserts data into the YAML document to define the number of cells in the user's model. +!> Once the YAML document is written, the number of model cells can be extracted +!> with the method GetGridCellCountYAML. GetGridCellCountYAML is NOT a PhreeqcRM +!> method; it is a global method and must be used BEFORE the PhreeqcRM instance +!> is created. SetGridCellCount will be ignored once the PhreeqcRM instance exists. +!> @param n Number of cells for the PhreeqcRM instance. The number of cells +!> @retval IRM_RESULT Zero indicates success, negative indicates failure. +!> can be used in the creation of the PhreeqcRM instance. The PhreeqcRM constructor +!> takes two arguments. GetGridCellCountYAML +!> provides the value for the first argument. If the YAML file does not contain the +!> node "SetGridCellCount:", GetGridCellCountYAML will return zero. +!> @par Fortran Example: +!> @htmlonly +!> +!>
+!> integer nxyz
+!> nxyz = 40
+!> status = YAMLSetGridCellCount(nxyz)
+!> 
+!>
+!> @endhtmlonly + INTEGER FUNCTION YAMLSetGridCellCount(id, n) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION YAMLSetGridCellCount_F(id, n) & + BIND(C, NAME='YAMLSetGridCellCount_F') + USE ISO_C_BINDING + IMPLICIT NONE + integer(kind=C_INT), intent(in) :: id + integer(kind=C_INT), intent(in) :: n + END FUNCTION YAMLSetGridCellCount_F + END INTERFACE + integer, intent(in) :: id + integer, intent(in) :: n + YAMLSetGridCellCount = YAMLSetGridCellCount_F(id, n) + END FUNCTION YAMLSetGridCellCount +!> Inserts data into the YAML document for the PhreeqcRM method SetNthSelectedOutput. +!> When the YAML document is written to file it can be processed by the method InitializeYAML to +!> initialize a PhreeqcRM instance. +!> @param id The instance id returned from @ref CreateYAMLPhreeqcRM. +!> @param n Sequence number of the SELECTED_OUTPUT data block that is to be used. +!> @retval IRM_RESULT Zero indicates success, negative indicates failure. +!> @par +!> SetNthSelectedOutput specifies the current selected output by sequence number (one-based). +!> The user may define multiple SELECTED_OUTPUT +!> data blocks for the workers. A user number is specified for each data block, and the blocks are +!> stored in user-number order. The value of +!> the argument @a n selects the sequence number of the SELECTED_OUTPUT definition that will be used +!> for selected-output operations. +!> @see +!> @ref YAMLSetCurrentSelectedOutputUserNumber, +!> @ref YAMLSetSelectedOutputOn. +!> @par Fortran Example: +!> @htmlonly +!> +!>
+!> status = YAMLSetCurrentSelectedOutput(id, 1)
+!> 
+!>
+!> @endhtmlonly + INTEGER FUNCTION YAMLSetNthSelectedOutput(id, n) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION YAMLSetNthSelectedOutput_F(id, n) & + BIND(C, NAME='YAMLSetNthSelectedOutput_F') + USE ISO_C_BINDING + IMPLICIT NONE + integer(kind=C_INT), intent(in) :: id + integer(kind=C_INT), intent(in) :: n + END FUNCTION YAMLSetNthSelectedOutput_F + END INTERFACE + integer, intent(in) :: id + integer, intent(in) :: n + YAMLSetNthSelectedOutput = YAMLSetNthSelectedOutput_F(id, n) + END FUNCTION YAMLSetNthSelectedOutput +!> Inserts data into the YAML document for the PhreeqcRM method SetPartitionUZSolids. +!> When the YAML document is written to file it can be processed by the method InitializeYAML to +!> initialize a PhreeqcRM instance. +!> @param id The instance id returned from @ref CreateYAMLPhreeqcRM. +!> @param tf @a True, the fraction of solids and gases available for +!> reaction is equal to the saturation; +!> @a False (default), all solids and gases are reactive regardless of saturation. +!> @retval IRM_RESULT Zero indicates success, negative indicates failure. +!> @par +!> SetPartitionUZSolids sets the property for partitioning solids between the +!> saturated and unsaturated parts of a partially saturated cell. +!> @par +!> The option is intended to be used by saturated-only +!> flow codes that allow a variable water table. +!> The value has meaning only when saturations +!> less than 1.0 are encountered. The partially saturated cells +!> may have a small water-to-rock ratio that causes +!> reactions to proceed differently relative to fully saturated cells. +!> By setting @a SetPartitionUZSolids to true, the +!> amounts of solids and gases are partioned according to the saturation. +!> If a cell has a saturation of 0.5, then +!> the water interacts with only half of the solids and gases; the other half is unreactive +!> until the water table rises. As the saturation in a cell varies, +!> solids and gases are transferred between the +!> saturated and unsaturated (unreactive) reservoirs of the cell. +!> Unsaturated-zone flow and transport codes will probably use the default (false), +!> which assumes all gases and solids are reactive regardless of saturation. +!> @par Fortran Example: +!> @htmlonly +!> +!>
+!> status = YAMLSetPartitionUZSolids(id, .false.)
+!> 
+!>
+!> @endhtmlonly + INTEGER FUNCTION YAMLSetPartitionUZSolids(id, tf) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION YAMLSetPartitionUZSolids_F(id, itf) & + BIND(C, NAME='YAMLSetPartitionUZSolids_F') + USE ISO_C_BINDING + IMPLICIT NONE + integer(kind=C_INT), intent(in) :: id + integer(kind=C_INT), intent(in) :: itf + END FUNCTION YAMLSetPartitionUZSolids_F + END INTERFACE + integer, intent(in) :: id + logical, intent(in) :: tf + integer :: itf + itf = 0 + if (tf) itf = 1 + YAMLSetPartitionUZSolids = YAMLSetPartitionUZSolids_F(id, itf) + END FUNCTION YAMLSetPartitionUZSolids +!> Inserts data into the YAML document for the PhreeqcRM method SetPorosity. +!> When the YAML document is written to file it can be processed by the method InitializeYAML to +!> initialize a PhreeqcRM instance. +!> @param id The instance id returned from @ref CreateYAMLPhreeqcRM. +!> @param por Vector of porosities, unitless. Default is 0.1. +!> @retval IRM_RESULT Zero indicates success, negative indicates failure. +!> @par +!> SetPorosity sets the porosity for each reaction cell. +!> The volume of water in a reaction cell is the product of porosity, saturation +!> (SetSaturation), and representative volume (SetRepresentativeVolume). +!> Size of vector is @a nxyz, where @a nxyz is the number +!> of grid cells in the user's model. +!> @see @ref YAMLSetRepresentativeVolume, @ref YAMLSetSaturation. +!> @par Fortran Example: +!> @htmlonly +!> +!>
+!> real(kind=8), allocatable, dimension(:) :: por
+!> allocate(por(nxyz))
+!> por = 0.2d0
+!> status = YAMLSetPorosity(id, por)
+!> 
+!>
+!> @endhtmlonly + INTEGER FUNCTION YAMLSetPorosity(id, por) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION YAMLSetPorosity_F(id, por, dim) & + BIND(C, NAME='YAMLSetPorosity_F') + USE ISO_C_BINDING + IMPLICIT NONE + integer(kind=C_INT), intent(in) :: id + real(kind=C_DOUBLE), intent(in) :: por + integer(kind=C_INT), intent(in) :: dim + END FUNCTION YAMLSetPorosity_F + END INTERFACE + integer, intent(in) :: id + real(kind=8), allocatable, dimension(:), intent(in) :: por + YAMLSetPorosity = YAMLSetPorosity_F(id, por(1), size(por)) + END FUNCTION YAMLSetPorosity +!> Inserts data into the YAML document for the PhreeqcRM method SetPressure. +!> When the YAML document is written to file it can be processed by the method InitializeYAML to +!> initialize a PhreeqcRM instance. +!> @param id The instance id returned from @ref CreateYAMLPhreeqcRM. +!> @param p Vector of pressures, in atm. Size of vector is @a nxyz, +!> where @a nxyz is the number of grid cells in the user's model. +!> @retval IRM_RESULT Zero indicates success, negative indicates failure. +!> @par +!> SetPressure sets the pressure for each reaction cell. Pressure effects are +!> considered only in three of the +!> databases distributed with PhreeqcRM: phreeqc.dat, Amm.dat, and pitzer.dat. +!> @see @ref YAMLSetTemperature. +!> @par Fortran Example: +!> @htmlonly +!> +!>
+!> real(kind=8), allocatable, dimension(:) :: pressure
+!> allocate(por(nxyz))
+!> pressure = 2.0d0
+!> status = YAMLSetPressure(id, pressure)
+!> 
+!>
+!> @endhtmlonly + INTEGER FUNCTION YAMLSetPressure(id, p) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION YAMLSetPressure_F(id, p, dim) & + BIND(C, NAME='YAMLSetPressure_F') + USE ISO_C_BINDING + IMPLICIT NONE + integer(kind=C_INT), intent(in) :: id + real(kind=C_DOUBLE), intent(in) :: p + integer(kind=C_INT), intent(in) :: dim + END FUNCTION YAMLSetPressure_F + END INTERFACE + integer, intent(in) :: id + real(kind=8), allocatable, dimension(:), intent(in) :: p + YAMLSetPressure = YAMLSetPressure_F(id, p(1), size(p)) + END FUNCTION YAMLSetPressure +!> Inserts data into the YAML document for the PhreeqcRM method SetPrintChemistryMask. +!> When the YAML document is written to file it can be processed by the method InitializeYAML to +!> initialize a PhreeqcRM instance. +!> @param id The instance id returned from @ref CreateYAMLPhreeqcRM. +!> @param cell_mask Vector of integers. Size of vector is @a nxyz, where @a nxyz is the number +!> of grid cells in the user's model. A value of 0 will +!> disable printing detailed output for the cell; a value of 1 will enable printing detailed output for a cell. +!> @retval IRM_RESULT Zero indicates success, negative indicates failure. +!> @par +!> SetPrintChemistryMask enables or disables detailed output for each reaction cell. +!> Printing for a reaction cell will occur only when the +!> printing is enabled with SetPrintChemistryOn and the @a cell_mask value is 1. +!> @see @ref YAMLSetPrintChemistryOn. +!> @par Fortran Example: +!> @htmlonly +!> +!>
+!> integer, allocatable, dimension(:) :: print_chemistry_mask;
+!> allocate(print_chemistry_mask(nxyz))
+!> print_chemistry_mask = 0
+!> do i = 1, nxyz / 2 
+!> 	print_chemistry_mask(i) = 1
+!> enddo
+!> status = YAMLSetPrintChemistryMask(id, print_chemistry_mask)  
+!> 
+!>
+!> @endhtmlonly + INTEGER FUNCTION YAMLSetPrintChemistryMask(id, mask) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION YAMLSetPrintChemistryMask_F(id, mask, dim) & + BIND(C, NAME='YAMLSetPrintChemistryMask_F') + USE ISO_C_BINDING + IMPLICIT NONE + integer(kind=C_INT), intent(in) :: id + integer(kind=C_INT), intent(in) :: mask + integer(kind=C_INT), intent(in) :: dim + END FUNCTION YAMLSetPrintChemistryMask_F + END INTERFACE + integer, intent(in) :: id + integer, allocatable, dimension(:), intent(in) :: mask + YAMLSetPrintChemistryMask = YAMLSetPrintChemistryMask_F(id, mask(1), size(mask)) + END FUNCTION YAMLSetPrintChemistryMask +!> Inserts data into the YAML document for the PhreeqcRM method SetPrintChemistryOn. +!> When the YAML document is written to file it can be processed by the method InitializeYAML to +!> initialize a PhreeqcRM instance. +!> @param id The instance id returned from @ref CreateYAMLPhreeqcRM. +!> @param workers @a True, enable detailed printing in the worker instances; +!> @a False, disable detailed printing in the worker instances. +!> @param initial_phreeqc @a True, enable detailed printing in the InitialPhreeqc instance; +!> @a False, disable detailed printing in the InitialPhreeqc instance. +!> @param utility @a True, enable detailed printing in the Utility instance; +!> @a False, disable detailed printing in the Utility instance. +!> @retval IRM_RESULT Zero indicates success, negative indicates failure. +!> @par +!> SetPrintChemistryOn +!> sets the property that enables or disables printing detailed output from reaction calculations +!> to the output file for a set of cells defined by SetPrintChemistryMask. +!> The detailed output prints all of the output typical of a PHREEQC reaction calculation, +!> which includes solution descriptions and the compositions of all other reactants. +!> The output can be several hundred lines per cell, which can lead to a very +!> large output file (prefix.chem.txt opened by the method OpenFiles). +!> For the worker instances, the output can be limited to a set of cells +!> (method SetPrintChemistryMask) and, in general, the +!> amount of information printed can be limited by use of options in the PRINT data block of PHREEQC +!> (applied by using methods RunFile or RunString). +!> Printing the detailed output for the workers is generally used only for debugging, +!> and PhreeqcRM will run significantly faster +!> when printing detailed output for the workers is disabled. +!> @see @ref YAMLOpenFiles, @ref YAMLRunFile, @ref YAMLRunString, +!> @ref YAMLSetPrintChemistryMask. +!> @par Fortran Example: +!> @htmlonly +!> +!>
+!> status = YAMLSetPrintChemistryOn(id, .false., .true., .false.)
+!> 
+!>
+!> @endhtmlonly + INTEGER FUNCTION YAMLSetPrintChemistryOn(id, workers, initial_phreeqc, utility) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION YAMLSetPrintChemistryOn_F(id, iworkers, iinitial_phreeqc, iutility) & + BIND(C, NAME='YAMLSetPrintChemistryOn_F') + USE ISO_C_BINDING + IMPLICIT NONE + integer(kind=C_INT), intent(in) :: id + integer(kind=C_INT), intent(in) :: iworkers, iinitial_phreeqc, iutility + END FUNCTION YAMLSetPrintChemistryOn_F + END INTERFACE + integer, intent(in) :: id + logical, intent(in) :: workers, initial_phreeqc, utility + integer :: iworkers, iinitial_phreeqc, iutility + iworkers = 0 + iinitial_phreeqc = 0 + iutility = 0 + if (workers) iworkers = 1 + if (initial_phreeqc) iinitial_phreeqc = 1 + if (utility) iutility = 1 + YAMLSetPrintChemistryOn = YAMLSetPrintChemistryOn_F(id, iworkers, iinitial_phreeqc, iutility) + END FUNCTION YAMLSetPrintChemistryOn +!> Inserts data into the YAML document for the PhreeqcRM method SetRebalanceByCell. +!> When the YAML document is written to file it can be processed by the method InitializeYAML to +!> initialize a PhreeqcRM instance. +!> @param id The instance id returned from @ref CreateYAMLPhreeqcRM. +!> @param tf @a True, indicates individual cell times are used in rebalancing (default); +!> @a False, indicates average times are used in rebalancing. +!> @retval IRM_RESULT Zero indicates success, negative indicates failure. +!> @par +!> SetRebalanceByCell +!> sets the load-balancing algorithm. +!> PhreeqcRM attempts to rebalance the load of each thread or process such that each +!> thread or process takes the same amount of time to run its part of a RunCells +!> calculation. Two algorithms are available; one uses individual times for each cell and +!> accounts for cells that were not run because +!> saturation was zero (default), and +!> the other assigns an average time to all cells. +!> The methods are similar, but limited testing indicates the default method performs better. +!> @see @ref YAMLSetRebalanceFraction. +!> @par Fortran Example: +!> @htmlonly +!> +!>
+!> status = YAMLSetRebalanceByCell(id, .true.)
+!> 
+!>
+!> @endhtmlonly + INTEGER FUNCTION YAMLSetRebalanceByCell(id, tf) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION YAMLSetRebalanceByCell_F(id, itf) & + BIND(C, NAME='YAMLSetRebalanceByCell_F') + USE ISO_C_BINDING + IMPLICIT NONE + integer(kind=C_INT), intent(in) :: id + integer(kind=C_INT), intent(in) :: itf + END FUNCTION YAMLSetRebalanceByCell_F + END INTERFACE + integer, intent(in) :: id + logical, intent(in) :: tf + integer :: itf + itf = 0 + if (tf) itf = 1 + YAMLSetRebalanceByCell = YAMLSetRebalanceByCell_F(id, itf) + END FUNCTION YAMLSetRebalanceByCell +!> Inserts data into the YAML document for the PhreeqcRM method SetRebalanceFraction. +!> When the YAML document is written to file it can be processed by the method InitializeYAML to +!> initialize a PhreeqcRM instance. +!> @param id The instance id returned from @ref CreateYAMLPhreeqcRM. +!> @param f Fraction from 0.0 to 1.0. +!> @retval IRM_RESULT Zero indicates success, negative indicates failure. +!> @par +!> SetRebalanceFraction sets the fraction of cells that are transferred +!> among threads or processes when rebalancing. +!> PhreeqcRM attempts to rebalance the load of each thread or process such that each +!> thread or process takes the same amount of time to run its part of a RunCells +!> calculation. The rebalancing transfers cell calculations among threads or processes to +!> try to achieve an optimum balance. @a SetRebalanceFraction +!> adjusts the calculated optimum number of cell transfers by a fraction from 0 to 1.0 to +!> determine the actual number of cell transfers. A value of zero eliminates +!> load rebalancing. A value less than 1.0 is suggested to slow the approach to the optimum cell +!> distribution and avoid possible oscillations +!> when too many cells are transferred at one iteration, requiring reverse transfers +!> at the next iteration. Default is 0.5. +!> +!> @see @ref YAMLSetRebalanceByCell. +!> +!> @par Fortran Example: +!> @htmlonly +!> +!>
+!> status = YAMLSetRebalanceFraction(id, 0.5)
+!> 
+!>
+!> @endhtmlonly + INTEGER FUNCTION YAMLSetRebalanceFraction(id, f) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION YAMLSetRebalanceFraction_F(id, f) & + BIND(C, NAME='YAMLSetRebalanceFraction_F') + USE ISO_C_BINDING + IMPLICIT NONE + integer(kind=C_INT), intent(in) :: id + real(kind=C_DOUBLE), intent(in) :: f + END FUNCTION YAMLSetRebalanceFraction_F + END INTERFACE + integer, intent(in) :: id + real(kind=8), intent(in) :: f + YAMLSetRebalanceFraction = YAMLSetRebalanceFraction_F(id, f) + END FUNCTION YAMLSetRebalanceFraction +!> Inserts data into the YAML document for the PhreeqcRM method SetRepresentativeVolume. +!> When the YAML document is written to file it can be processed by the method InitializeYAML to +!> initialize a PhreeqcRM instance. +!> @param id The instance id returned from @ref CreateYAMLPhreeqcRM. +!> @param rv Vector of representative volumes, in liters. Default is 1.0 liter. +!> Size of array is @a nxyz, where @a nxyz is the number +!> of grid cells in the user's model. +!> @retval IRM_RESULT Zero indicates success, negative indicates failure. +!> @par +!> SetRepresentativeVolume +!> sets the representative volume of each reaction cell. +!> By default the representative volume of each reaction cell is 1 liter. +!> The volume of water in a reaction cell is determined by the product of the representative volume, +!> the porosity (SetPorosity), and the saturation (SetSaturation). +!> The numerical method of PHREEQC is more robust if the water volume for a reaction cell is +!> within a couple orders of magnitude of 1.0. +!> Small water volumes caused by small porosities and (or) small saturations +!> (and (or) small representative volumes) +!> may cause non-convergence of the numerical method. +!> In these cases, a larger representative volume may help. Note +!> that increasing the representative volume also increases +!> the number of moles of the reactants in the reaction cell (minerals, surfaces, exchangers, +!> and others), which are defined as moles per representative volume. +!> @a SetRepresentativeVolume should be called before initial conditions +!> are defined for the reaction cells. +!> +!> @see @ref YAMLSetPorosity, @ref YAMLSetSaturation. +!> @par Fortran Example: +!> @htmlonly +!> +!>
+!> real(kind=8), allocatable, dimension(:)   :: rv
+!> allocate(rv(nxyz))
+!> rv = 1.0d0
+!> status = YAMLSetRepresentativeVolume(id, rv)
+!> 
+!>
+!> @endhtmlonly + INTEGER FUNCTION YAMLSetRepresentativeVolume(id, rv) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION YAMLSetRepresentativeVolume_F(id, rv, dim) & + BIND(C, NAME='YAMLSetRepresentativeVolume_F') + USE ISO_C_BINDING + IMPLICIT NONE + integer(kind=C_INT), intent(in) :: id + real(kind=C_DOUBLE), intent(in) :: rv + integer(kind=C_INT), intent(in) :: dim + END FUNCTION YAMLSetRepresentativeVolume_F + END INTERFACE + integer, intent(in) :: id + real(kind=8), allocatable, dimension(:), intent(in) :: rv + YAMLSetRepresentativeVolume = YAMLSetRepresentativeVolume_F(id, rv(1), size(rv)) + END FUNCTION YAMLSetRepresentativeVolume +!> Inserts data into the YAML document for the PhreeqcRM method SetSaturation. +!> When the YAML document is written to file it can be processed by the method InitializeYAML to +!> initialize a PhreeqcRM instance. +!> @param id The instance id returned from @ref CreateYAMLPhreeqcRM. +!> @param sat Vector of saturations, unitless. Default 1.0. Size of vector is @a nxyz, +!> where @a nxyz is the number of grid cells in the user's model. +!> @retval IRM_RESULT Zero indicates success, negative indicates failure. +!> @par +!> SetSaturation +!> sets the saturation of each reaction cell. Saturation is a fraction ranging from 0 to 1. +!> The volume of water in a cell is the product of porosity (SetPorosity), saturation (SetSaturation), +!> and representative volume (SetRepresentativeVolume). As a result of a reaction calculation, +!> solution properties (density and volume) will change; +!> the databases phreeqc.dat, Amm.dat, and pitzer.dat have the molar +!> volume data to calculate these changes. The methods GetDensity, +!> GetSolutionVolume, and GetSaturation can be used to account +!> for these changes in the succeeding transport calculation. +!> +!> @param sat Vector of saturations, unitless. Default 1.0. Size of vector is @a nxyz, +!> where @a nxyz is the number of grid cells in the user's model. +!> @see +!> @ref YAMLSetPorosity, @ref YAMLSetRepresentativeVolume. +!> @par Fortran Example: +!> @htmlonly +!> +!>
   
+!> real(kind=8), allocatable, dimension(:) :: sat 
+!> allocate(sat(nxyz))
+!> sat = 1.0d0
+!> status = YAMLSetSaturation(id, sat)  
+!> 
+!>
+!> @endhtmlonly + INTEGER FUNCTION YAMLSetSaturation(id, sat) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION YAMLSetSaturation_F(id, sat, dim) & + BIND(C, NAME='YAMLSetSaturation_F') + USE ISO_C_BINDING + IMPLICIT NONE + integer(kind=C_INT), intent(in) :: id + real(kind=C_DOUBLE), intent(in) :: sat + integer(kind=C_INT), intent(in) :: dim + END FUNCTION YAMLSetSaturation_F + END INTERFACE + integer, intent(in) :: id + real(kind=8), allocatable, dimension(:), intent(in) :: sat + YAMLSetSaturation = YAMLSetSaturation_F(id, sat(1), size(sat)) + END FUNCTION YAMLSetSaturation +!> Inserts data into the YAML document for the PhreeqcRM method SetScreenOn. +!> When the YAML document is written to file it can be processed by the method InitializeYAML to +!> initialize a PhreeqcRM instance. +!> @param id The instance id returned from @ref CreateYAMLPhreeqcRM. +!> @param tf @a True, enable screen messages; @a False, disable screen messages. Default is true. +!> @retval IRM_RESULT Zero indicates success, negative indicates failure. +!> @par +!> SetScreenOn +!> sets the property that controls whether messages are written to the screen. +!> Messages include information about rebalancing during RunCells, and +!> any messages written with ScreenMessage. +!> +!> @see @ref YAMLRunCells, @ref YAMLScreenMessage. +!> @par Fortran Example: +!> @htmlonly +!> +!>
+!> status = YAMLSetScreenOn(id, .true.)
+!> 
+!>
+!> @endhtmlonly + INTEGER FUNCTION YAMLSetScreenOn(id, tf) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION YAMLSetScreenOn_F(id, itf) & + BIND(C, NAME='YAMLSetScreenOn_F') + USE ISO_C_BINDING + IMPLICIT NONE + integer(kind=C_INT), intent(in) :: id + integer(kind=C_INT), intent(in) :: itf + END FUNCTION YAMLSetScreenOn_F + END INTERFACE + integer, intent(in) :: id + logical, intent(in) :: tf + integer :: itf + itf = 0 + if (tf) itf = 1 + YAMLSetScreenOn = YAMLSetScreenOn_F(id, itf) + END FUNCTION YAMLSetScreenOn +!> Inserts data into the YAML document for the PhreeqcRM method SetSelectedOutputOn. +!> When the YAML document is written to file it can be processed by the method InitializeYAML to +!> initialize a PhreeqcRM instance. +!> @param id The instance id returned from @ref CreateYAMLPhreeqcRM. +!> @param tf @a True, enable selected output; @a False, disable selected output. +!> @retval IRM_RESULT Zero indicates success, negative indicates failure. +!> @par +!> SetSelectedOutputOn +!> sets the property that controls whether selected-output results are available to be retrieved +!> with GetSelectedOutput. @a True indicates that selected-output results +!> will be accumulated during RunCells and can be retrieved with GetSelectedOutput; +!> @a False indicates that selected-output results will not +!> be accumulated during RunCells. +!> +!> @see +!> @ref YAMLSetCurrentSelectedOutputUserNumber, +!> @ref YAMLSetNthSelectedOutput, +!> @ref YAMLSetSelectedOutputOn. +!> @par Fortran Example: +!> @htmlonly +!> +!>
+!> status = YAMLSetSelectedOutputOn(id, .true.)
+!> 
+!>
+!> @endhtmlonly + INTEGER FUNCTION YAMLSetSelectedOutputOn(id, tf) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION YAMLSetSelectedOutputOn_F(id, itf) & + BIND(C, NAME='YAMLSetSelectedOutputOn_F') + USE ISO_C_BINDING + IMPLICIT NONE + integer(kind=C_INT), intent(in) :: id + integer(kind=C_INT), intent(in) :: itf + END FUNCTION YAMLSetSelectedOutputOn_F + END INTERFACE + integer, intent(in) :: id + logical, intent(in) :: tf + integer :: itf + itf = 0 + if (tf) itf = 1 + YAMLSetSelectedOutputOn = YAMLSetSelectedOutputOn_F(id, itf) + END FUNCTION YAMLSetSelectedOutputOn +!> Inserts data into the YAML document for the PhreeqcRM method SetSpeciesSaveOn. +!> When the YAML document is written to file it can be processed by the method InitializeYAML to +!> initialize a PhreeqcRM instance. +!> @param id The instance id returned from @ref CreateYAMLPhreeqcRM. +!> @param save_on @a True indicates species concentrations are saved; +!> @a False indicates species concentrations are not saved. +!> @retval IRM_RESULT Zero indicates success, negative indicates failure. +!> @par +!> SetSpeciesSaveOn +!> sets the value of the species-save property. +!> This method enables or disables use of PhreeqcRM with multicomponent-diffusion transport calculations. +!> By default, concentrations of aqueous species are not saved. +!> Setting the species-save property to @a true allows +!> aqueous species concentrations to be retrieved +!> with GetSpeciesConcentrations, and solution compositions to be set with +!> SpeciesConcentrations2Module. +!> SetSpeciesSaveOn must be called before calls to FindComponents. +!> +!> @see @ref YAMLFindComponents, +!> @ref YAMLSpeciesConcentrations2Module. +!> @par Fortran Example: +!> @htmlonly +!> +!>
+!> status = YAMLSetSpeciesSaveOn(id, .true.)
+!> 
+!>
+!> @endhtmlonly + INTEGER FUNCTION YAMLSetSpeciesSaveOn(id, tf) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION YAMLSetSpeciesSaveOn_F(id, itf) & + BIND(C, NAME='YAMLSetSpeciesSaveOn_F') + USE ISO_C_BINDING + IMPLICIT NONE + integer(kind=C_INT), intent(in) :: id + integer(kind=C_INT), intent(in) :: itf + END FUNCTION YAMLSetSpeciesSaveOn_F + END INTERFACE + integer, intent(in) :: id + logical(kind=4), intent(in) :: tf + integer :: itf + itf = 0 + if (tf) itf = 1 + YAMLSetSpeciesSaveOn = YAMLSetSpeciesSaveOn_F(id, itf) + END FUNCTION YAMLSetSpeciesSaveOn +!> Inserts data into the YAML document for the PhreeqcRM method SetTemperature. +!> When the YAML document is written to file it can be processed by the method InitializeYAML to +!> initialize a PhreeqcRM instance. +!> @param id The instance id returned from @ref CreateYAMLPhreeqcRM. +!> @param tc Vector of temperatures, in degrees C. +!> @retval IRM_RESULT Zero indicates success, negative indicates failure. +!> @par +!> SetTemperature +!> sets the temperature for each reaction cell. If SetTemperature is not called, +!> worker solutions will have temperatures as defined by initial conditions +!> (InitialPhreeqc2Module and InitialPhreeqcCell2Module). +!> Size of vector is @a nxyz, where @a nxyz is the number +!> of grid cells in the user's model. +!> @see @ref YAMLInitialPhreeqc2Module, +!> @ref YAMLInitialPhreeqcCell2Module, @ref YAMLSetPressure. +!> +!> @par Fortran Example: +!> @htmlonly +!> +!>
    
+!> real(kind=8), allocatable, dimension(:) :: tc
+!> allocate(tc(nxyz))
+!> por = 0.2d0
+!> status = YAMLSetTemperature(id, tc)
+!> 
+!>
+!> @endhtmlonly + INTEGER FUNCTION YAMLSetTemperature(id, tc) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION YAMLSetTemperature_F(id, tc, dim) & + BIND(C, NAME='YAMLSetTemperature_F') + USE ISO_C_BINDING + IMPLICIT NONE + integer(kind=C_INT), intent(in) :: id + real(kind=C_DOUBLE), intent(in) :: tc + integer(kind=C_INT), intent(in) :: dim + END FUNCTION YAMLSetTemperature_F + END INTERFACE + integer, intent(in) :: id + real(kind=8), allocatable, dimension(:), intent(in) :: tc + YAMLSetTemperature = YAMLSetTemperature_F(id, tc(1), size(tc)) + END FUNCTION YAMLSetTemperature +!> Inserts data into the YAML document for the PhreeqcRM method SetTime. +!> When the YAML document is written to file it can be processed by the method InitializeYAML to +!> initialize a PhreeqcRM instance. +!> @param id The instance id returned from @ref CreateYAMLPhreeqcRM. +!> @param time Current simulation time, in seconds. +!> @retval IRM_RESULT Zero indicates success, negative indicates failure. +!> @par +!> SetTime +!> sets current simulation time for the reaction module. +!> @see @ref YAMLSetTimeStep, @ref YAMLSetTimeConversion. +!> @par Fortran Example: +!> @htmlonly +!> +!>
+!> status = YAMLSetTime(id, 0.0)
+!> 
+!>
+!> @endhtmlonly + INTEGER FUNCTION YAMLSetTime(id, time) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION YAMLSetTime_F(id, time) & + BIND(C, NAME='YAMLSetTime_F') + USE ISO_C_BINDING + IMPLICIT NONE + integer(kind=C_INT), intent(in) :: id + real(kind=C_DOUBLE), intent(in) :: time + END FUNCTION YAMLSetTime_F + END INTERFACE + integer, intent(in) :: id + real(kind=8), intent(in) :: time + YAMLSetTime = YAMLSetTime_F(id, time) + END FUNCTION YAMLSetTime +!> Inserts data into the YAML document for the PhreeqcRM method SetTimeConversion. +!> When the YAML document is written to file it can be processed by the method InitializeYAML to +!> initialize a PhreeqcRM instance. +!> @param id The instance id returned from @ref CreateYAMLPhreeqcRM. +!> @param conv_factor Factor to convert seconds to user time units. +!> @retval IRM_RESULT Zero indicates success, negative indicates failure. +!> @par +!> SetTimeConversion +!> Set a factor to convert from seconds to user time units. Factor times seconds produces user time units +!> that is used in some PhreeqcRM printing. +!> +!> @see @ref YAMLSetTime, @ref YAMLSetTimeStep. +!> @par Fortran Example: +!> @htmlonly +!> +!>
+!> time_conversion = 1.0d0 / 86400.d0
+!> status = YAMLSetTimeConversion(id, time_conversion)
+!> 
+!>
+!> @endhtmlonly + INTEGER FUNCTION YAMLSetTimeConversion(id, conv) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION YAMLSetTimeConversion_F(id, conv) & + BIND(C, NAME='YAMLSetTimeConversion_F') + USE ISO_C_BINDING + IMPLICIT NONE + integer(kind=C_INT), intent(in) :: id + real(kind=C_DOUBLE), intent(in) :: conv + END FUNCTION YAMLSetTimeConversion_F + END INTERFACE + integer, intent(in) :: id + real(kind=8), intent(in) :: conv + YAMLSetTimeConversion = YAMLSetTimeConversion_F(id, conv) + END FUNCTION YAMLSetTimeConversion +!> Inserts data into the YAML document for the PhreeqcRM method SetTimeStep. +!> When the YAML document is written to file it can be processed by the method InitializeYAML to +!> initialize a PhreeqcRM instance. +!> @param id The instance id returned from @ref CreateYAMLPhreeqcRM. +!> @param time_step Time step, in seconds. +!> @retval IRM_RESULT Zero indicates success, negative indicates failure. +!> @par +!> SetTimeStep +!> sets current time step for the reaction module. This is the length +!> of time over which kinetic reactions are integrated. +!> +!> @see @ref YAMLSetTime, @ref YAMLSetTimeConversion. +!> @par Fortran Example: +!> @htmlonly +!> +!>
+!> time_step = 86400.d0
+!> status = YAMLSetTimeStep(time_step)
+!> 
+!>
+!> @endhtmlonly + INTEGER FUNCTION YAMLSetTimeStep(id, time) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION YAMLSetTimeStep_F(id, time) & + BIND(C, NAME='YAMLSetTimeStep_F') + USE ISO_C_BINDING + IMPLICIT NONE + integer(kind=C_INT), intent(in) :: id + real(kind=C_DOUBLE), intent(in) :: time + END FUNCTION YAMLSetTimeStep_F + END INTERFACE + integer, intent(in) :: id + real(kind=8), intent(in) :: time + YAMLSetTimeStep = YAMLSetTimeStep_F(id, time) + END FUNCTION YAMLSetTimeStep +!> Inserts data into the YAML document for the PhreeqcRM method SetUnitsExchange. +!> When the YAML document is written to file it can be processed by the method InitializeYAML to +!> initialize a PhreeqcRM instance. +!> @param id The instance id returned from @ref CreateYAMLPhreeqcRM. +!> @param option Units option for exchangers: 0, 1, or 2. +!> @retval IRM_RESULT Zero indicates success, negative indicates failure. +!> @par +!> SetUnitsExchange +!> sets input units for exchangers. +!> In PHREEQC input, exchangers are defined by moles of exchange sites (@a Mp). +!> SetUnitsExchange specifies how the number of moles of exchange sites in a reaction cell (@a Mc) +!> is calculated from the input value (@a Mp). +!> @par +!> Options are +!> 0, @a Mp is mol/L of RV (default), @a Mc = @a Mp*RV, where RV is the representative volume (SetRepresentativeVolume); +!> 1, @a Mp is mol/L of water in the RV, @a Mc = @a Mp*P*RV, where @a P is porosity (SetPorosity); or +!> 2, @a Mp is mol/L of rock in the RV, @a Mc = @a Mp*(1-P)*RV. +!> @par +!> If a single EXCHANGE definition is used for cells with different initial porosity, +!> the three options scale quite differently. +!> For option 0, the number of moles of exchangers will be the same regardless of porosity. +!> For option 1, the number of moles of exchangers will be vary directly with porosity and inversely with rock volume. +!> For option 2, the number of moles of exchangers will vary directly with rock volume and inversely with porosity. +!> +!> @see @ref YAMLInitialPhreeqc2Module, @ref YAMLInitialPhreeqcCell2Module, +!> @ref YAMLSetPorosity, @ref YAMLSetRepresentativeVolume. +!> @par Fortran Example: +!> @htmlonly +!> +!>
+!> status = YAMLSetUnitsExchange(id, 1)
+!> 
+!>
+!> @endhtmlonly + INTEGER FUNCTION YAMLSetUnitsExchange(id, option) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION YAMLSetUnitsExchange_F(id, option) & + BIND(C, NAME='YAMLSetUnitsExchange_F') + USE ISO_C_BINDING + IMPLICIT NONE + integer(kind=C_INT), intent(in) :: id + integer(kind=C_INT), intent(in) :: option + END FUNCTION YAMLSetUnitsExchange_F + END INTERFACE + integer, intent(in) :: id + integer, intent(in) :: option + YAMLSetUnitsExchange = YAMLSetUnitsExchange_F(id, option) + END FUNCTION YAMLSetUnitsExchange +!> Inserts data into the YAML document for the PhreeqcRM method SetUnitsGasPhase. +!> When the YAML document is written to file it can be processed by the method InitializeYAML to +!> initialize a PhreeqcRM instance. +!> @param id The instance id returned from @ref CreateYAMLPhreeqcRM. +!> @param option Units option for gas phases: 0, 1, or 2. +!> @retval IRM_RESULT Zero indicates success, negative indicates failure. +!> @par +!> SetUnitsGasPhase +!> sets input units for gas phases. +!> In PHREEQC input, gas phases are defined by moles of component gases (@a Mp). +!> @a SetUnitsGasPhase specifies how the number of moles of component gases in a reaction cell (@a Mc) +!> is calculated from the input value (@a Mp). +!> @par +!> Options are +!> 0, @a Mp is mol/L of RV (default), @a Mc = @a Mp*RV, where RV is the representative volume (SetRepresentativeVolume); +!> 1, @a Mp is mol/L of water in the RV, @a Mc = @a Mp*P*RV, where @a P is porosity (SetPorosity); or +!> 2, @a Mp is mol/L of rock in the RV, @a Mc = @a Mp*(1-@a P)*RV. +!> @par +!> If a single GAS_PHASE definition is used for cells with different initial porosity, +!> the three options scale quite differently. +!> For option 0, the number of moles of a gas component will be the same regardless of porosity. +!> For option 1, the number of moles of a gas component will be vary directly with porosity and inversely with rock volume. +!> For option 2, the number of moles of a gas component will vary directly with rock volume and inversely with porosity. +!> +!> @see @ref YAMLInitialPhreeqc2Module, @ref YAMLInitialPhreeqcCell2Module, +!> @ref YAMLSetPorosity, @ref YAMLSetRepresentativeVolume. +!> +!> @par Fortran Example: +!> @htmlonly +!> +!>
+!> status = YAMLSetUnitsGasPhase(id, 1)
+!> 
+!>
+!> @endhtmlonly + INTEGER FUNCTION YAMLSetUnitsGasPhase(id, option) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION YAMLSetUnitsGasPhase_F(id, option) & + BIND(C, NAME='YAMLSetUnitsGasPhase_F') + USE ISO_C_BINDING + IMPLICIT NONE + integer(kind=C_INT), intent(in) :: id + integer(kind=C_INT), intent(in) :: option + END FUNCTION YAMLSetUnitsGasPhase_F + END INTERFACE + integer, intent(in) :: id + integer, intent(in) :: option + YAMLSetUnitsGasPhase = YAMLSetUnitsGasPhase_F(id, option) + END FUNCTION YAMLSetUnitsGasPhase +!> Inserts data into the YAML document for the PhreeqcRM method SetUnitsKinetics. +!> When the YAML document is written to file it can be processed by the method InitializeYAML to +!> initialize a PhreeqcRM instance. +!> @param id The instance id returned from @ref CreateYAMLPhreeqcRM. +!> @param option Units option for kinetic reactants: 0, 1, or 2. +!> @retval IRM_RESULT Zero indicates success, negative indicates failure. +!> @par +!> SetUnitsKinetics +!> sets input units for kinetic reactants. +!> @par +!> In PHREEQC input, kinetics are defined by moles of kinetic reactants (@a Mp). +!> @a SetUnitsKinetics specifies how the number of moles of kinetic reactants in a reaction cell (@a Mc) +!> is calculated from the input value (@a Mp). +!> @par +!> Options are +!> 0, @a Mp is mol/L of RV (default), @a Mc = @a Mp*RV, where RV is the representative volume (SetRepresentativeVolume); +!> 1, @a Mp is mol/L of water in the RV, @a Mc = @a Mp*P*RV, where @a P is porosity (SetPorosity); or +!> 2, @a Mp is mol/L of rock in the RV, @a Mc = @a Mp*(1-@a P)*RV. +!> @par +!> If a single KINETICS definition is used for cells with different initial porosity, +!> the three options scale quite differently. +!> For option 0, the number of moles of kinetic reactants will be the same regardless of porosity. +!> For option 1, the number of moles of kinetic reactants will be vary directly with porosity and inversely with rock volume. +!> For option 2, the number of moles of kinetic reactants will vary directly with rock volume and inversely with porosity. +!> @par +!> Note that the volume of water in a cell in the reaction module is equal to the product of +!> porosity (SetPorosity), the saturation (SetSaturation), and representative volume (SetRepresentativeVolume), +!> which is usually less than 1 liter. It is important to write the RATES +!> definitions for homogeneous (aqueous) kinetic reactions to account for the current volume of +!> water, often by calculating the rate of reaction per liter of water and multiplying by the volume +!> of water (Basic function SOLN_VOL). +!> @par +!> Rates that depend on surface area of solids, are not dependent +!> on the volume of water. However, it is important to get the correct surface area for the kinetic +!> reaction. To scale the surface area with the number of moles, the specific area (m^2 per mole of reactant) +!> can be defined as a parameter (KINETICS; -parm), which is multiplied by the number of moles of +!> reactant (Basic function M) in RATES to obtain the surface area. +!> +!> @see @ref YAMLInitialPhreeqc2Module, @ref YAMLInitialPhreeqcCell2Module, +!> @ref YAMLSetPorosity, @ref YAMLSetRepresentativeVolume, @ref YAMLSetSaturation. +!> +!> @par Fortran Example: +!> @htmlonly +!> +!>
+!> status = YAMLSetUnitsKinetics(id, 1)
+!> 
+!>
+!> @endhtmlonly + INTEGER FUNCTION YAMLSetUnitsKinetics(id, option) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION YAMLSetUnitsKinetics_F(id, option) & + BIND(C, NAME='YAMLSetUnitsKinetics_F') + USE ISO_C_BINDING + IMPLICIT NONE + integer(kind=C_INT), intent(in) :: id + integer(kind=C_INT), intent(in) :: option + END FUNCTION YAMLSetUnitsKinetics_F + END INTERFACE + integer, intent(in) :: id + integer, intent(in) :: option + YAMLSetUnitsKinetics = YAMLSetUnitsKinetics_F(id, option) + END FUNCTION YAMLSetUnitsKinetics +!> Inserts data into the YAML document for the PhreeqcRM method SetUnitsPPassemblage. +!> When the YAML document is written to file it can be processed by the method InitializeYAML to +!> initialize a PhreeqcRM instance. +!> @param id The instance id returned from @ref CreateYAMLPhreeqcRM. +!> @param option Units option for equilibrium phases: 0, 1, or 2. +!> @retval IRM_RESULT Zero indicates success, negative indicates failure. +!> @par +!> SetUnitsPPassemblage +!> sets input units for pure phase assemblages (equilibrium phases). +!> In PHREEQC input, equilibrium phases are defined by moles of each phase (@a Mp). +!> @a SetUnitsPPassemblage specifies how the number of moles of phases in a reaction cell (@a Mc) +!> is calculated from the input value (@a Mp). +!> @par +!> Options are +!> 0, @a Mp is mol/L of RV (default), @a Mc = @a Mp*RV, where RV is the representative volume (SetRepresentativeVolume); +!> 1, @a Mp is mol/L of water in the RV, @a Mc = @a Mp*P*RV, where @a P is porosity (SetPorosity); or +!> 2, @a Mp is mol/L of rock in the RV, @a Mc = @a Mp*(1-P)*RV. +!> @par +!> If a single EQUILIBRIUM_PHASES definition is used for cells with different initial porosity, +!> the three options scale quite differently. +!> For option 0, the number of moles of a mineral will be the same regardless of porosity. +!> For option 1, the number of moles of a mineral will be vary directly with porosity and inversely with rock volume. +!> For option 2, the number of moles of a mineral will vary directly with rock volume and inversely with porosity. +!> +!> @see @ref YAMLInitialPhreeqc2Module, @ref YAMLInitialPhreeqcCell2Module, +!> @ref YAMLSetPorosity, @ref YAMLSetRepresentativeVolume. +!> @par Fortran Example: +!> @htmlonly +!> +!>
+!> status = YAMLSetUnitsPPassemblage(id, 1)
+!> 
+!>
+!> @endhtmlonly + INTEGER FUNCTION YAMLSetUnitsPPassemblage(id, option) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION YAMLSetUnitsPPassemblage_F(id, option) & + BIND(C, NAME='YAMLSetUnitsPPassemblage_F') + USE ISO_C_BINDING + IMPLICIT NONE + integer(kind=C_INT), intent(in) :: id + integer(kind=C_INT), intent(in) :: option + END FUNCTION YAMLSetUnitsPPassemblage_F + END INTERFACE + integer, intent(in) :: id + integer, intent(in) :: option + YAMLSetUnitsPPassemblage = YAMLSetUnitsPPassemblage_F(id, option) + END FUNCTION YAMLSetUnitsPPassemblage +!> Inserts data into the YAML document for the PhreeqcRM method SetUnitsSolution. +!> When the YAML document is written to file it can be processed by the method InitializeYAML to +!> initialize a PhreeqcRM instance. +!> @param id The instance id returned from @ref CreateYAMLPhreeqcRM. +!> @param option Units option for solutions: 1, 2, or 3, default is 1, mg/L. +!> @retval IRM_RESULT Zero indicates success, negative indicates failure. +!> @par +!> SetUnitsSolution +!> sets solution concentration units used by the transport model. +!> Options are 1, mg/L; 2 mol/L; or 3, mass fraction, kg/kgs. +!> PHREEQC defines solutions by the number of moles of each +!> element in the solution. +!> @par +!> To convert from mg/L to moles +!> of element in the representative volume of a reaction cell, mg/L is converted to mol/L and +!> multiplied by the solution volume, +!> which is the product of porosity (SetPorosity), saturation (SetSaturation), +!> and representative volume (SetRepresentativeVolume). +!> To convert from mol/L to moles +!> of element in the representative volume of a reaction cell, mol/L is +!> multiplied by the solution volume. +!> To convert from mass fraction to moles +!> of element in the representative volume of a reaction cell, kg/kgs is converted to mol/kgs, multiplied by density +!> (SetDensity) and +!> multiplied by the solution volume. +!> @par +!> To convert from moles +!> of element in the representative volume of a reaction cell to mg/L, the number of moles of an element is divided by the +!> solution volume resulting in mol/L, and then converted to mg/L. +!> To convert from moles +!> of element in a cell to mol/L, the number of moles of an element is divided by the +!> solution volume resulting in mol/L. +!> To convert from moles +!> of element in a cell to mass fraction, the number of moles of an element is converted to kg and divided +!> by the total mass of the solution. +!> Two options are available for the volume and mass of solution +!> that are used in converting to transport concentrations: (1) the volume and mass of solution are +!> calculated by PHREEQC, or (2) the volume of solution is the product of porosity (SetPorosity), +!> saturation (SetSaturation), and representative volume (SetRepresentativeVolume), +!> and the mass of solution is volume times density as defined by SetDensity. +!> Which option is used is determined by UseSolutionDensityVolume. +!> +!> @see @ref YAMLSetDensity, @ref YAMLSetPorosity, @ref YAMLSetRepresentativeVolume, +!> @ref YAMLSetSaturation, +!> @ref YAMLUseSolutionDensityVolume. +!> +!> @par Fortran Example: +!> @htmlonly +!> +!>
+!> status = YAMLSetUnitsSolution(id, 2)
+!> 
+!>
+!> @endhtmlonly + INTEGER FUNCTION YAMLSetUnitsSolution(id, option) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION YAMLSetUnitsSolution_F(id, option) & + BIND(C, NAME='YAMLSetUnitsSolution_F') + USE ISO_C_BINDING + IMPLICIT NONE + integer(kind=C_INT), intent(in) :: id + integer(kind=C_INT), intent(in) :: option + END FUNCTION YAMLSetUnitsSolution_F + END INTERFACE + integer, intent(in) :: id + integer, intent(in) :: option + YAMLSetUnitsSolution = YAMLSetUnitsSolution_F(id, option) + END FUNCTION YAMLSetUnitsSolution +!> Inserts data into the YAML document for the PhreeqcRM method SetUnitsSSassemblage. +!> When the YAML document is written to file it can be processed by the method InitializeYAML to +!> initialize a PhreeqcRM instance. +!> @param id The instance id returned from @ref CreateYAMLPhreeqcRM. +!> @param option Units option for solid solutions: 0, 1, or 2. +!> @retval IRM_RESULT Zero indicates success, negative indicates failure. +!> @par +!> SetUnitsSSassemblage +!> sets input units for solid-solution assemblages. +!> In PHREEQC, solid solutions are defined by moles of each component (@a Mp). +!> @a SetUnitsSSassemblage specifies how the number of moles of solid-solution components in a reaction cell (@a Mc) +!> is calculated from the input value (@a Mp). +!> @par +!> Options are +!> 0, @a Mp is mol/L of RV (default), @a Mc = @a Mp*RV, where RV is the representative volume (SetRepresentativeVolume); +!> 1, @a Mp is mol/L of water in the RV, @a Mc = @a Mp*P*RV, where @a P is porosity (SetPorosity); or +!> 2, @a Mp is mol/L of rock in the RV, @a Mc = @a Mp*(1-@ P)*RV. +!> @par +!> If a single SOLID_SOLUTION definition is used for cells with different initial porosity, +!> the three options scale quite differently. +!> For option 0, the number of moles of a solid-solution component will be the same regardless of porosity. +!> For option 1, the number of moles of a solid-solution component will be vary directly with porosity and inversely with rock volume. +!> For option 2, the number of moles of a solid-solution component will vary directly with rock volume and inversely with porosity. +!> +!> @see @ref YAMLInitialPhreeqc2Module, @ref YAMLInitialPhreeqcCell2Module, +!> @ref YAMLSetPorosity, @ref YAMLSetRepresentativeVolume. +!> @par Fortran Example: +!> @htmlonly +!> +!>
+!> status = YAMLSetUnitsSSassemblage(id, 1)
+!> 
+!>
+!> @endhtmlonly + INTEGER FUNCTION YAMLSetUnitsSSassemblage(id, option) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION YAMLSetUnitsSSassemblage_F(id, option) & + BIND(C, NAME='YAMLSetUnitsSSassemblage_F') + USE ISO_C_BINDING + IMPLICIT NONE + integer(kind=C_INT), intent(in) :: id + integer(kind=C_INT), intent(in) :: option + END FUNCTION YAMLSetUnitsSSassemblage_F + END INTERFACE + integer, intent(in) :: id + integer, intent(in) :: option + YAMLSetUnitsSSassemblage = YAMLSetUnitsSSassemblage_F(id, option) + END FUNCTION YAMLSetUnitsSSassemblage +!> Inserts data into the YAML document for the PhreeqcRM method SetUnitsSurface. +!> When the YAML document is written to file it can be processed by the method InitializeYAML to +!> initialize a PhreeqcRM instance. +!> @param id The instance id returned from @ref CreateYAMLPhreeqcRM. +!> @param option Units option for surfaces: 0, 1, or 2. +!> @retval IRM_RESULT Zero indicates success, negative indicates failure. +!> @par +!> SetUnitsSurface +!> sets input units for surfaces. +!> In PHREEQC input, surfaces are defined by moles of surface sites (@a Mp). +!> @a SetUnitsSurface specifies how the number of moles of surface sites in a reaction cell (@a Mc) +!> is calculated from the input value (@a Mp). +!> @par +!> Options are +!> 0, @a Mp is mol/L of RV (default), @a Mc = @a Mp*RV, where RV is the representative volume (SetRepresentativeVolume); +!> 1, @a Mp is mol/L of water in the RV, @a Mc = @a Mp*P*RV, where @a P is porosity (SetPorosity); or +!> 2, @a Mp is mol/L of rock in the RV, @a Mc = @a Mp*(1-@a P)*RV. +!> @par +!> If a single SURFACE definition is used for cells with different initial porosity, +!> the three options scale quite differently. +!> For option 0, the number of moles of surface sites will be the same regardless of porosity. +!> For option 1, the number of moles of surface sites will be vary directly with porosity and inversely with rock volume. +!> For option 2, the number of moles of surface sites will vary directly with rock volume and inversely with porosity. +!> +!> @see @ref YAMLInitialPhreeqc2Module, @ref YAMLInitialPhreeqcCell2Module, +!> @ref YAMLSetPorosity, @ref YAMLSetRepresentativeVolume. +!> @par Fortran Example: +!> @htmlonly +!> +!>
+!> status = YAMLSetUnitsSurface(id, 1)
+!> 
+!>
+!> @endhtmlonly + INTEGER FUNCTION YAMLSetUnitsSurface(id, option) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION YAMLSetUnitsSurface_F(id, option) & + BIND(C, NAME='YAMLSetUnitsSurface_F') + USE ISO_C_BINDING + IMPLICIT NONE + integer(kind=C_INT), intent(in) :: id + integer(kind=C_INT), intent(in) :: option + END FUNCTION YAMLSetUnitsSurface_F + END INTERFACE + integer, intent(in) :: id + integer, intent(in) :: option + YAMLSetUnitsSurface = YAMLSetUnitsSurface_F(id, option) + END FUNCTION YAMLSetUnitsSurface +!> Inserts data into the YAML document for the PhreeqcRM method SpeciesConcentrations2Module. +!> When the YAML document is written to file it can be processed by the method InitializeYAML to +!> initialize a PhreeqcRM instance. +!> @param id The instance id returned from @ref CreateYAMLPhreeqcRM. +!> @param species_conc Vector of aqueous species concentrations. Dimension of the +!> array is @a nspecies times @a nxyz, +!> where @a nspecies is the number of aqueous species, +!> and @a nxyz is the number of user grid cells. +!> Concentrations are moles per liter. +!> @retval IRM_RESULT Zero indicates success, negative indicates failure. +!> @par +!> SpeciesConcentrations2Module +!> sets solution concentrations in the reaction cells +!> based on the vector of aqueous species concentrations (@a species_conc). +!> This method is intended for use with multicomponent-diffusion transport calculations, +!> and SetSpeciesSaveOn must be set to @a true. +!> The list of aqueous species is determined by FindComponents and includes all +!> aqueous species that can be made from the set of components. +!> The method determines the total concentration of a component +!> by summing the molarities of the individual species times the stoichiometric +!> coefficient of the element in each species. +!> Solution compositions in the reaction cells are updated with these component concentrations. +!> Usually, accurate concentrations will not be known to use YAMLSetSpeciesConcentrations during +!> initialization. +!> +!> @see @ref YAMLFindComponents, +!> @ref YAMLSetSpeciesSaveOn. +!> @par Fortran Example: +!> @htmlonly +!> +!>
+!> status = YAMLSetSpeciesConcentrations(id, c)
+!> 
+!>
+!> @endhtmlonly + INTEGER FUNCTION YAMLSpeciesConcentrations2Module(id, c) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION YAMLSpeciesConcentrations2Module_F(id, c, dim) & + BIND(C, NAME='YAMLSpeciesConcentrations2Module_F') + USE ISO_C_BINDING + IMPLICIT NONE + integer(kind=C_INT), intent(in) :: id + real(kind=C_DOUBLE), intent(in) :: c + integer(kind=C_INT), intent(in) :: dim + END FUNCTION YAMLSpeciesConcentrations2Module_F + END INTERFACE + integer, intent(in) :: id + real(kind=8), allocatable, dimension(:,:), intent(in) :: c + integer :: dim + dim = size(c,1)*size(c,2) + YAMLSpeciesConcentrations2Module = YAMLSpeciesConcentrations2Module_F(id, c(1,1), dim) + END FUNCTION YAMLSpeciesConcentrations2Module +!> Inserts data into the YAML document for the PhreeqcRM method StateSave. +!> When the YAML document is written to file it can be processed by the method InitializeYAML to +!> initialize a PhreeqcRM instance. +!> @param id The instance id returned from @ref CreateYAMLPhreeqcRM. +!> @param n Integer identifying the state that is saved. +!> @retval IRM_RESULT Zero indicates success, negative indicates failure. +!> @par +!> StateSave +!> saves the state of the chemistry in all model cells, including SOLUTIONs, +!> EQUILIBRIUM_PHASES, EXCHANGEs, GAS_PHASEs, KINETICS, SOLID_SOLUTIONs, and SURFACEs. +!> Although not generally used, MIXes, REACTIONs, REACTION_PRESSUREs, and REACTION_TEMPERATUREs +!> will be saved for each cell, if they have been defined in the worker IPhreeqc instances. +!> The distribution of cells among the workers and the chemistry of fully or partially +!> unsaturated cells are also saved. The state is saved in memory; use DumpModule to save the state +!> to file. PhreeqcRM can be reset to this state by using StateApply. +!> A state is identified by an integer, and multiple states can be saved. +!> +!> @see @ref YAMLDumpModule, +!> @ref YAMLStateApply, and +!> @ref YAMLStateDelete. +!> @par Fortran Example: +!> @htmlonly +!> +!>
+!> status = YAMLStateSave(id, 1)
+!> 
+!>
+!> @endhtmlonly + INTEGER FUNCTION YAMLStateSave(id, n) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION YAMLStateSave_F(id, n) & + BIND(C, NAME='YAMLStateSave_F') + USE ISO_C_BINDING + IMPLICIT NONE + integer(kind=C_INT), intent(in) :: id + integer(kind=C_INT), intent(in) :: n + END FUNCTION YAMLStateSave_F + END INTERFACE + integer, intent(in) :: id + integer, intent(in) :: n + YAMLStateSave = YAMLStateSave_F(id, n) + END FUNCTION YAMLStateSave +!> Inserts data into the YAML document for the PhreeqcRM method StateApply. +!> When the YAML document is written to file it can be processed by the method InitializeYAML to +!> initialize a PhreeqcRM instance. +!> @param id The instance id returned from @ref CreateYAMLPhreeqcRM. +!> @param n Integer identifying the state that is to be applied. +!> @retval IRM_RESULT Zero indicates success, negative indicates failure. +!> @par +!> StateApply +!> resets the state of the module to a state previously saved with StateSave. +!> The chemistry of all model cells are reset, including SOLUTIONs, +!> EQUILIBRIUM_PHASES, EXCHANGEs, GAS_PHASEs, KINETICS, SOLID_SOLUTIONs, and SURFACEs. +!> MIXes, REACTIONs, REACTION_PRESSUREs, and REACTION_TEMPERATUREs +!> will be reset for each cell, if they were defined in the worker IPhreeqc instances +!> at the time the state was saved. +!> The distribution of cells among the workers and the chemistry of fully or partially +!> unsaturated cells are also reset to the saved state. +!> The state to be applied is identified by an integer. +!> +!> @see @ref YAMLStateSave and +!> @ref YAMLStateDelete. +!> @par Fortran Example: +!> @htmlonly +!> +!>
+!> status = YAMLStateApply(id, 1)
+!> 
+!>
+!> @endhtmlonly + INTEGER FUNCTION YAMLStateApply(id, n) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION YAMLStateApply_F(id, n) & + BIND(C, NAME='YAMLStateApply_F') + USE ISO_C_BINDING + IMPLICIT NONE + integer(kind=C_INT), intent(in) :: id + integer(kind=C_INT), intent(in) :: n + END FUNCTION YAMLStateApply_F + END INTERFACE + integer, intent(in) :: id + integer, intent(in) :: n + YAMLStateApply = YAMLStateApply_F(id, n) + END FUNCTION YAMLStateApply +!> Inserts data into the YAML document for the PhreeqcRM method StateDelete. +!> When the YAML document is written to file it can be processed by the method InitializeYAML to +!> initialize a PhreeqcRM instance. +!> @param id The instance id returned from @ref CreateYAMLPhreeqcRM. +!> @param n Integer identifying the state that is to be deleted. +!> @retval IRM_RESULT Zero indicates success, negative indicates failure. +!> @par +!> StateDelete +!> deletes a state previously saved with StateSave. +!> +!> @see @ref YAMLStateSave and +!> @ref YAMLStateApply. +!> @par Fortran Example: +!> @htmlonly +!> +!>
+!> status = YAMLStateDelete(id, 1)
+!> 
+!>
+!> @endhtmlonly + INTEGER FUNCTION YAMLStateDelete(id, n) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION YAMLStateDelete_F(id, n) & + BIND(C, NAME='YAMLStateDelete_F') + USE ISO_C_BINDING + IMPLICIT NONE + integer(kind=C_INT), intent(in) :: id + integer(kind=C_INT), intent(in) :: n + END FUNCTION YAMLStateDelete_F + END INTERFACE + integer, intent(in) :: id + integer, intent(in) :: n + YAMLStateDelete = YAMLStateDelete_F(id, n) + END FUNCTION YAMLStateDelete +!> Inserts data into the YAML document for the PhreeqcRM method UseSolutionDensityVolume. +!> When the YAML document is written to file it can be processed by the method InitializeYAML to +!> initialize a PhreeqcRM instance. +!> @param id The instance id returned from @ref CreateYAMLPhreeqcRM. +!> @param tf @a True indicates that the solution density and volume as +!> calculated by PHREEQC will be used to calculate concentrations. +!> @a False indicates that the solution density set by SetDensity and the volume determined by the +!> product of SetSaturation, SetPorosity, and SetRepresentativeVolume, +!> will be used to calculate concentrations retrieved by GetConcentrations. +!> @retval IRM_RESULT Zero indicates success, negative indicates failure. +!> @par +!> UseSolutionDensityVolume +!> determines the volume and density to use when converting from the reaction-cell concentrations +!> to transport concentrations (GetConcentrations). +!> Two options are available to convert concentration units: +!> (1) the density and solution volume calculated by PHREEQC are used, or +!> (2) the specified density (SetDensity) +!> and solution volume are determined by the product of +!> saturation (SetSaturation), porosity (SetPorosity), +!> and representative volume (SetRepresentativeVolume). +!> Transport models that consider density-dependent flow will probably use the +!> PHREEQC-calculated density and solution volume (default), +!> whereas transport models that assume constant-density flow will probably use +!> specified values of density and solution volume. +!> Only the following databases distributed with PhreeqcRM have molar-volume information +!> needed to accurately calculate density and solution volume: phreeqc.dat, Amm.dat, and pitzer.dat. +!> Density is only used when converting to or from transport units of mass fraction. +!> +!> @see @ref YAMLSetDensity, +!> @ref YAMLSetPorosity, @ref YAMLSetRepresentativeVolume, @ref YAMLSetSaturation. +!> @par Fortran Example: +!> @htmlonly +!> +!>
+!> status = YAMLUseSolutionDensityVolume(id, .false.)
+!> 
+!>
+!> @endhtmlonly + INTEGER FUNCTION YAMLUseSolutionDensityVolume(id, tf) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION YAMLUseSolutionDensityVolume_F(id, itf) & + BIND(C, NAME='YAMLUseSolutionDensityVolume_F') + USE ISO_C_BINDING + IMPLICIT NONE + integer(kind=C_INT), intent(in) :: id + integer(kind=C_INT), intent(in) :: itf + END FUNCTION YAMLUseSolutionDensityVolume_F + END INTERFACE + integer, intent(in) :: id + logical, intent(in) :: tf + integer :: itf + itf = 0 + if (tf) itf = 1 + YAMLUseSolutionDensityVolume = YAMLUseSolutionDensityVolume_F(id, itf) + END FUNCTION YAMLUseSolutionDensityVolume +!> Inserts data into the YAML document for the PhreeqcRM method WarningMessage. +!> When the YAML document is written to file it can be processed by the method InitializeYAML to +!> initialize a PhreeqcRM instance. +!> @param id The instance id returned from @ref CreateYAMLPhreeqcRM. +!> @param str String to be printed. +!> @retval IRM_RESULT Zero indicates success, negative indicates failure. +!> @par +!> WarningMessage +!> prints a warning message to the screen and the log file. +!> +!> @see @ref YAMLOpenFiles, @ref YAMLLogMessage, +!> @ref YAMLOutputMessage, @ref YAMLScreenMessage. +!> @par Fortran Example: +!> @htmlonly +!> +!>
+!> status = WarningMessage(id, "Need to check these definitions.")
+!> 
+!>
+!> @endhtmlonly + INTEGER FUNCTION YAMLWarningMessage(id, str) + USE ISO_C_BINDING + IMPLICIT NONE + INTERFACE + INTEGER(KIND=C_INT) FUNCTION YAMLWarningMessage_F(id, str) & + BIND(C, NAME='YAMLWarningMessage_F') + USE ISO_C_BINDING + IMPLICIT NONE + integer(kind=C_INT), intent(in) :: id + character(KIND=C_CHAR), intent(in) :: str(*) + END FUNCTION YAMLWarningMessage_F + END INTERFACE + integer, intent(in) :: id + character(len=*), intent(in) :: str + YAMLWarningMessage = YAMLWarningMessage_F(id, trim(str)//C_NULL_CHAR) + END FUNCTION YAMLWarningMessage + +END MODULE YAML_interface + +#endif diff --git a/src/YAML_interface_F.cpp b/src/YAML_interface_F.cpp new file mode 100644 index 000000000..11692bc5b --- /dev/null +++ b/src/YAML_interface_F.cpp @@ -0,0 +1,656 @@ +#ifdef USE_YAML +#include +#include +#include +#include "YAMLPhreeqcRM.h" +#include "YAML_interface_F.h" + +int CreateYAMLPhreeqcRM_F(void) +{ + return YAMLPhreeqcRMLib::CreateYAMLPhreeqcRM(); +} +int DestroyYAMLPhreeqcRM_F(int* id) +{ + return YAMLPhreeqcRMLib::DestroyYAMLPhreeqcRM(*id); +} +IRM_RESULT YAMLClear_F(int* id) +{ + YAMLPhreeqcRM* yrm_ptr = YAMLPhreeqcRMLib::GetInstance(*id); + if (yrm_ptr != NULL) + { + yrm_ptr->Clear(); + return IRM_OK; + } + return IRM_BADINSTANCE; + +} +IRM_RESULT WriteYAMLDoc_F(int* id, const char* file_name) +{ + YAMLPhreeqcRM* yrm_ptr = YAMLPhreeqcRMLib::GetInstance(*id); + if (yrm_ptr != NULL) + { + yrm_ptr->WriteYAMLDoc(file_name); + return IRM_OK; + } + return IRM_BADINSTANCE; +} +IRM_RESULT YAMLCloseFiles_F(int* id) +{ + YAMLPhreeqcRM* yrm_ptr = YAMLPhreeqcRMLib::GetInstance(*id); + if (yrm_ptr != NULL) + { + yrm_ptr->YAMLCloseFiles(); + return IRM_OK; + } + return IRM_BADINSTANCE; +}; +IRM_RESULT YAMLCreateMapping_F(int* id, int* grid2chem, int* dim) +{ + YAMLPhreeqcRM* yrm_ptr = YAMLPhreeqcRMLib::GetInstance(*id); + if (yrm_ptr != NULL) + { + std::vector grid2chem_v(*dim, 0); + memcpy(grid2chem_v.data(), grid2chem, (*dim) * sizeof(int)); + yrm_ptr->YAMLCreateMapping(grid2chem_v); + return IRM_OK; + } + return IRM_BADINSTANCE; +}; +IRM_RESULT YAMLDumpModule_F(int* id, int* idump_on, int* iappend) +{ + YAMLPhreeqcRM* yrm_ptr = YAMLPhreeqcRMLib::GetInstance(*id); + if (yrm_ptr != NULL) + { + bool dump_on = (bool)*idump_on; + bool append = (bool)*iappend; + yrm_ptr->YAMLDumpModule(dump_on, append); + return IRM_OK; + } + return IRM_BADINSTANCE; +}; +IRM_RESULT YAMLFindComponents_F(int* id) +{ + YAMLPhreeqcRM* yrm_ptr = YAMLPhreeqcRMLib::GetInstance(*id); + if (yrm_ptr != NULL) + { + yrm_ptr->YAMLFindComponents(); + return IRM_OK; + } + return IRM_BADINSTANCE; +}; +IRM_RESULT YAMLInitialPhreeqc2Module_F(int* id, int* ic1, int* dim) +{ + YAMLPhreeqcRM* yrm_ptr = YAMLPhreeqcRMLib::GetInstance(*id); + if (yrm_ptr != NULL) + { + std::vector ic1_v(*dim, -1); + memcpy(ic1_v.data(), ic1, (*dim) * sizeof(int)); + yrm_ptr->YAMLInitialPhreeqc2Module(ic1_v); + return IRM_OK; + } + return IRM_BADINSTANCE; +}; +IRM_RESULT YAMLInitialPhreeqc2Module_mix_F(int* id, int* ic1, int* ic2, double* f1, int* dim) +{ + YAMLPhreeqcRM* yrm_ptr = YAMLPhreeqcRMLib::GetInstance(*id); + if (yrm_ptr != NULL) + { + std::vector ic1_v(*dim, -1), ic2_v(*dim, -1); + std::vector f1_v(*dim, 0.0); + memcpy(ic1_v.data(), ic1, (*dim)*sizeof(int)); + memcpy(ic2_v.data(), ic2, (*dim) * sizeof(int)); + memcpy(f1_v.data(), f1, (*dim) * sizeof(double)); + yrm_ptr->YAMLInitialPhreeqc2Module(ic1_v, ic2_v, f1_v); + return IRM_OK; + } + return IRM_BADINSTANCE; +}; + +IRM_RESULT YAMLInitialPhreeqcCell2Module_F(int* id, + int* n, int* cell_numbers, int* dim) +{ + YAMLPhreeqcRM* yrm_ptr = YAMLPhreeqcRMLib::GetInstance(*id); + if (yrm_ptr != NULL) + { + std::vector cell_numbers_v(*dim, 0.0); + memcpy(cell_numbers_v.data(), cell_numbers, (*dim) * sizeof(int)); + yrm_ptr->YAMLInitialPhreeqcCell2Module(*n, cell_numbers_v); + return IRM_OK; + } + return IRM_BADINSTANCE; +} + +IRM_RESULT YAMLLoadDatabase_F(int* id, const char* database) +{ + YAMLPhreeqcRM* yrm_ptr = YAMLPhreeqcRMLib::GetInstance(*id); + if (yrm_ptr != NULL) + { + yrm_ptr->YAMLLoadDatabase(database); + return IRM_OK; + } + return IRM_BADINSTANCE; +} +IRM_RESULT YAMLLogMessage_F(int* id, const char* str) +{ + YAMLPhreeqcRM* yrm_ptr = YAMLPhreeqcRMLib::GetInstance(*id); + if (yrm_ptr != NULL) + { + yrm_ptr->YAMLLogMessage(str); + return IRM_OK; + } + return IRM_BADINSTANCE; +} +IRM_RESULT YAMLOpenFiles_F(int* id) +{ + YAMLPhreeqcRM* yrm_ptr = YAMLPhreeqcRMLib::GetInstance(*id); + if (yrm_ptr != NULL) + { + yrm_ptr->YAMLOpenFiles(); + return IRM_OK; + } + return IRM_BADINSTANCE; +} +IRM_RESULT YAMLOutputMessage_F(int* id, const char* str) +{ + YAMLPhreeqcRM* yrm_ptr = YAMLPhreeqcRMLib::GetInstance(*id); + if (yrm_ptr != NULL) + { + yrm_ptr->YAMLOutputMessage(str); + return IRM_OK; + } + return IRM_BADINSTANCE; +} +IRM_RESULT YAMLRunCells_F(int* id) +{ + YAMLPhreeqcRM* yrm_ptr = YAMLPhreeqcRMLib::GetInstance(*id); + if (yrm_ptr != NULL) + { + yrm_ptr->YAMLRunCells(); + return IRM_OK; + } + return IRM_BADINSTANCE; +} +IRM_RESULT YAMLRunFile_F(int* id, int* iworkers, int* iinitial_phreeqc, + int* iutility, const char* file_name) +{ + YAMLPhreeqcRM* yrm_ptr = YAMLPhreeqcRMLib::GetInstance(*id); + if (yrm_ptr != NULL) + { + bool workers = (bool)*iworkers; + bool initial_phreeqc = (bool)*iinitial_phreeqc; + bool utility = (bool)*iutility; + + yrm_ptr->YAMLRunFile(workers, initial_phreeqc, utility, file_name); + return IRM_OK; + } + return IRM_BADINSTANCE; +} +IRM_RESULT YAMLRunString_F(int* id, int* iworkers, int* iinitial_phreeqc, + int* iutility, const char* input_string) +{ + YAMLPhreeqcRM* yrm_ptr = YAMLPhreeqcRMLib::GetInstance(*id); + if (yrm_ptr != NULL) + { + bool workers = (bool)*iworkers; + bool initial_phreeqc = (bool)*iinitial_phreeqc; + bool utility = (bool)*iutility; + yrm_ptr->YAMLRunString(workers, initial_phreeqc, utility, input_string); + return IRM_OK; + } + return IRM_BADINSTANCE; +} +IRM_RESULT YAMLScreenMessage_F(int* id, const char* str) +{ + YAMLPhreeqcRM* yrm_ptr = YAMLPhreeqcRMLib::GetInstance(*id); + if (yrm_ptr != NULL) + { + yrm_ptr->YAMLScreenMessage(str); + return IRM_OK; + } + return IRM_BADINSTANCE; +} +IRM_RESULT YAMLSetComponentH2O_F(int* id, int* itf) +{ + YAMLPhreeqcRM* yrm_ptr = YAMLPhreeqcRMLib::GetInstance(*id); + if (yrm_ptr != NULL) + { + bool tf = (bool)itf; + yrm_ptr->YAMLSetComponentH2O(tf); + return IRM_OK; + } + return IRM_BADINSTANCE; +}; +IRM_RESULT YAMLSetConcentrations_F(int* id, double* c, int* dim) +{ + YAMLPhreeqcRM* yrm_ptr = YAMLPhreeqcRMLib::GetInstance(*id); + if (yrm_ptr != NULL) + { + std::vector c_v(*dim, 0.0); + memcpy(c_v.data(), c, (*dim) * sizeof(double)); + yrm_ptr->YAMLSetConcentrations(c_v); + return IRM_OK; + } + return IRM_BADINSTANCE; +} +IRM_RESULT YAMLSetCurrentSelectedOutputUserNumber_F(int* id, int* n_user) +{ + YAMLPhreeqcRM* yrm_ptr = YAMLPhreeqcRMLib::GetInstance(*id); + if (yrm_ptr != NULL) + { + yrm_ptr->YAMLSetCurrentSelectedOutputUserNumber(*n_user); + return IRM_OK; + } + return IRM_BADINSTANCE; +} +IRM_RESULT YAMLSetDensity_F(int* id, double* density, int* dim) +{ + YAMLPhreeqcRM* yrm_ptr = YAMLPhreeqcRMLib::GetInstance(*id); + if (yrm_ptr != NULL) + { + std::vector density_v(*dim, 0.0); + memcpy(density_v.data(), density, (*dim) * sizeof(double)); + yrm_ptr->YAMLSetDensity(density_v); + return IRM_OK; + } + return IRM_BADINSTANCE; +} +IRM_RESULT YAMLSetDumpFileName_F(int* id, const char* dump_name) +{ + YAMLPhreeqcRM* yrm_ptr = YAMLPhreeqcRMLib::GetInstance(*id); + if (yrm_ptr != NULL) + { + yrm_ptr->YAMLSetDumpFileName(dump_name); + return IRM_OK; + } + return IRM_BADINSTANCE; +} +IRM_RESULT YAMLSetErrorHandlerMode_F(int* id, int* mode) +{ + YAMLPhreeqcRM* yrm_ptr = YAMLPhreeqcRMLib::GetInstance(*id); + if (yrm_ptr != NULL) + { + yrm_ptr->YAMLSetErrorHandlerMode(*mode); + return IRM_OK; + } + return IRM_BADINSTANCE; +}; +IRM_RESULT YAMLSetErrorOn_F(int* id, int* itf) +{ + YAMLPhreeqcRM* yrm_ptr = YAMLPhreeqcRMLib::GetInstance(*id); + if (yrm_ptr != NULL) + { + bool tf = (bool)*itf; + yrm_ptr->YAMLSetErrorOn(tf); + return IRM_OK; + } + return IRM_BADINSTANCE; +} +IRM_RESULT YAMLSetFilePrefix_F(int* id, const char* prefix) +{ + YAMLPhreeqcRM* yrm_ptr = YAMLPhreeqcRMLib::GetInstance(*id); + if (yrm_ptr != NULL) + { + yrm_ptr->YAMLSetFilePrefix(prefix); + return IRM_OK; + } + return IRM_BADINSTANCE; +}; +IRM_RESULT YAMLSetGasCompMoles_F(int* id, double* gas_moles, int* dim) +{ + YAMLPhreeqcRM* yrm_ptr = YAMLPhreeqcRMLib::GetInstance(*id); + if (yrm_ptr != NULL) + { + std::vector gas_moles_v(*dim, 0.0); + memcpy(gas_moles_v.data(), gas_moles, (*dim) * sizeof(double)); + yrm_ptr->YAMLSetGasCompMoles(gas_moles_v); + return IRM_OK; + } + return IRM_BADINSTANCE; +} +IRM_RESULT YAMLSetGasPhaseVolume_F(int* id, double* gas_volume, int* dim) +{ + YAMLPhreeqcRM* yrm_ptr = YAMLPhreeqcRMLib::GetInstance(*id); + if (yrm_ptr != NULL) + { + std::vector gas_volume_v(*dim, 0.0); + memcpy(gas_volume_v.data(), gas_volume, (*dim) * sizeof(double)); + yrm_ptr->YAMLSetGasPhaseVolume(gas_volume_v); + return IRM_OK; + } + return IRM_BADINSTANCE; +} +IRM_RESULT YAMLSetGridCellCount_F(int* id, int* count) +{ + YAMLPhreeqcRM* yrm_ptr = YAMLPhreeqcRMLib::GetInstance(*id); + if (yrm_ptr != NULL) + { + yrm_ptr->YAMLSetGridCellCount(*count); + return IRM_OK; + } + return IRM_BADINSTANCE; +} +IRM_RESULT YAMLSetNthSelectedOutput_F(int* id, int* n) +{ + YAMLPhreeqcRM* yrm_ptr = YAMLPhreeqcRMLib::GetInstance(*id); + if (yrm_ptr != NULL) + { + yrm_ptr->YAMLSetNthSelectedOutput(*n); + return IRM_OK; + } + return IRM_BADINSTANCE; +} +IRM_RESULT YAMLSetPartitionUZSolids_F(int* id, int* itf) +{ + YAMLPhreeqcRM* yrm_ptr = YAMLPhreeqcRMLib::GetInstance(*id); + if (yrm_ptr != NULL) + { + bool tf = (bool)*itf; + yrm_ptr->YAMLSetPartitionUZSolids(tf); + return IRM_OK; + } + return IRM_BADINSTANCE; +}; +IRM_RESULT YAMLSetPorosity_F(int* id, double* por, int* dim) +{ + YAMLPhreeqcRM* yrm_ptr = YAMLPhreeqcRMLib::GetInstance(*id); + if (yrm_ptr != NULL) + { + std::vector por_v(*dim, 0.0); + memcpy(por_v.data(), por, (*dim) * sizeof(double)); + yrm_ptr->YAMLSetPorosity(por_v); + return IRM_OK; + } + return IRM_BADINSTANCE; +} +IRM_RESULT YAMLSetPressure_F(int* id, double* p, int* dim) +{ + YAMLPhreeqcRM* yrm_ptr = YAMLPhreeqcRMLib::GetInstance(*id); + if (yrm_ptr != NULL) + { + std::vector p_v(*dim, 0.0); + memcpy(p_v.data(), p, (*dim) * sizeof(double)); + yrm_ptr->YAMLSetPressure(p_v); + return IRM_OK; + } + return IRM_BADINSTANCE; +} +IRM_RESULT YAMLSetPrintChemistryMask_F(int* id, int* cell_mask, int* dim) +{ + YAMLPhreeqcRM* yrm_ptr = YAMLPhreeqcRMLib::GetInstance(*id); + if (yrm_ptr != NULL) + { + std::vector cell_mask_v(*dim, 0.0); + memcpy(cell_mask_v.data(), cell_mask, (*dim) * sizeof(int)); + yrm_ptr->YAMLSetPrintChemistryMask(cell_mask_v); + return IRM_OK; + } + return IRM_BADINSTANCE; +} +IRM_RESULT YAMLSetPrintChemistryOn_F(int* id, int* iworkers, int* iinitial_phreeqc, + int* iutility) +{ + YAMLPhreeqcRM* yrm_ptr = YAMLPhreeqcRMLib::GetInstance(*id); + if (yrm_ptr != NULL) + { + bool workers = (bool)*iworkers; + bool initial_phreeqc = (bool)*iinitial_phreeqc; + bool utility = (bool)*iutility; + yrm_ptr->YAMLSetPrintChemistryOn(workers, initial_phreeqc, utility); + return IRM_OK; + } + return IRM_BADINSTANCE; +} +IRM_RESULT YAMLSetRebalanceByCell_F(int* id, int* itf) +{ + YAMLPhreeqcRM* yrm_ptr = YAMLPhreeqcRMLib::GetInstance(*id); + if (yrm_ptr != NULL) + { + bool tf = (bool)*itf; + yrm_ptr->YAMLSetRebalanceByCell(tf); + return IRM_OK; + } + return IRM_BADINSTANCE; +}; +IRM_RESULT YAMLSetRebalanceFraction_F(int* id, double* f) +{ + YAMLPhreeqcRM* yrm_ptr = YAMLPhreeqcRMLib::GetInstance(*id); + if (yrm_ptr != NULL) + { + yrm_ptr->YAMLSetRebalanceFraction(*f); + return IRM_OK; + } + return IRM_BADINSTANCE; +} +IRM_RESULT YAMLSetRepresentativeVolume_F(int* id, double* rv, int* dim) +{ + YAMLPhreeqcRM* yrm_ptr = YAMLPhreeqcRMLib::GetInstance(*id); + if (yrm_ptr != NULL) + { + std::vector rv_v(*dim, 0.0); + memcpy(rv_v.data(), rv, (*dim) * sizeof(double)); + yrm_ptr->YAMLSetRepresentativeVolume(rv_v); + return IRM_OK; + } + return IRM_BADINSTANCE; +} +IRM_RESULT YAMLSetSaturation_F(int* id, double* sat, int* dim) +{ + YAMLPhreeqcRM* yrm_ptr = YAMLPhreeqcRMLib::GetInstance(*id); + if (yrm_ptr != NULL) + { + std::vector sat_v(*dim, 0.0); + memcpy(sat_v.data(), sat, (*dim) * sizeof(double)); + yrm_ptr->YAMLSetSaturation(sat_v); + return IRM_OK; + } + return IRM_BADINSTANCE; +} +IRM_RESULT YAMLSetScreenOn_F(int* id, int* itf) +{ + YAMLPhreeqcRM* yrm_ptr = YAMLPhreeqcRMLib::GetInstance(*id); + if (yrm_ptr != NULL) + { + bool tf = (bool)*itf; + yrm_ptr->YAMLSetScreenOn(tf); + return IRM_OK; + } + return IRM_BADINSTANCE; +} +IRM_RESULT YAMLSetSelectedOutputOn_F(int* id, int* itf) +{ + YAMLPhreeqcRM* yrm_ptr = YAMLPhreeqcRMLib::GetInstance(*id); + if (yrm_ptr != NULL) + { + bool tf = (bool)*itf; + yrm_ptr->YAMLSetSelectedOutputOn(tf); + return IRM_OK; + } + return IRM_BADINSTANCE; +} +IRM_RESULT YAMLSetSpeciesSaveOn_F(int* id, int* isave_on) +{ + YAMLPhreeqcRM* yrm_ptr = YAMLPhreeqcRMLib::GetInstance(*id); + if (yrm_ptr != NULL) + { + bool save_on = (bool)*isave_on; + yrm_ptr->YAMLSetSpeciesSaveOn(save_on); + return IRM_OK; + } + return IRM_BADINSTANCE; +} +IRM_RESULT YAMLSetTemperature_F(int* id, double* t, int* dim) +{ + YAMLPhreeqcRM* yrm_ptr = YAMLPhreeqcRMLib::GetInstance(*id); + if (yrm_ptr != NULL) + { + std::vector t_v(*dim, 0.0); + memcpy(t_v.data(), t, (*dim) * sizeof(double)); + yrm_ptr->YAMLSetTemperature(t_v); + return IRM_OK; + } + return IRM_BADINSTANCE; +} +IRM_RESULT YAMLSetTime_F(int* id, double* time) +{ + YAMLPhreeqcRM* yrm_ptr = YAMLPhreeqcRMLib::GetInstance(*id); + if (yrm_ptr != NULL) + { + yrm_ptr->YAMLSetTime(*time); + return IRM_OK; + } + return IRM_BADINSTANCE; +} +IRM_RESULT YAMLSetTimeConversion_F(int* id, double* conv_factor) +{ + YAMLPhreeqcRM* yrm_ptr = YAMLPhreeqcRMLib::GetInstance(*id); + if (yrm_ptr != NULL) + { + yrm_ptr->YAMLSetTimeConversion(*conv_factor); + return IRM_OK; + } + return IRM_BADINSTANCE; +} +IRM_RESULT YAMLSetTimeStep_F(int* id, double* time_step) +{ + YAMLPhreeqcRM* yrm_ptr = YAMLPhreeqcRMLib::GetInstance(*id); + if (yrm_ptr != NULL) + { + yrm_ptr->YAMLSetTimeStep(*time_step); + return IRM_OK; + } + return IRM_BADINSTANCE; +} +IRM_RESULT YAMLSetUnitsExchange_F(int* id, int* option) +{ + YAMLPhreeqcRM* yrm_ptr = YAMLPhreeqcRMLib::GetInstance(*id); + if (yrm_ptr != NULL) + { + yrm_ptr->YAMLSetUnitsExchange(*option); + return IRM_OK; + } + return IRM_BADINSTANCE; +}; +IRM_RESULT YAMLSetUnitsGasPhase_F(int* id, int* option) +{ + YAMLPhreeqcRM* yrm_ptr = YAMLPhreeqcRMLib::GetInstance(*id); + if (yrm_ptr != NULL) + { + yrm_ptr->YAMLSetUnitsGasPhase(*option); + return IRM_OK; + } + return IRM_BADINSTANCE; +}; +IRM_RESULT YAMLSetUnitsKinetics_F(int* id, int* option) +{ + YAMLPhreeqcRM* yrm_ptr = YAMLPhreeqcRMLib::GetInstance(*id); + if (yrm_ptr != NULL) + { + yrm_ptr->YAMLSetUnitsKinetics(*option); + return IRM_OK; + } + return IRM_BADINSTANCE; +}; +IRM_RESULT YAMLSetUnitsPPassemblage_F(int* id, int* option) +{ + YAMLPhreeqcRM* yrm_ptr = YAMLPhreeqcRMLib::GetInstance(*id); + if (yrm_ptr != NULL) + { + yrm_ptr->YAMLSetUnitsPPassemblage(*option); + return IRM_OK; + } + return IRM_BADINSTANCE; +}; +IRM_RESULT YAMLSetUnitsSolution_F(int* id, int* option) +{ + YAMLPhreeqcRM* yrm_ptr = YAMLPhreeqcRMLib::GetInstance(*id); + if (yrm_ptr != NULL) + { + yrm_ptr->YAMLSetUnitsSolution(*option); + return IRM_OK; + } + return IRM_BADINSTANCE; +}; +IRM_RESULT YAMLSetUnitsSSassemblage_F(int* id, int* option) +{ + YAMLPhreeqcRM* yrm_ptr = YAMLPhreeqcRMLib::GetInstance(*id); + if (yrm_ptr != NULL) + { + yrm_ptr->YAMLSetUnitsSSassemblage(*option); + return IRM_OK; + } + return IRM_BADINSTANCE; +}; +IRM_RESULT YAMLSetUnitsSurface_F(int* id, int* option) +{ + YAMLPhreeqcRM* yrm_ptr = YAMLPhreeqcRMLib::GetInstance(*id); + if (yrm_ptr != NULL) + { + yrm_ptr->YAMLSetUnitsSurface(*option); + return IRM_OK; + } + return IRM_BADINSTANCE; +} +IRM_RESULT YAMLSpeciesConcentrations2Module_F(int* id, double* species_conc, int* dim) +{ + YAMLPhreeqcRM* yrm_ptr = YAMLPhreeqcRMLib::GetInstance(*id); + if (yrm_ptr != NULL) + { + std::vector species_conc_v(*dim, 0.0); + memcpy(species_conc_v.data(), species_conc, (*dim) * sizeof(double)); + yrm_ptr->YAMLSpeciesConcentrations2Module(species_conc_v); + return IRM_OK; + } + return IRM_BADINSTANCE; +} +IRM_RESULT YAMLStateSave_F(int* id, int* istate) +{ + YAMLPhreeqcRM* yrm_ptr = YAMLPhreeqcRMLib::GetInstance(*id); + if (yrm_ptr != NULL) + { + yrm_ptr->YAMLStateSave(*istate); + return IRM_OK; + } + return IRM_BADINSTANCE; +} +IRM_RESULT YAMLStateApply_F(int* id, int* istate) +{ + YAMLPhreeqcRM* yrm_ptr = YAMLPhreeqcRMLib::GetInstance(*id); + if (yrm_ptr != NULL) + { + yrm_ptr->YAMLStateApply(*istate); + return IRM_OK; + } + return IRM_BADINSTANCE; +} +IRM_RESULT YAMLStateDelete_F(int* id, int* istate) +{ + YAMLPhreeqcRM* yrm_ptr = YAMLPhreeqcRMLib::GetInstance(*id); + if (yrm_ptr != NULL) + { + yrm_ptr->YAMLStateDelete(*istate); + return IRM_OK; + } + return IRM_BADINSTANCE; +} +IRM_RESULT YAMLUseSolutionDensityVolume_F(int* id, int* itf) +{ + YAMLPhreeqcRM* yrm_ptr = YAMLPhreeqcRMLib::GetInstance(*id); + if (yrm_ptr != NULL) + { + bool tf = (bool)*itf; + yrm_ptr->YAMLUseSolutionDensityVolume(tf); + return IRM_OK; + } + return IRM_BADINSTANCE; +}; +IRM_RESULT YAMLWarningMessage_F(int* id, const char* warnstr) +{ + YAMLPhreeqcRM* yrm_ptr = YAMLPhreeqcRMLib::GetInstance(*id); + if (yrm_ptr != NULL) + { + yrm_ptr->YAMLWarningMessage(warnstr); + return IRM_OK; + } + return IRM_BADINSTANCE; +} +#endif \ No newline at end of file diff --git a/src/YAML_interface_F.h b/src/YAML_interface_F.h new file mode 100644 index 000000000..0833197e1 --- /dev/null +++ b/src/YAML_interface_F.h @@ -0,0 +1,84 @@ +#ifdef USE_YAML +#ifndef INC_YAML_interface_F_H +#define INC_YAML_interface_F_H +#if defined(_WINDLL) +#define IRM_DLL_EXPORT __declspec(dllexport) +#else +#define IRM_DLL_EXPORT +#endif + +#if defined(__cplusplus) +extern "C" { +#endif + +IRM_DLL_EXPORT int CreateYAMLPhreeqcRM_F(void); +IRM_DLL_EXPORT int DestroyYAMLPhreeqcRM_F(int* id); +IRM_DLL_EXPORT IRM_RESULT YAMLClear_F(int* id); +IRM_DLL_EXPORT IRM_RESULT WriteYAMLDoc_F(int* id, const char* file_name); +IRM_DLL_EXPORT IRM_RESULT YAMLCloseFiles_F(int* id); +IRM_DLL_EXPORT IRM_RESULT YAMLCreateMapping_F(int* id, int* grid2chem, int* dim); +IRM_DLL_EXPORT IRM_RESULT YAMLDumpModule_F(int* id, int* dump_on, int* append); +IRM_DLL_EXPORT IRM_RESULT YAMLFindComponents_F(int* id); +IRM_DLL_EXPORT IRM_RESULT YAMLInitialPhreeqc2Module_F(int* id, int* ic1, int* dim); +IRM_DLL_EXPORT IRM_RESULT YAMLInitialPhreeqc2Module_mix_F(int* id, int* ic1, int* ic2, double* f1, int* dim); +IRM_DLL_EXPORT IRM_RESULT YAMLInitialPhreeqcCell2Module_F(int* id, + int* n, int* cell_numbers, int* dim); +IRM_DLL_EXPORT IRM_RESULT YAMLLoadDatabase_F(int* id, const char* database); +IRM_DLL_EXPORT IRM_RESULT YAMLLogMessage_F(int* id, const char* str); +IRM_DLL_EXPORT IRM_RESULT YAMLOpenFiles_F(int* id); +IRM_DLL_EXPORT IRM_RESULT YAMLOutputMessage_F(int* id, const char* str); +IRM_DLL_EXPORT IRM_RESULT YAMLRunCells_F(int* id); +IRM_DLL_EXPORT IRM_RESULT YAMLRunFile_F(int* id, int* workers, int* initial_phreeqc, + int* utility, const char* file_name); +IRM_DLL_EXPORT IRM_RESULT YAMLRunString_F(int* id, int* workers, int* initial_phreeqc, + int* utility, const char* input_string); +IRM_DLL_EXPORT IRM_RESULT YAMLScreenMessage_F(int* id, const char* str); +IRM_DLL_EXPORT IRM_RESULT YAMLSetComponentH2O_F(int* id, int* tf); +IRM_DLL_EXPORT IRM_RESULT YAMLSetConcentrations_F(int* id, double* c, int* dim); +IRM_DLL_EXPORT IRM_RESULT YAMLSetCurrentSelectedOutputUserNumber_F(int* id, int* n_user); +IRM_DLL_EXPORT IRM_RESULT YAMLSetDensity_F(int* id, double* density, int* dim); +IRM_DLL_EXPORT IRM_RESULT YAMLSetDumpFileName_F(int* id, const char* dump_name); +IRM_DLL_EXPORT IRM_RESULT YAMLSetErrorHandlerMode_F(int* id, int* mode); +IRM_DLL_EXPORT IRM_RESULT YAMLSetErrorOn_F(int* id, int* tf); +IRM_DLL_EXPORT IRM_RESULT YAMLSetFilePrefix_F(int* id, const char* prefix); +IRM_DLL_EXPORT IRM_RESULT YAMLSetGasCompMoles_F(int* id, double* gas_moles, int* dim); +IRM_DLL_EXPORT IRM_RESULT YAMLSetGasPhaseVolume_F(int* id, double* gas_volume, int* dim); +IRM_DLL_EXPORT IRM_RESULT YAMLSetGridCellCount_F(int* id, int* count); +IRM_DLL_EXPORT IRM_RESULT YAMLSetNthSelectedOutput_F(int* id, int* n); +IRM_DLL_EXPORT IRM_RESULT YAMLSetPartitionUZSolids_F(int* id, int* tf); +IRM_DLL_EXPORT IRM_RESULT YAMLSetPorosity_F(int* id, double* por, int* dim); +IRM_DLL_EXPORT IRM_RESULT YAMLSetPressure_F(int* id, double* p, int* dim); +IRM_DLL_EXPORT IRM_RESULT YAMLSetPrintChemistryMask_F(int* id, int* cell_mask, int* dim); +IRM_DLL_EXPORT IRM_RESULT YAMLSetPrintChemistryOn_F(int* id, int* workers, int* initial_phreeqc, + int* utility); +IRM_DLL_EXPORT IRM_RESULT YAMLSetRebalanceByCell_F(int* id, int* tf); +IRM_DLL_EXPORT IRM_RESULT YAMLSetRebalanceFraction_F(int* id, double* f); +IRM_DLL_EXPORT IRM_RESULT YAMLSetRepresentativeVolume_F(int* id, double* rv, int* dim); +IRM_DLL_EXPORT IRM_RESULT YAMLSetSaturation_F(int* id, double* sat, int* dim); +IRM_DLL_EXPORT IRM_RESULT YAMLSetScreenOn_F(int* id, int* tf); +IRM_DLL_EXPORT IRM_RESULT YAMLSetSelectedOutputOn_F(int* id, int* tf); +IRM_DLL_EXPORT IRM_RESULT YAMLSetSpeciesSaveOn_F(int* id, int* save_on); +IRM_DLL_EXPORT IRM_RESULT YAMLSetTemperature_F(int* id, double* t, int* dim); +IRM_DLL_EXPORT IRM_RESULT YAMLSetTime_F(int* id, double* time); +IRM_DLL_EXPORT IRM_RESULT YAMLSetTimeConversion_F(int* id, double* conv_factor); +IRM_DLL_EXPORT IRM_RESULT YAMLSetTimeStep_F(int* id, double* time_step); +IRM_DLL_EXPORT IRM_RESULT YAMLSetUnitsExchange_F(int* id, int* option); +IRM_DLL_EXPORT IRM_RESULT YAMLSetUnitsGasPhase_F(int* id, int* option); +IRM_DLL_EXPORT IRM_RESULT YAMLSetUnitsKinetics_F(int* id, int* option); +IRM_DLL_EXPORT IRM_RESULT YAMLSetUnitsPPassemblage_F(int* id, int* option); +IRM_DLL_EXPORT IRM_RESULT YAMLSetUnitsSolution_F(int* id, int* option); +IRM_DLL_EXPORT IRM_RESULT YAMLSetUnitsSSassemblage_F(int* id, int* option); +IRM_DLL_EXPORT IRM_RESULT YAMLSetUnitsSurface_F(int* id, int* option); +IRM_DLL_EXPORT IRM_RESULT YAMLSpeciesConcentrations2Module_F(int* id, double* species_conc, int* dim); +IRM_DLL_EXPORT IRM_RESULT YAMLStateSave_F(int* id, int* istate); +IRM_DLL_EXPORT IRM_RESULT YAMLStateApply_F(int* id, int* istate); +IRM_DLL_EXPORT IRM_RESULT YAMLStateDelete_F(int* id, int* istate); +IRM_DLL_EXPORT IRM_RESULT YAMLUseSolutionDensityVolume_F(int* id, int* tf); +IRM_DLL_EXPORT IRM_RESULT YAMLWarningMessage_F(int* id, const char* warnstr); + +#if defined(__cplusplus) +} +#endif + +#endif // INC_YAML_interface_F_H +#endif // USE_YAML diff --git a/src/bmi.hxx b/src/bmi.hxx new file mode 100644 index 000000000..43a313ae7 --- /dev/null +++ b/src/bmi.hxx @@ -0,0 +1,83 @@ +// The Basic Model Interface (BMI) C++ specification. +// +// This language specification is derived from the Scientific +// Interface Definition Language (SIDL) file bmi.sidl located at +// https://github.com/csdms/bmi. +#ifndef BMI_HXX +#define BMI_HXX +#include +#include + +namespace bmi { + + const int BMI_SUCCESS = 0; + const int BMI_FAILURE = 1; + + const int MAX_COMPONENT_NAME = 2048; + const int MAX_VAR_NAME = 2048; + const int MAX_UNITS_NAME = 2048; + const int MAX_TYPE_NAME = 2048; + + class Bmi { + public: + // Model control functions. + virtual void Initialize(std::string config_file) = 0; + virtual void Update() = 0; + virtual void UpdateUntil(double time) = 0; + virtual void Finalize() = 0; + + // Model information functions. + virtual std::string GetComponentName() = 0; + virtual int GetInputItemCount() = 0; + virtual int GetOutputItemCount() = 0; + virtual std::vector GetInputVarNames() = 0; + virtual std::vector GetOutputVarNames() = 0; + + // Variable information functions + virtual int GetVarGrid(std::string name) = 0; + virtual std::string GetVarType(std::string name) = 0; + virtual std::string GetVarUnits(std::string name) = 0; + virtual int GetVarItemsize(std::string name) = 0; + virtual int GetVarNbytes(std::string name) = 0; + virtual std::string GetVarLocation(std::string name) = 0; + + virtual double GetCurrentTime() = 0; + virtual double GetStartTime() = 0; + virtual double GetEndTime() = 0; + virtual std::string GetTimeUnits() = 0; + virtual double GetTimeStep() = 0; + + // Variable getters + virtual void GetValue(std::string name, void* dest) = 0; + virtual void* GetValuePtr(std::string name) = 0; + virtual void GetValueAtIndices(std::string name, void* dest, int* inds, int count) = 0; + + // Variable setters + virtual void SetValue(std::string name, void* src) = 0; + virtual void SetValueAtIndices(std::string name, int* inds, int count, void* src) = 0; + + // Grid information functions + virtual int GetGridRank(const int grid) = 0; + virtual int GetGridSize(const int grid) = 0; + virtual std::string GetGridType(const int grid) = 0; + + virtual void GetGridShape(const int grid, int* shape) = 0; + virtual void GetGridSpacing(const int grid, double* spacing) = 0; + virtual void GetGridOrigin(const int grid, double* origin) = 0; + + virtual void GetGridX(const int grid, double* x) = 0; + virtual void GetGridY(const int grid, double* y) = 0; + virtual void GetGridZ(const int grid, double* z) = 0; + + virtual int GetGridNodeCount(const int grid) = 0; + virtual int GetGridEdgeCount(const int grid) = 0; + virtual int GetGridFaceCount(const int grid) = 0; + + virtual void GetGridEdgeNodes(const int grid, int* edge_nodes) = 0; + virtual void GetGridFaceEdges(const int grid, int* face_edges) = 0; + virtual void GetGridFaceNodes(const int grid, int* face_nodes) = 0; + virtual void GetGridNodesPerFace(const int grid, int* nodes_per_face) = 0; + }; +} + +#endif \ No newline at end of file diff --git a/src/numpy.i b/src/numpy.i new file mode 100644 index 000000000..c8c26cbcd --- /dev/null +++ b/src/numpy.i @@ -0,0 +1,2970 @@ +/* -*- C -*- (not really, but good for syntax highlighting) */ + +/* + * Copyright (c) 2005-2015, NumPy Developers. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * Neither the name of the NumPy Developers nor the names of any + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef SWIGPYTHON + +%{ +#ifndef SWIG_FILE_WITH_INIT +#define NO_IMPORT_ARRAY +#endif +#include "stdio.h" +#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION +#include +%} + +/**********************************************************************/ + +%fragment("NumPy_Backward_Compatibility", "header") +{ +%#if NPY_API_VERSION < NPY_1_7_API_VERSION +%#define NPY_ARRAY_DEFAULT NPY_DEFAULT +%#define NPY_ARRAY_FARRAY NPY_FARRAY +%#define NPY_FORTRANORDER NPY_FORTRAN +%#endif +} + +/**********************************************************************/ + +/* The following code originally appeared in + * enthought/kiva/agg/src/numeric.i written by Eric Jones. It was + * translated from C++ to C by John Hunter. Bill Spotz has modified + * it to fix some minor bugs, upgrade from Numeric to numpy (all + * versions), add some comments and functionality, and convert from + * direct code insertion to SWIG fragments. + */ + +%fragment("NumPy_Macros", "header") +{ +/* Macros to extract array attributes. + */ +%#if NPY_API_VERSION < NPY_1_7_API_VERSION +%#define is_array(a) ((a) && PyArray_Check((PyArrayObject*)a)) +%#define array_type(a) (int)(PyArray_TYPE((PyArrayObject*)a)) +%#define array_numdims(a) (((PyArrayObject*)a)->nd) +%#define array_dimensions(a) (((PyArrayObject*)a)->dimensions) +%#define array_size(a,i) (((PyArrayObject*)a)->dimensions[i]) +%#define array_strides(a) (((PyArrayObject*)a)->strides) +%#define array_stride(a,i) (((PyArrayObject*)a)->strides[i]) +%#define array_data(a) (((PyArrayObject*)a)->data) +%#define array_descr(a) (((PyArrayObject*)a)->descr) +%#define array_flags(a) (((PyArrayObject*)a)->flags) +%#define array_clearflags(a,f) (((PyArrayObject*)a)->flags) &= ~f +%#define array_enableflags(a,f) (((PyArrayObject*)a)->flags) = f +%#define array_is_fortran(a) (PyArray_ISFORTRAN((PyArrayObject*)a)) +%#else +%#define is_array(a) ((a) && PyArray_Check(a)) +%#define array_type(a) PyArray_TYPE((PyArrayObject*)a) +%#define array_numdims(a) PyArray_NDIM((PyArrayObject*)a) +%#define array_dimensions(a) PyArray_DIMS((PyArrayObject*)a) +%#define array_strides(a) PyArray_STRIDES((PyArrayObject*)a) +%#define array_stride(a,i) PyArray_STRIDE((PyArrayObject*)a,i) +%#define array_size(a,i) PyArray_DIM((PyArrayObject*)a,i) +%#define array_data(a) PyArray_DATA((PyArrayObject*)a) +%#define array_descr(a) PyArray_DESCR((PyArrayObject*)a) +%#define array_flags(a) PyArray_FLAGS((PyArrayObject*)a) +%#define array_enableflags(a,f) PyArray_ENABLEFLAGS((PyArrayObject*)a,f) +%#define array_clearflags(a,f) PyArray_CLEARFLAGS((PyArrayObject*)a,f) +%#define array_is_fortran(a) (PyArray_IS_F_CONTIGUOUS((PyArrayObject*)a)) +%#endif +%#define array_is_contiguous(a) (PyArray_ISCONTIGUOUS((PyArrayObject*)a)) +%#define array_is_native(a) (PyArray_ISNOTSWAPPED((PyArrayObject*)a)) +} + +/**********************************************************************/ + +%fragment("NumPy_Utilities", + "header") +{ + /* Given a PyObject, return a string describing its type. + */ + const char* pytype_string(PyObject* py_obj) + { + if (py_obj == NULL ) return "C NULL value"; + if (py_obj == Py_None ) return "Python None" ; + if (PyCallable_Check(py_obj)) return "callable" ; + if (PyBytes_Check( py_obj)) return "string" ; + if (PyLong_Check( py_obj)) return "int" ; + if (PyFloat_Check( py_obj)) return "float" ; + if (PyDict_Check( py_obj)) return "dict" ; + if (PyList_Check( py_obj)) return "list" ; + if (PyTuple_Check( py_obj)) return "tuple" ; + + return "unknown type"; + } + + /* Given a NumPy typecode, return a string describing the type. + */ + const char* typecode_string(int typecode) + { + static const char* type_names[25] = {"bool", + "byte", + "unsigned byte", + "short", + "unsigned short", + "int", + "unsigned int", + "long", + "unsigned long", + "long long", + "unsigned long long", + "float", + "double", + "long double", + "complex float", + "complex double", + "complex long double", + "object", + "string", + "unicode", + "void", + "ntypes", + "notype", + "char", + "unknown"}; + return typecode < 24 ? type_names[typecode] : type_names[24]; + } + + /* Make sure input has correct numpy type. This now just calls + PyArray_EquivTypenums(). + */ + int type_match(int actual_type, + int desired_type) + { + return PyArray_EquivTypenums(actual_type, desired_type); + } + +void free_cap(PyObject * cap) + { + void* array = (void*) PyCapsule_GetPointer(cap,SWIGPY_CAPSULE_NAME); + if (array != NULL) free(array); + } + + +} + +/**********************************************************************/ + +%fragment("NumPy_Object_to_Array", + "header", + fragment="NumPy_Backward_Compatibility", + fragment="NumPy_Macros", + fragment="NumPy_Utilities") +{ + /* Given a PyObject pointer, cast it to a PyArrayObject pointer if + * legal. If not, set the python error string appropriately and + * return NULL. + */ + PyArrayObject* obj_to_array_no_conversion(PyObject* input, + int typecode) + { + PyArrayObject* ary = NULL; + if (is_array(input) && (typecode == NPY_NOTYPE || + PyArray_EquivTypenums(array_type(input), typecode))) + { + ary = (PyArrayObject*) input; + } + else if is_array(input) + { + const char* desired_type = typecode_string(typecode); + const char* actual_type = typecode_string(array_type(input)); + PyErr_Format(PyExc_TypeError, + "Array of type '%s' required. Array of type '%s' given", + desired_type, actual_type); + ary = NULL; + } + else + { + const char* desired_type = typecode_string(typecode); + const char* actual_type = pytype_string(input); + PyErr_Format(PyExc_TypeError, + "Array of type '%s' required. A '%s' was given", + desired_type, + actual_type); + ary = NULL; + } + return ary; + } + + /* Convert the given PyObject to a NumPy array with the given + * typecode. On success, return a valid PyArrayObject* with the + * correct type. On failure, the python error string will be set and + * the routine returns NULL. + */ + PyArrayObject* obj_to_array_allow_conversion(PyObject* input, + int typecode, + int* is_new_object) + { + PyArrayObject* ary = NULL; + PyObject* py_obj; + if (is_array(input) && (typecode == NPY_NOTYPE || + PyArray_EquivTypenums(array_type(input),typecode))) + { + ary = (PyArrayObject*) input; + *is_new_object = 0; + } + else + { + py_obj = PyArray_FROMANY(input, typecode, 0, 0, NPY_ARRAY_DEFAULT); + /* If NULL, PyArray_FromObject will have set python error value.*/ + ary = (PyArrayObject*) py_obj; + *is_new_object = 1; + } + return ary; + } + + /* Given a PyArrayObject, check to see if it is contiguous. If so, + * return the input pointer and flag it as not a new object. If it is + * not contiguous, create a new PyArrayObject using the original data, + * flag it as a new object and return the pointer. + */ + PyArrayObject* make_contiguous(PyArrayObject* ary, + int* is_new_object, + int min_dims, + int max_dims) + { + PyArrayObject* result; + if (array_is_contiguous(ary)) + { + result = ary; + *is_new_object = 0; + } + else + { + result = (PyArrayObject*) PyArray_ContiguousFromObject((PyObject*)ary, + array_type(ary), + min_dims, + max_dims); + *is_new_object = 1; + } + return result; + } + + /* Given a PyArrayObject, check to see if it is Fortran-contiguous. + * If so, return the input pointer, but do not flag it as not a new + * object. If it is not Fortran-contiguous, create a new + * PyArrayObject using the original data, flag it as a new object + * and return the pointer. + */ + PyArrayObject* make_fortran(PyArrayObject* ary, + int* is_new_object) + { + PyArrayObject* result; + if (array_is_fortran(ary)) + { + result = ary; + *is_new_object = 0; + } + else + { + Py_INCREF(array_descr(ary)); + result = (PyArrayObject*) PyArray_FromArray(ary, + array_descr(ary), +%#if NPY_API_VERSION < NPY_1_7_API_VERSION + NPY_FORTRANORDER); +%#else + NPY_ARRAY_F_CONTIGUOUS); +%#endif + *is_new_object = 1; + } + return result; + } + + /* Convert a given PyObject to a contiguous PyArrayObject of the + * specified type. If the input object is not a contiguous + * PyArrayObject, a new one will be created and the new object flag + * will be set. + */ + PyArrayObject* obj_to_array_contiguous_allow_conversion(PyObject* input, + int typecode, + int* is_new_object) + { + int is_new1 = 0; + int is_new2 = 0; + PyArrayObject* ary2; + PyArrayObject* ary1 = obj_to_array_allow_conversion(input, + typecode, + &is_new1); + if (ary1) + { + ary2 = make_contiguous(ary1, &is_new2, 0, 0); + if ( is_new1 && is_new2) + { + Py_DECREF(ary1); + } + ary1 = ary2; + } + *is_new_object = is_new1 || is_new2; + return ary1; + } + + /* Convert a given PyObject to a Fortran-ordered PyArrayObject of the + * specified type. If the input object is not a Fortran-ordered + * PyArrayObject, a new one will be created and the new object flag + * will be set. + */ + PyArrayObject* obj_to_array_fortran_allow_conversion(PyObject* input, + int typecode, + int* is_new_object) + { + int is_new1 = 0; + int is_new2 = 0; + PyArrayObject* ary2; + PyArrayObject* ary1 = obj_to_array_allow_conversion(input, + typecode, + &is_new1); + if (ary1) + { + ary2 = make_fortran(ary1, &is_new2); + if (is_new1 && is_new2) + { + Py_DECREF(ary1); + } + ary1 = ary2; + } + *is_new_object = is_new1 || is_new2; + return ary1; + } +} /* end fragment */ + +/**********************************************************************/ + +%fragment("NumPy_Array_Requirements", + "header", + fragment="NumPy_Backward_Compatibility", + fragment="NumPy_Macros") +{ + /* Test whether a python object is contiguous. If array is + * contiguous, return 1. Otherwise, set the python error string and + * return 0. + */ + int require_contiguous(PyArrayObject* ary) + { + int contiguous = 1; + if (!array_is_contiguous(ary)) + { + PyErr_SetString(PyExc_TypeError, + "Array must be contiguous. A non-contiguous array was given"); + contiguous = 0; + } + return contiguous; + } + + /* Test whether a python object is (C_ or F_) contiguous. If array is + * contiguous, return 1. Otherwise, set the python error string and + * return 0. + */ + int require_c_or_f_contiguous(PyArrayObject* ary) + { + int contiguous = 1; + if (!(array_is_contiguous(ary) || array_is_fortran(ary))) + { + PyErr_SetString(PyExc_TypeError, + "Array must be contiguous (C_ or F_). A non-contiguous array was given"); + contiguous = 0; + } + return contiguous; + } + + /* Require that a numpy array is not byte-swapped. If the array is + * not byte-swapped, return 1. Otherwise, set the python error string + * and return 0. + */ + int require_native(PyArrayObject* ary) + { + int native = 1; + if (!array_is_native(ary)) + { + PyErr_SetString(PyExc_TypeError, + "Array must have native byteorder. " + "A byte-swapped array was given"); + native = 0; + } + return native; + } + + /* Require the given PyArrayObject to have a specified number of + * dimensions. If the array has the specified number of dimensions, + * return 1. Otherwise, set the python error string and return 0. + */ + int require_dimensions(PyArrayObject* ary, + int exact_dimensions) + { + int success = 1; + if (array_numdims(ary) != exact_dimensions) + { + PyErr_Format(PyExc_TypeError, + "Array must have %d dimensions. Given array has %d dimensions", + exact_dimensions, + array_numdims(ary)); + success = 0; + } + return success; + } + + /* Require the given PyArrayObject to have one of a list of specified + * number of dimensions. If the array has one of the specified number + * of dimensions, return 1. Otherwise, set the python error string + * and return 0. + */ + int require_dimensions_n(PyArrayObject* ary, + int* exact_dimensions, + int n) + { + int success = 0; + int i; + char dims_str[255] = ""; + char s[255]; + for (i = 0; i < n && !success; i++) + { + if (array_numdims(ary) == exact_dimensions[i]) + { + success = 1; + } + } + if (!success) + { + for (i = 0; i < n-1; i++) + { + sprintf(s, "%d, ", exact_dimensions[i]); + strcat(dims_str,s); + } + sprintf(s, " or %d", exact_dimensions[n-1]); + strcat(dims_str,s); + PyErr_Format(PyExc_TypeError, + "Array must have %s dimensions. Given array has %d dimensions", + dims_str, + array_numdims(ary)); + } + return success; + } + + /* Require the given PyArrayObject to have a specified shape. If the + * array has the specified shape, return 1. Otherwise, set the python + * error string and return 0. + */ + int require_size(PyArrayObject* ary, + npy_intp* size, + int n) + { + int i; + int success = 1; + size_t len; + char desired_dims[255] = "["; + char s[255]; + char actual_dims[255] = "["; + for(i=0; i < n;i++) + { + if (size[i] != -1 && size[i] != array_size(ary,i)) + { + success = 0; + } + } + if (!success) + { + for (i = 0; i < n; i++) + { + if (size[i] == -1) + { + sprintf(s, "*,"); + } + else + { + sprintf(s, "%ld,", (long int)size[i]); + } + strcat(desired_dims,s); + } + len = strlen(desired_dims); + desired_dims[len-1] = ']'; + for (i = 0; i < n; i++) + { + sprintf(s, "%ld,", (long int)array_size(ary,i)); + strcat(actual_dims,s); + } + len = strlen(actual_dims); + actual_dims[len-1] = ']'; + PyErr_Format(PyExc_TypeError, + "Array must have shape of %s. Given array has shape of %s", + desired_dims, + actual_dims); + } + return success; + } + + /* Require the given PyArrayObject to be Fortran ordered. If the + * the PyArrayObject is already Fortran ordered, do nothing. Else, + * set the Fortran ordering flag and recompute the strides. + */ + int require_fortran(PyArrayObject* ary) + { + int success = 1; + int nd = array_numdims(ary); + int i; + npy_intp * strides = array_strides(ary); + if (array_is_fortran(ary)) return success; + int n_non_one = 0; + /* Set the Fortran ordered flag */ + const npy_intp *dims = array_dimensions(ary); + for (i=0; i < nd; ++i) + n_non_one += (dims[i] != 1) ? 1 : 0; + if (n_non_one > 1) + array_clearflags(ary,NPY_ARRAY_CARRAY); + array_enableflags(ary,NPY_ARRAY_FARRAY); + /* Recompute the strides */ + strides[0] = strides[nd-1]; + for (i=1; i < nd; ++i) + strides[i] = strides[i-1] * array_size(ary,i-1); + return success; + } +} + +/* Combine all NumPy fragments into one for convenience */ +%fragment("NumPy_Fragments", + "header", + fragment="NumPy_Backward_Compatibility", + fragment="NumPy_Macros", + fragment="NumPy_Utilities", + fragment="NumPy_Object_to_Array", + fragment="NumPy_Array_Requirements") +{ +} + +/* End John Hunter translation (with modifications by Bill Spotz) + */ + +/* %numpy_typemaps() macro + * + * This macro defines a family of 75 typemaps that allow C arguments + * of the form + * + * 1. (DATA_TYPE IN_ARRAY1[ANY]) + * 2. (DATA_TYPE* IN_ARRAY1, DIM_TYPE DIM1) + * 3. (DIM_TYPE DIM1, DATA_TYPE* IN_ARRAY1) + * + * 4. (DATA_TYPE IN_ARRAY2[ANY][ANY]) + * 5. (DATA_TYPE* IN_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + * 6. (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_ARRAY2) + * 7. (DATA_TYPE* IN_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + * 8. (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_FARRAY2) + * + * 9. (DATA_TYPE IN_ARRAY3[ANY][ANY][ANY]) + * 10. (DATA_TYPE* IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + * 11. (DATA_TYPE** IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + * 12. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_ARRAY3) + * 13. (DATA_TYPE* IN_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + * 14. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_FARRAY3) + * + * 15. (DATA_TYPE IN_ARRAY4[ANY][ANY][ANY][ANY]) + * 16. (DATA_TYPE* IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) + * 17. (DATA_TYPE** IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) + * 18. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, , DIM_TYPE DIM4, DATA_TYPE* IN_ARRAY4) + * 19. (DATA_TYPE* IN_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) + * 20. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* IN_FARRAY4) + * + * 21. (DATA_TYPE INPLACE_ARRAY1[ANY]) + * 22. (DATA_TYPE* INPLACE_ARRAY1, DIM_TYPE DIM1) + * 23. (DIM_TYPE DIM1, DATA_TYPE* INPLACE_ARRAY1) + * + * 24. (DATA_TYPE INPLACE_ARRAY2[ANY][ANY]) + * 25. (DATA_TYPE* INPLACE_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + * 26. (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_ARRAY2) + * 27. (DATA_TYPE* INPLACE_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + * 28. (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_FARRAY2) + * + * 29. (DATA_TYPE INPLACE_ARRAY3[ANY][ANY][ANY]) + * 30. (DATA_TYPE* INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + * 31. (DATA_TYPE** INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + * 32. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_ARRAY3) + * 33. (DATA_TYPE* INPLACE_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + * 34. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_FARRAY3) + * + * 35. (DATA_TYPE INPLACE_ARRAY4[ANY][ANY][ANY][ANY]) + * 36. (DATA_TYPE* INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) + * 37. (DATA_TYPE** INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) + * 38. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* INPLACE_ARRAY4) + * 39. (DATA_TYPE* INPLACE_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) + * 40. (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* INPLACE_FARRAY4) + * + * 41. (DATA_TYPE ARGOUT_ARRAY1[ANY]) + * 42. (DATA_TYPE* ARGOUT_ARRAY1, DIM_TYPE DIM1) + * 43. (DIM_TYPE DIM1, DATA_TYPE* ARGOUT_ARRAY1) + * + * 44. (DATA_TYPE ARGOUT_ARRAY2[ANY][ANY]) + * + * 45. (DATA_TYPE ARGOUT_ARRAY3[ANY][ANY][ANY]) + * + * 46. (DATA_TYPE ARGOUT_ARRAY4[ANY][ANY][ANY][ANY]) + * + * 47. (DATA_TYPE** ARGOUTVIEW_ARRAY1, DIM_TYPE* DIM1) + * 48. (DIM_TYPE* DIM1, DATA_TYPE** ARGOUTVIEW_ARRAY1) + * + * 49. (DATA_TYPE** ARGOUTVIEW_ARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) + * 50. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_ARRAY2) + * 51. (DATA_TYPE** ARGOUTVIEW_FARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) + * 52. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_FARRAY2) + * + * 53. (DATA_TYPE** ARGOUTVIEW_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) + * 54. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_ARRAY3) + * 55. (DATA_TYPE** ARGOUTVIEW_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) + * 56. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_FARRAY3) + * + * 57. (DATA_TYPE** ARGOUTVIEW_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) + * 58. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEW_ARRAY4) + * 59. (DATA_TYPE** ARGOUTVIEW_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) + * 60. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEW_FARRAY4) + * + * 61. (DATA_TYPE** ARGOUTVIEWM_ARRAY1, DIM_TYPE* DIM1) + * 62. (DIM_TYPE* DIM1, DATA_TYPE** ARGOUTVIEWM_ARRAY1) + * + * 63. (DATA_TYPE** ARGOUTVIEWM_ARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) + * 64. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEWM_ARRAY2) + * 65. (DATA_TYPE** ARGOUTVIEWM_FARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) + * 66. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEWM_FARRAY2) + * + * 67. (DATA_TYPE** ARGOUTVIEWM_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) + * 68. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEWM_ARRAY3) + * 69. (DATA_TYPE** ARGOUTVIEWM_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) + * 70. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEWM_FARRAY3) + * + * 71. (DATA_TYPE** ARGOUTVIEWM_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) + * 72. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEWM_ARRAY4) + * 73. (DATA_TYPE** ARGOUTVIEWM_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) + * 74. (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEWM_FARRAY4) + * + * 75. (DATA_TYPE* INPLACE_ARRAY_FLAT, DIM_TYPE DIM_FLAT) + * + * where "DATA_TYPE" is any type supported by the NumPy module, and + * "DIM_TYPE" is any int-like type suitable for specifying dimensions. + * The difference between "ARRAY" typemaps and "FARRAY" typemaps is + * that the "FARRAY" typemaps expect Fortran ordering of + * multidimensional arrays. In python, the dimensions will not need + * to be specified (except for the "DATA_TYPE* ARGOUT_ARRAY1" + * typemaps). The IN_ARRAYs can be a numpy array or any sequence that + * can be converted to a numpy array of the specified type. The + * INPLACE_ARRAYs must be numpy arrays of the appropriate type. The + * ARGOUT_ARRAYs will be returned as new numpy arrays of the + * appropriate type. + * + * These typemaps can be applied to existing functions using the + * %apply directive. For example: + * + * %apply (double* IN_ARRAY1, int DIM1) {(double* series, int length)}; + * double prod(double* series, int length); + * + * %apply (int DIM1, int DIM2, double* INPLACE_ARRAY2) + * {(int rows, int cols, double* matrix )}; + * void floor(int rows, int cols, double* matrix, double f); + * + * %apply (double IN_ARRAY3[ANY][ANY][ANY]) + * {(double tensor[2][2][2] )}; + * %apply (double ARGOUT_ARRAY3[ANY][ANY][ANY]) + * {(double low[2][2][2] )}; + * %apply (double ARGOUT_ARRAY3[ANY][ANY][ANY]) + * {(double upp[2][2][2] )}; + * void luSplit(double tensor[2][2][2], + * double low[2][2][2], + * double upp[2][2][2] ); + * + * or directly with + * + * double prod(double* IN_ARRAY1, int DIM1); + * + * void floor(int DIM1, int DIM2, double* INPLACE_ARRAY2, double f); + * + * void luSplit(double IN_ARRAY3[ANY][ANY][ANY], + * double ARGOUT_ARRAY3[ANY][ANY][ANY], + * double ARGOUT_ARRAY3[ANY][ANY][ANY]); + */ + +%define %numpy_typemaps(DATA_TYPE, DATA_TYPECODE, DIM_TYPE) + +/************************/ +/* Input Array Typemaps */ +/************************/ + +/* Typemap suite for (DATA_TYPE IN_ARRAY1[ANY]) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE IN_ARRAY1[ANY]) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE IN_ARRAY1[ANY]) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[1] = { $1_dim0 }; + array = obj_to_array_contiguous_allow_conversion($input, + DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 1) || + !require_size(array, size, 1)) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} +%typemap(freearg) + (DATA_TYPE IN_ARRAY1[ANY]) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE* IN_ARRAY1, DIM_TYPE DIM1) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* IN_ARRAY1, DIM_TYPE DIM1) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* IN_ARRAY1, DIM_TYPE DIM1) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[1] = { -1 }; + array = obj_to_array_contiguous_allow_conversion($input, + DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 1) || + !require_size(array, size, 1)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); +} +%typemap(freearg) + (DATA_TYPE* IN_ARRAY1, DIM_TYPE DIM1) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DIM_TYPE DIM1, DATA_TYPE* IN_ARRAY1) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DATA_TYPE* IN_ARRAY1) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DATA_TYPE* IN_ARRAY1) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[1] = {-1}; + array = obj_to_array_contiguous_allow_conversion($input, + DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 1) || + !require_size(array, size, 1)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DATA_TYPE*) array_data(array); +} +%typemap(freearg) + (DIM_TYPE DIM1, DATA_TYPE* IN_ARRAY1) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE IN_ARRAY2[ANY][ANY]) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE IN_ARRAY2[ANY][ANY]) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE IN_ARRAY2[ANY][ANY]) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[2] = { $1_dim0, $1_dim1 }; + array = obj_to_array_contiguous_allow_conversion($input, + DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 2) || + !require_size(array, size, 2)) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} +%typemap(freearg) + (DATA_TYPE IN_ARRAY2[ANY][ANY]) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE* IN_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* IN_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* IN_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[2] = { -1, -1 }; + array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 2) || + !require_size(array, size, 2)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); +} +%typemap(freearg) + (DATA_TYPE* IN_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_ARRAY2) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_ARRAY2) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_ARRAY2) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[2] = { -1, -1 }; + array = obj_to_array_contiguous_allow_conversion($input, + DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 2) || + !require_size(array, size, 2)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DATA_TYPE*) array_data(array); +} +%typemap(freearg) + (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_ARRAY2) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE* IN_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* IN_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* IN_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[2] = { -1, -1 }; + array = obj_to_array_fortran_allow_conversion($input, + DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 2) || + !require_size(array, size, 2) || !require_fortran(array)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); +} +%typemap(freearg) + (DATA_TYPE* IN_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_FARRAY2) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_FARRAY2) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_FARRAY2) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[2] = { -1, -1 }; + array = obj_to_array_fortran_allow_conversion($input, + DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 2) || + !require_size(array, size, 2) || !require_fortran(array)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DATA_TYPE*) array_data(array); +} +%typemap(freearg) + (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* IN_FARRAY2) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE IN_ARRAY3[ANY][ANY][ANY]) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE IN_ARRAY3[ANY][ANY][ANY]) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE IN_ARRAY3[ANY][ANY][ANY]) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[3] = { $1_dim0, $1_dim1, $1_dim2 }; + array = obj_to_array_contiguous_allow_conversion($input, + DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 3) || + !require_size(array, size, 3)) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} +%typemap(freearg) + (DATA_TYPE IN_ARRAY3[ANY][ANY][ANY]) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE* IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[3] = { -1, -1, -1 }; + array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 3) || + !require_size(array, size, 3)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); + $4 = (DIM_TYPE) array_size(array,2); +} +%typemap(freearg) + (DATA_TYPE* IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE** IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE** IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) +{ + /* for now, only concerned with lists */ + $1 = PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE** IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + (DATA_TYPE** array=NULL, PyArrayObject** object_array=NULL, int* is_new_object_array=NULL) +{ + npy_intp size[2] = { -1, -1 }; + PyArrayObject* temp_array; + Py_ssize_t i; + int is_new_object; + + /* length of the list */ + $2 = PyList_Size($input); + + /* the arrays */ + array = (DATA_TYPE **)malloc($2*sizeof(DATA_TYPE *)); + object_array = (PyArrayObject **)calloc($2,sizeof(PyArrayObject *)); + is_new_object_array = (int *)calloc($2,sizeof(int)); + + if (array == NULL || object_array == NULL || is_new_object_array == NULL) + { + SWIG_fail; + } + + for (i=0; i<$2; i++) + { + temp_array = obj_to_array_contiguous_allow_conversion(PySequence_GetItem($input,i), DATA_TYPECODE, &is_new_object); + + /* the new array must be stored so that it can be destroyed in freearg */ + object_array[i] = temp_array; + is_new_object_array[i] = is_new_object; + + if (!temp_array || !require_dimensions(temp_array, 2)) SWIG_fail; + + /* store the size of the first array in the list, then use that for comparison. */ + if (i == 0) + { + size[0] = array_size(temp_array,0); + size[1] = array_size(temp_array,1); + } + + if (!require_size(temp_array, size, 2)) SWIG_fail; + + array[i] = (DATA_TYPE*) array_data(temp_array); + } + + $1 = (DATA_TYPE**) array; + $3 = (DIM_TYPE) size[0]; + $4 = (DIM_TYPE) size[1]; +} +%typemap(freearg) + (DATA_TYPE** IN_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) +{ + Py_ssize_t i; + + if (array$argnum!=NULL) free(array$argnum); + + /*freeing the individual arrays if needed */ + if (object_array$argnum!=NULL) + { + if (is_new_object_array$argnum!=NULL) + { + for (i=0; i<$2; i++) + { + if (object_array$argnum[i] != NULL && is_new_object_array$argnum[i]) + { Py_DECREF(object_array$argnum[i]); } + } + free(is_new_object_array$argnum); + } + free(object_array$argnum); + } +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, + * DATA_TYPE* IN_ARRAY3) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_ARRAY3) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_ARRAY3) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[3] = { -1, -1, -1 }; + array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 3) || + !require_size(array, size, 3)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DIM_TYPE) array_size(array,2); + $4 = (DATA_TYPE*) array_data(array); +} +%typemap(freearg) + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_ARRAY3) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE* IN_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* IN_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* IN_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[3] = { -1, -1, -1 }; + array = obj_to_array_fortran_allow_conversion($input, DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 3) || + !require_size(array, size, 3) | !require_fortran(array)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); + $4 = (DIM_TYPE) array_size(array,2); +} +%typemap(freearg) + (DATA_TYPE* IN_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, + * DATA_TYPE* IN_FARRAY3) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_FARRAY3) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_FARRAY3) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[3] = { -1, -1, -1 }; + array = obj_to_array_fortran_allow_conversion($input, + DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 3) || + !require_size(array, size, 3) || !require_fortran(array)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DIM_TYPE) array_size(array,2); + $4 = (DATA_TYPE*) array_data(array); +} +%typemap(freearg) + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* IN_FARRAY3) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE IN_ARRAY4[ANY][ANY][ANY][ANY]) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE IN_ARRAY4[ANY][ANY][ANY][ANY]) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE IN_ARRAY4[ANY][ANY][ANY][ANY]) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[4] = { $1_dim0, $1_dim1, $1_dim2 , $1_dim3}; + array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 4) || + !require_size(array, size, 4)) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} +%typemap(freearg) + (DATA_TYPE IN_ARRAY4[ANY][ANY][ANY][ANY]) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE* IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3, DIM_TYPE DIM4) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[4] = { -1, -1, -1, -1 }; + array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 4) || + !require_size(array, size, 4)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); + $4 = (DIM_TYPE) array_size(array,2); + $5 = (DIM_TYPE) array_size(array,3); +} +%typemap(freearg) + (DATA_TYPE* IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE** IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3, DIM_TYPE DIM4) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE** IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) +{ + /* for now, only concerned with lists */ + $1 = PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE** IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) + (DATA_TYPE** array=NULL, PyArrayObject** object_array=NULL, int* is_new_object_array=NULL) +{ + npy_intp size[3] = { -1, -1, -1 }; + PyArrayObject* temp_array; + Py_ssize_t i; + int is_new_object; + + /* length of the list */ + $2 = PyList_Size($input); + + /* the arrays */ + array = (DATA_TYPE **)malloc($2*sizeof(DATA_TYPE *)); + object_array = (PyArrayObject **)calloc($2,sizeof(PyArrayObject *)); + is_new_object_array = (int *)calloc($2,sizeof(int)); + + if (array == NULL || object_array == NULL || is_new_object_array == NULL) + { + SWIG_fail; + } + + for (i=0; i<$2; i++) + { + temp_array = obj_to_array_contiguous_allow_conversion(PySequence_GetItem($input,i), DATA_TYPECODE, &is_new_object); + + /* the new array must be stored so that it can be destroyed in freearg */ + object_array[i] = temp_array; + is_new_object_array[i] = is_new_object; + + if (!temp_array || !require_dimensions(temp_array, 3)) SWIG_fail; + + /* store the size of the first array in the list, then use that for comparison. */ + if (i == 0) + { + size[0] = array_size(temp_array,0); + size[1] = array_size(temp_array,1); + size[2] = array_size(temp_array,2); + } + + if (!require_size(temp_array, size, 3)) SWIG_fail; + + array[i] = (DATA_TYPE*) array_data(temp_array); + } + + $1 = (DATA_TYPE**) array; + $3 = (DIM_TYPE) size[0]; + $4 = (DIM_TYPE) size[1]; + $5 = (DIM_TYPE) size[2]; +} +%typemap(freearg) + (DATA_TYPE** IN_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) +{ + Py_ssize_t i; + + if (array$argnum!=NULL) free(array$argnum); + + /*freeing the individual arrays if needed */ + if (object_array$argnum!=NULL) + { + if (is_new_object_array$argnum!=NULL) + { + for (i=0; i<$2; i++) + { + if (object_array$argnum[i] != NULL && is_new_object_array$argnum[i]) + { Py_DECREF(object_array$argnum[i]); } + } + free(is_new_object_array$argnum); + } + free(object_array$argnum); + } +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, + * DATA_TYPE* IN_ARRAY4) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* IN_ARRAY4) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* IN_ARRAY4) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[4] = { -1, -1, -1 , -1}; + array = obj_to_array_contiguous_allow_conversion($input, DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 4) || + !require_size(array, size, 4)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DIM_TYPE) array_size(array,2); + $4 = (DIM_TYPE) array_size(array,3); + $5 = (DATA_TYPE*) array_data(array); +} +%typemap(freearg) + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* IN_ARRAY4) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DATA_TYPE* IN_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3, DIM_TYPE DIM4) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* IN_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* IN_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[4] = { -1, -1, -1, -1 }; + array = obj_to_array_fortran_allow_conversion($input, DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 4) || + !require_size(array, size, 4) | !require_fortran(array)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); + $4 = (DIM_TYPE) array_size(array,2); + $5 = (DIM_TYPE) array_size(array,3); +} +%typemap(freearg) + (DATA_TYPE* IN_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, + * DATA_TYPE* IN_FARRAY4) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* IN_FARRAY4) +{ + $1 = is_array($input) || PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* IN_FARRAY4) + (PyArrayObject* array=NULL, int is_new_object=0) +{ + npy_intp size[4] = { -1, -1, -1 , -1 }; + array = obj_to_array_fortran_allow_conversion($input, DATA_TYPECODE, + &is_new_object); + if (!array || !require_dimensions(array, 4) || + !require_size(array, size, 4) || !require_fortran(array)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DIM_TYPE) array_size(array,2); + $4 = (DIM_TYPE) array_size(array,3); + $5 = (DATA_TYPE*) array_data(array); +} +%typemap(freearg) + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* IN_FARRAY4) +{ + if (is_new_object$argnum && array$argnum) + { Py_DECREF(array$argnum); } +} + +/***************************/ +/* In-Place Array Typemaps */ +/***************************/ + +/* Typemap suite for (DATA_TYPE INPLACE_ARRAY1[ANY]) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE INPLACE_ARRAY1[ANY]) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE INPLACE_ARRAY1[ANY]) + (PyArrayObject* array=NULL) +{ + npy_intp size[1] = { $1_dim0 }; + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,1) || !require_size(array, size, 1) || + !require_contiguous(array) || !require_native(array)) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} + +/* Typemap suite for (DATA_TYPE* INPLACE_ARRAY1, DIM_TYPE DIM1) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* INPLACE_ARRAY1, DIM_TYPE DIM1) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* INPLACE_ARRAY1, DIM_TYPE DIM1) + (PyArrayObject* array=NULL, int i=1) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,1) || !require_contiguous(array) + || !require_native(array)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = 1; + for (i=0; i < array_numdims(array); ++i) $2 *= array_size(array,i); +} + +/* Typemap suite for (DIM_TYPE DIM1, DATA_TYPE* INPLACE_ARRAY1) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DATA_TYPE* INPLACE_ARRAY1) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DATA_TYPE* INPLACE_ARRAY1) + (PyArrayObject* array=NULL, int i=0) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,1) || !require_contiguous(array) + || !require_native(array)) SWIG_fail; + $1 = 1; + for (i=0; i < array_numdims(array); ++i) $1 *= array_size(array,i); + $2 = (DATA_TYPE*) array_data(array); +} + +/* Typemap suite for (DATA_TYPE INPLACE_ARRAY2[ANY][ANY]) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE INPLACE_ARRAY2[ANY][ANY]) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE INPLACE_ARRAY2[ANY][ANY]) + (PyArrayObject* array=NULL) +{ + npy_intp size[2] = { $1_dim0, $1_dim1 }; + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,2) || !require_size(array, size, 2) || + !require_contiguous(array) || !require_native(array)) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} + +/* Typemap suite for (DATA_TYPE* INPLACE_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* INPLACE_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* INPLACE_ARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,2) || !require_contiguous(array) + || !require_native(array)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_ARRAY2) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_ARRAY2) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_ARRAY2) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,2) || !require_contiguous(array) || + !require_native(array)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DATA_TYPE*) array_data(array); +} + +/* Typemap suite for (DATA_TYPE* INPLACE_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* INPLACE_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* INPLACE_FARRAY2, DIM_TYPE DIM1, DIM_TYPE DIM2) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,2) || !require_contiguous(array) + || !require_native(array) || !require_fortran(array)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_FARRAY2) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_FARRAY2) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DATA_TYPE* INPLACE_FARRAY2) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,2) || !require_contiguous(array) || + !require_native(array) || !require_fortran(array)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DATA_TYPE*) array_data(array); +} + +/* Typemap suite for (DATA_TYPE INPLACE_ARRAY3[ANY][ANY][ANY]) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE INPLACE_ARRAY3[ANY][ANY][ANY]) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE INPLACE_ARRAY3[ANY][ANY][ANY]) + (PyArrayObject* array=NULL) +{ + npy_intp size[3] = { $1_dim0, $1_dim1, $1_dim2 }; + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,3) || !require_size(array, size, 3) || + !require_contiguous(array) || !require_native(array)) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} + +/* Typemap suite for (DATA_TYPE* INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,3) || !require_contiguous(array) || + !require_native(array)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); + $4 = (DIM_TYPE) array_size(array,2); +} + +/* Typemap suite for (DATA_TYPE** INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE** INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) +{ + $1 = PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE** INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + (DATA_TYPE** array=NULL, PyArrayObject** object_array=NULL) +{ + npy_intp size[2] = { -1, -1 }; + PyArrayObject* temp_array; + Py_ssize_t i; + + /* length of the list */ + $2 = PyList_Size($input); + + /* the arrays */ + array = (DATA_TYPE **)malloc($2*sizeof(DATA_TYPE *)); + object_array = (PyArrayObject **)calloc($2,sizeof(PyArrayObject *)); + + if (array == NULL || object_array == NULL) + { + SWIG_fail; + } + + for (i=0; i<$2; i++) + { + temp_array = obj_to_array_no_conversion(PySequence_GetItem($input,i), DATA_TYPECODE); + + /* the new array must be stored so that it can be destroyed in freearg */ + object_array[i] = temp_array; + + if ( !temp_array || !require_dimensions(temp_array, 2) || + !require_contiguous(temp_array) || + !require_native(temp_array) || + !PyArray_EquivTypenums(array_type(temp_array), DATA_TYPECODE) + ) SWIG_fail; + + /* store the size of the first array in the list, then use that for comparison. */ + if (i == 0) + { + size[0] = array_size(temp_array,0); + size[1] = array_size(temp_array,1); + } + + if (!require_size(temp_array, size, 2)) SWIG_fail; + + array[i] = (DATA_TYPE*) array_data(temp_array); + } + + $1 = (DATA_TYPE**) array; + $3 = (DIM_TYPE) size[0]; + $4 = (DIM_TYPE) size[1]; +} +%typemap(freearg) + (DATA_TYPE** INPLACE_ARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) +{ + if (array$argnum!=NULL) free(array$argnum); + if (object_array$argnum!=NULL) free(object_array$argnum); +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, + * DATA_TYPE* INPLACE_ARRAY3) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_ARRAY3) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_ARRAY3) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,3) || !require_contiguous(array) + || !require_native(array)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DIM_TYPE) array_size(array,2); + $4 = (DATA_TYPE*) array_data(array); +} + +/* Typemap suite for (DATA_TYPE* INPLACE_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* INPLACE_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* INPLACE_FARRAY3, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,3) || !require_contiguous(array) || + !require_native(array) || !require_fortran(array)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); + $4 = (DIM_TYPE) array_size(array,2); +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, + * DATA_TYPE* INPLACE_FARRAY3) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_FARRAY3) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DATA_TYPE* INPLACE_FARRAY3) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,3) || !require_contiguous(array) + || !require_native(array) || !require_fortran(array)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DIM_TYPE) array_size(array,2); + $4 = (DATA_TYPE*) array_data(array); +} + +/* Typemap suite for (DATA_TYPE INPLACE_ARRAY4[ANY][ANY][ANY][ANY]) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE INPLACE_ARRAY4[ANY][ANY][ANY][ANY]) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE INPLACE_ARRAY4[ANY][ANY][ANY][ANY]) + (PyArrayObject* array=NULL) +{ + npy_intp size[4] = { $1_dim0, $1_dim1, $1_dim2 , $1_dim3 }; + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,4) || !require_size(array, size, 4) || + !require_contiguous(array) || !require_native(array)) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} + +/* Typemap suite for (DATA_TYPE* INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3, DIM_TYPE DIM4) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,4) || !require_contiguous(array) || + !require_native(array)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); + $4 = (DIM_TYPE) array_size(array,2); + $5 = (DIM_TYPE) array_size(array,3); +} + +/* Typemap suite for (DATA_TYPE** INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3, DIM_TYPE DIM4) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE** INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) +{ + $1 = PySequence_Check($input); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE** INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) + (DATA_TYPE** array=NULL, PyArrayObject** object_array=NULL) +{ + npy_intp size[3] = { -1, -1, -1 }; + PyArrayObject* temp_array; + Py_ssize_t i; + + /* length of the list */ + $2 = PyList_Size($input); + + /* the arrays */ + array = (DATA_TYPE **)malloc($2*sizeof(DATA_TYPE *)); + object_array = (PyArrayObject **)calloc($2,sizeof(PyArrayObject *)); + + if (array == NULL || object_array == NULL) + { + SWIG_fail; + } + + for (i=0; i<$2; i++) + { + temp_array = obj_to_array_no_conversion(PySequence_GetItem($input,i), DATA_TYPECODE); + + /* the new array must be stored so that it can be destroyed in freearg */ + object_array[i] = temp_array; + + if ( !temp_array || !require_dimensions(temp_array, 3) || + !require_contiguous(temp_array) || + !require_native(temp_array) || + !PyArray_EquivTypenums(array_type(temp_array), DATA_TYPECODE) + ) SWIG_fail; + + /* store the size of the first array in the list, then use that for comparison. */ + if (i == 0) + { + size[0] = array_size(temp_array,0); + size[1] = array_size(temp_array,1); + size[2] = array_size(temp_array,2); + } + + if (!require_size(temp_array, size, 3)) SWIG_fail; + + array[i] = (DATA_TYPE*) array_data(temp_array); + } + + $1 = (DATA_TYPE**) array; + $3 = (DIM_TYPE) size[0]; + $4 = (DIM_TYPE) size[1]; + $5 = (DIM_TYPE) size[2]; +} +%typemap(freearg) + (DATA_TYPE** INPLACE_ARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) +{ + if (array$argnum!=NULL) free(array$argnum); + if (object_array$argnum!=NULL) free(object_array$argnum); +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, + * DATA_TYPE* INPLACE_ARRAY4) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* INPLACE_ARRAY4) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* INPLACE_ARRAY4) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,4) || !require_contiguous(array) + || !require_native(array)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DIM_TYPE) array_size(array,2); + $4 = (DIM_TYPE) array_size(array,3); + $5 = (DATA_TYPE*) array_data(array); +} + +/* Typemap suite for (DATA_TYPE* INPLACE_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, + * DIM_TYPE DIM3, DIM_TYPE DIM4) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* INPLACE_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* INPLACE_FARRAY4, DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,4) || !require_contiguous(array) || + !require_native(array) || !require_fortran(array)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = (DIM_TYPE) array_size(array,0); + $3 = (DIM_TYPE) array_size(array,1); + $4 = (DIM_TYPE) array_size(array,2); + $5 = (DIM_TYPE) array_size(array,3); +} + +/* Typemap suite for (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, + * DATA_TYPE* INPLACE_FARRAY4) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* INPLACE_FARRAY4) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DIM_TYPE DIM2, DIM_TYPE DIM3, DIM_TYPE DIM4, DATA_TYPE* INPLACE_FARRAY4) + (PyArrayObject* array=NULL) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_dimensions(array,4) || !require_contiguous(array) + || !require_native(array) || !require_fortran(array)) SWIG_fail; + $1 = (DIM_TYPE) array_size(array,0); + $2 = (DIM_TYPE) array_size(array,1); + $3 = (DIM_TYPE) array_size(array,2); + $4 = (DIM_TYPE) array_size(array,3); + $5 = (DATA_TYPE*) array_data(array); +} + +/*************************/ +/* Argout Array Typemaps */ +/*************************/ + +/* Typemap suite for (DATA_TYPE ARGOUT_ARRAY1[ANY]) + */ +%typemap(in,numinputs=0, + fragment="NumPy_Backward_Compatibility,NumPy_Macros") + (DATA_TYPE ARGOUT_ARRAY1[ANY]) + (PyObject* array = NULL) +{ + npy_intp dims[1] = { $1_dim0 }; + array = PyArray_SimpleNew(1, dims, DATA_TYPECODE); + if (!array) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} +%typemap(argout) + (DATA_TYPE ARGOUT_ARRAY1[ANY]) +{ + $result = SWIG_Python_AppendOutput($result,(PyObject*)array$argnum); +} + +/* Typemap suite for (DATA_TYPE* ARGOUT_ARRAY1, DIM_TYPE DIM1) + */ +%typemap(in,numinputs=1, + fragment="NumPy_Fragments") + (DATA_TYPE* ARGOUT_ARRAY1, DIM_TYPE DIM1) + (PyObject* array = NULL) +{ + npy_intp dims[1]; + if (!PyLong_Check($input)) + { + const char* typestring = pytype_string($input); + PyErr_Format(PyExc_TypeError, + "Int dimension expected. '%s' given.", + typestring); + SWIG_fail; + } + $2 = (DIM_TYPE) PyLong_AsSsize_t($input); + if ($2 == -1 && PyErr_Occurred()) SWIG_fail; + dims[0] = (npy_intp) $2; + array = PyArray_SimpleNew(1, dims, DATA_TYPECODE); + if (!array) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); +} +%typemap(argout) + (DATA_TYPE* ARGOUT_ARRAY1, DIM_TYPE DIM1) +{ + $result = SWIG_Python_AppendOutput($result,(PyObject*)array$argnum); +} + +/* Typemap suite for (DIM_TYPE DIM1, DATA_TYPE* ARGOUT_ARRAY1) + */ +%typemap(in,numinputs=1, + fragment="NumPy_Fragments") + (DIM_TYPE DIM1, DATA_TYPE* ARGOUT_ARRAY1) + (PyObject* array = NULL) +{ + npy_intp dims[1]; + if (!PyLong_Check($input)) + { + const char* typestring = pytype_string($input); + PyErr_Format(PyExc_TypeError, + "Int dimension expected. '%s' given.", + typestring); + SWIG_fail; + } + $1 = (DIM_TYPE) PyLong_AsSsize_t($input); + if ($1 == -1 && PyErr_Occurred()) SWIG_fail; + dims[0] = (npy_intp) $1; + array = PyArray_SimpleNew(1, dims, DATA_TYPECODE); + if (!array) SWIG_fail; + $2 = (DATA_TYPE*) array_data(array); +} +%typemap(argout) + (DIM_TYPE DIM1, DATA_TYPE* ARGOUT_ARRAY1) +{ + $result = SWIG_Python_AppendOutput($result,(PyObject*)array$argnum); +} + +/* Typemap suite for (DATA_TYPE ARGOUT_ARRAY2[ANY][ANY]) + */ +%typemap(in,numinputs=0, + fragment="NumPy_Backward_Compatibility,NumPy_Macros") + (DATA_TYPE ARGOUT_ARRAY2[ANY][ANY]) + (PyObject* array = NULL) +{ + npy_intp dims[2] = { $1_dim0, $1_dim1 }; + array = PyArray_SimpleNew(2, dims, DATA_TYPECODE); + if (!array) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} +%typemap(argout) + (DATA_TYPE ARGOUT_ARRAY2[ANY][ANY]) +{ + $result = SWIG_Python_AppendOutput($result,(PyObject*)array$argnum); +} + +/* Typemap suite for (DATA_TYPE ARGOUT_ARRAY3[ANY][ANY][ANY]) + */ +%typemap(in,numinputs=0, + fragment="NumPy_Backward_Compatibility,NumPy_Macros") + (DATA_TYPE ARGOUT_ARRAY3[ANY][ANY][ANY]) + (PyObject* array = NULL) +{ + npy_intp dims[3] = { $1_dim0, $1_dim1, $1_dim2 }; + array = PyArray_SimpleNew(3, dims, DATA_TYPECODE); + if (!array) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} +%typemap(argout) + (DATA_TYPE ARGOUT_ARRAY3[ANY][ANY][ANY]) +{ + $result = SWIG_Python_AppendOutput($result,(PyObject*)array$argnum); +} + +/* Typemap suite for (DATA_TYPE ARGOUT_ARRAY4[ANY][ANY][ANY][ANY]) + */ +%typemap(in,numinputs=0, + fragment="NumPy_Backward_Compatibility,NumPy_Macros") + (DATA_TYPE ARGOUT_ARRAY4[ANY][ANY][ANY][ANY]) + (PyObject* array = NULL) +{ + npy_intp dims[4] = { $1_dim0, $1_dim1, $1_dim2, $1_dim3 }; + array = PyArray_SimpleNew(4, dims, DATA_TYPECODE); + if (!array) SWIG_fail; + $1 = ($1_ltype) array_data(array); +} +%typemap(argout) + (DATA_TYPE ARGOUT_ARRAY4[ANY][ANY][ANY][ANY]) +{ + $result = SWIG_Python_AppendOutput($result,(PyObject*)array$argnum); +} + +/*****************************/ +/* Argoutview Array Typemaps */ +/*****************************/ + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEW_ARRAY1, DIM_TYPE* DIM1) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEW_ARRAY1, DIM_TYPE* DIM1 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim_temp) +{ + $1 = &data_temp; + $2 = &dim_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility") + (DATA_TYPE** ARGOUTVIEW_ARRAY1, DIM_TYPE* DIM1) +{ + npy_intp dims[1] = { *$2 }; + PyObject* obj = PyArray_SimpleNewFromData(1, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DATA_TYPE** ARGOUTVIEW_ARRAY1) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DATA_TYPE** ARGOUTVIEW_ARRAY1) + (DIM_TYPE dim_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim_temp; + $2 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility") + (DIM_TYPE* DIM1, DATA_TYPE** ARGOUTVIEW_ARRAY1) +{ + npy_intp dims[1] = { *$1 }; + PyObject* obj = PyArray_SimpleNewFromData(1, dims, DATA_TYPECODE, (void*)(*$2)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEW_ARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEW_ARRAY2, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility") + (DATA_TYPE** ARGOUTVIEW_ARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) +{ + npy_intp dims[2] = { *$2, *$3 }; + PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_ARRAY2) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DATA_TYPE** ARGOUTVIEW_ARRAY2) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_ARRAY2) +{ + npy_intp dims[2] = { *$1, *$2 }; + PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$3)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEW_FARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEW_FARRAY2, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") + (DATA_TYPE** ARGOUTVIEW_FARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) +{ + npy_intp dims[2] = { *$2, *$3 }; + PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || !require_fortran(array)) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_FARRAY2) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DATA_TYPE** ARGOUTVIEW_FARRAY2) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEW_FARRAY2) +{ + npy_intp dims[2] = { *$1, *$2 }; + PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$3)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || !require_fortran(array)) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEW_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, + DIM_TYPE* DIM3) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEW_ARRAY3, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; + $4 = &dim3_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility") + (DATA_TYPE** ARGOUTVIEW_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) +{ + npy_intp dims[3] = { *$2, *$3, *$4 }; + PyObject* obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, + DATA_TYPE** ARGOUTVIEW_ARRAY3) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_ARRAY3) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DATA_TYPE* data_temp = NULL) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &dim3_temp; + $4 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_ARRAY3) +{ + npy_intp dims[3] = { *$1, *$2, *$3 }; + PyObject* obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$4)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEW_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, + DIM_TYPE* DIM3) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEW_FARRAY3, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; + $4 = &dim3_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") + (DATA_TYPE** ARGOUTVIEW_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) +{ + npy_intp dims[3] = { *$2, *$3, *$4 }; + PyObject* obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || !require_fortran(array)) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, + DATA_TYPE** ARGOUTVIEW_FARRAY3) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DATA_TYPE** ARGOUTVIEW_FARRAY3) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &dim3_temp; + $4 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEW_FARRAY3) +{ + npy_intp dims[3] = { *$1, *$2, *$3 }; + PyObject* obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$4)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || !require_fortran(array)) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEW_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, + DIM_TYPE* DIM3, DIM_TYPE* DIM4) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEW_ARRAY4, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; + $4 = &dim3_temp; + $5 = &dim4_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility") + (DATA_TYPE** ARGOUTVIEW_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) +{ + npy_intp dims[4] = { *$2, *$3, *$4 , *$5 }; + PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, + DATA_TYPE** ARGOUTVIEW_ARRAY4) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 , DATA_TYPE** ARGOUTVIEW_ARRAY4) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &dim3_temp; + $4 = &dim4_temp; + $5 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEW_ARRAY4) +{ + npy_intp dims[4] = { *$1, *$2, *$3 , *$4 }; + PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$5)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEW_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, + DIM_TYPE* DIM3, DIM_TYPE* DIM4) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEW_FARRAY4, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; + $4 = &dim3_temp; + $5 = &dim4_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") + (DATA_TYPE** ARGOUTVIEW_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) +{ + npy_intp dims[4] = { *$2, *$3, *$4 , *$5 }; + PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || !require_fortran(array)) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, + DATA_TYPE** ARGOUTVIEW_FARRAY4) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 , DATA_TYPE** ARGOUTVIEW_FARRAY4) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &dim3_temp; + $4 = &dim4_temp; + $5 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEW_FARRAY4) +{ + npy_intp dims[4] = { *$1, *$2, *$3 , *$4 }; + PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$5)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || !require_fortran(array)) SWIG_fail; + $result = SWIG_Python_AppendOutput($result,obj); +} + +/*************************************/ +/* Managed Argoutview Array Typemaps */ +/*************************************/ + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_ARRAY1, DIM_TYPE* DIM1) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEWM_ARRAY1, DIM_TYPE* DIM1 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim_temp) +{ + $1 = &data_temp; + $2 = &dim_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Utilities") + (DATA_TYPE** ARGOUTVIEWM_ARRAY1, DIM_TYPE* DIM1) +{ + npy_intp dims[1] = { *$2 }; + PyObject* obj = PyArray_SimpleNewFromData(1, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + +PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); + +%#if NPY_API_VERSION < NPY_1_7_API_VERSION + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DATA_TYPE** ARGOUTVIEWM_ARRAY1) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DATA_TYPE** ARGOUTVIEWM_ARRAY1) + (DIM_TYPE dim_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim_temp; + $2 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Utilities") + (DIM_TYPE* DIM1, DATA_TYPE** ARGOUTVIEWM_ARRAY1) +{ + npy_intp dims[1] = { *$1 }; + PyObject* obj = PyArray_SimpleNewFromData(1, dims, DATA_TYPECODE, (void*)(*$2)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + +PyObject* cap = PyCapsule_New((void*)(*$2), SWIGPY_CAPSULE_NAME, free_cap); + +%#if NPY_API_VERSION < NPY_1_7_API_VERSION + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_ARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEWM_ARRAY2, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Utilities") + (DATA_TYPE** ARGOUTVIEWM_ARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) +{ + npy_intp dims[2] = { *$2, *$3 }; + PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + +PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); + +%#if NPY_API_VERSION < NPY_1_7_API_VERSION + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEWM_ARRAY2) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DATA_TYPE** ARGOUTVIEWM_ARRAY2) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Utilities") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEWM_ARRAY2) +{ + npy_intp dims[2] = { *$1, *$2 }; + PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$3)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + +PyObject* cap = PyCapsule_New((void*)(*$3), SWIGPY_CAPSULE_NAME, free_cap); + +%#if NPY_API_VERSION < NPY_1_7_API_VERSION + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_FARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEWM_FARRAY2, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements,NumPy_Utilities") + (DATA_TYPE** ARGOUTVIEWM_FARRAY2, DIM_TYPE* DIM1, DIM_TYPE* DIM2) +{ + npy_intp dims[2] = { *$2, *$3 }; + PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || !require_fortran(array)) SWIG_fail; + +PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); + +%#if NPY_API_VERSION < NPY_1_7_API_VERSION + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEWM_FARRAY2) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DATA_TYPE** ARGOUTVIEWM_FARRAY2) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements,NumPy_Utilities") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DATA_TYPE** ARGOUTVIEWM_FARRAY2) +{ + npy_intp dims[2] = { *$1, *$2 }; + PyObject* obj = PyArray_SimpleNewFromData(2, dims, DATA_TYPECODE, (void*)(*$3)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || !require_fortran(array)) SWIG_fail; + +PyObject* cap = PyCapsule_New((void*)(*$3), SWIGPY_CAPSULE_NAME, free_cap); + +%#if NPY_API_VERSION < NPY_1_7_API_VERSION + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, + DIM_TYPE* DIM3) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEWM_ARRAY3, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; + $4 = &dim3_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Utilities") + (DATA_TYPE** ARGOUTVIEWM_ARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) +{ + npy_intp dims[3] = { *$2, *$3, *$4 }; + PyObject* obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + +PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); + +%#if NPY_API_VERSION < NPY_1_7_API_VERSION + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, + DATA_TYPE** ARGOUTVIEWM_ARRAY3) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DATA_TYPE** ARGOUTVIEWM_ARRAY3) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &dim3_temp; + $4 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Utilities") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEWM_ARRAY3) +{ + npy_intp dims[3] = { *$1, *$2, *$3 }; + PyObject* obj= PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$4)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + +PyObject* cap = PyCapsule_New((void*)(*$4), SWIGPY_CAPSULE_NAME, free_cap); + +%#if NPY_API_VERSION < NPY_1_7_API_VERSION + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, + DIM_TYPE* DIM3) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEWM_FARRAY3, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; + $4 = &dim3_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements,NumPy_Utilities") + (DATA_TYPE** ARGOUTVIEWM_FARRAY3, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3) +{ + npy_intp dims[3] = { *$2, *$3, *$4 }; + PyObject* obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || !require_fortran(array)) SWIG_fail; + +PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); + +%#if NPY_API_VERSION < NPY_1_7_API_VERSION + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, + DATA_TYPE** ARGOUTVIEWM_FARRAY3) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DATA_TYPE** ARGOUTVIEWM_FARRAY3) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &dim3_temp; + $4 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements,NumPy_Utilities") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DATA_TYPE** ARGOUTVIEWM_FARRAY3) +{ + npy_intp dims[3] = { *$1, *$2, *$3 }; + PyObject* obj = PyArray_SimpleNewFromData(3, dims, DATA_TYPECODE, (void*)(*$4)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || !require_fortran(array)) SWIG_fail; + +PyObject* cap = PyCapsule_New((void*)(*$4), SWIGPY_CAPSULE_NAME, free_cap); + +%#if NPY_API_VERSION < NPY_1_7_API_VERSION + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, + DIM_TYPE* DIM3, DIM_TYPE* DIM4) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEWM_ARRAY4, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; + $4 = &dim3_temp; + $5 = &dim4_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Utilities") + (DATA_TYPE** ARGOUTVIEWM_ARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) +{ + npy_intp dims[4] = { *$2, *$3, *$4 , *$5 }; + PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + +PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); + +%#if NPY_API_VERSION < NPY_1_7_API_VERSION + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, + DATA_TYPE** ARGOUTVIEWM_ARRAY4) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 , DATA_TYPE** ARGOUTVIEWM_ARRAY4) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &dim3_temp; + $4 = &dim4_temp; + $5 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Utilities") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEWM_ARRAY4) +{ + npy_intp dims[4] = { *$1, *$2, *$3 , *$4 }; + PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$5)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array) SWIG_fail; + +PyObject* cap = PyCapsule_New((void*)(*$5), SWIGPY_CAPSULE_NAME, free_cap); + +%#if NPY_API_VERSION < NPY_1_7_API_VERSION + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DATA_TYPE** ARGOUTVIEWM_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, + DIM_TYPE* DIM3, DIM_TYPE* DIM4) + */ +%typemap(in,numinputs=0) + (DATA_TYPE** ARGOUTVIEWM_FARRAY4, DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 ) + (DATA_TYPE* data_temp = NULL , DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp) +{ + $1 = &data_temp; + $2 = &dim1_temp; + $3 = &dim2_temp; + $4 = &dim3_temp; + $5 = &dim4_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements,NumPy_Utilities") + (DATA_TYPE** ARGOUTVIEWM_FARRAY4, DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4) +{ + npy_intp dims[4] = { *$2, *$3, *$4 , *$5 }; + PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$1)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || !require_fortran(array)) SWIG_fail; + +PyObject* cap = PyCapsule_New((void*)(*$1), SWIGPY_CAPSULE_NAME, free_cap); + +%#if NPY_API_VERSION < NPY_1_7_API_VERSION + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/* Typemap suite for (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, + DATA_TYPE** ARGOUTVIEWM_FARRAY4) + */ +%typemap(in,numinputs=0) + (DIM_TYPE* DIM1 , DIM_TYPE* DIM2 , DIM_TYPE* DIM3 , DIM_TYPE* DIM4 , DATA_TYPE** ARGOUTVIEWM_FARRAY4) + (DIM_TYPE dim1_temp, DIM_TYPE dim2_temp, DIM_TYPE dim3_temp, DIM_TYPE dim4_temp, DATA_TYPE* data_temp = NULL ) +{ + $1 = &dim1_temp; + $2 = &dim2_temp; + $3 = &dim3_temp; + $4 = &dim4_temp; + $5 = &data_temp; +} +%typemap(argout, + fragment="NumPy_Backward_Compatibility,NumPy_Array_Requirements,NumPy_Utilities") + (DIM_TYPE* DIM1, DIM_TYPE* DIM2, DIM_TYPE* DIM3, DIM_TYPE* DIM4, DATA_TYPE** ARGOUTVIEWM_FARRAY4) +{ + npy_intp dims[4] = { *$1, *$2, *$3 , *$4 }; + PyObject* obj = PyArray_SimpleNewFromData(4, dims, DATA_TYPECODE, (void*)(*$5)); + PyArrayObject* array = (PyArrayObject*) obj; + + if (!array || !require_fortran(array)) SWIG_fail; + +PyObject* cap = PyCapsule_New((void*)(*$5), SWIGPY_CAPSULE_NAME, free_cap); + +%#if NPY_API_VERSION < NPY_1_7_API_VERSION + PyArray_BASE(array) = cap; +%#else + PyArray_SetBaseObject(array,cap); +%#endif + + $result = SWIG_Python_AppendOutput($result,obj); +} + +/**************************************/ +/* In-Place Array Typemap - flattened */ +/**************************************/ + +/* Typemap suite for (DATA_TYPE* INPLACE_ARRAY_FLAT, DIM_TYPE DIM_FLAT) + */ +%typecheck(SWIG_TYPECHECK_DOUBLE_ARRAY, + fragment="NumPy_Macros") + (DATA_TYPE* INPLACE_ARRAY_FLAT, DIM_TYPE DIM_FLAT) +{ + $1 = is_array($input) && PyArray_EquivTypenums(array_type($input), + DATA_TYPECODE); +} +%typemap(in, + fragment="NumPy_Fragments") + (DATA_TYPE* INPLACE_ARRAY_FLAT, DIM_TYPE DIM_FLAT) + (PyArrayObject* array=NULL, int i=1) +{ + array = obj_to_array_no_conversion($input, DATA_TYPECODE); + if (!array || !require_c_or_f_contiguous(array) + || !require_native(array)) SWIG_fail; + $1 = (DATA_TYPE*) array_data(array); + $2 = 1; + for (i=0; i < array_numdims(array); ++i) $2 *= array_size(array,i); +} + +%enddef /* %numpy_typemaps() macro */ +/* *************************************************************** */ + +/* Concrete instances of the %numpy_typemaps() macro: Each invocation + * below applies all of the typemaps above to the specified data type. + */ +%numpy_typemaps(signed char , NPY_BYTE , int) +%numpy_typemaps(unsigned char , NPY_UBYTE , int) +%numpy_typemaps(short , NPY_SHORT , int) +%numpy_typemaps(unsigned short , NPY_USHORT , int) +%numpy_typemaps(int , NPY_INT , int) +%numpy_typemaps(unsigned int , NPY_UINT , int) +%numpy_typemaps(long , NPY_LONG , int) +%numpy_typemaps(unsigned long , NPY_ULONG , int) +%numpy_typemaps(long long , NPY_LONGLONG , int) +%numpy_typemaps(unsigned long long, NPY_ULONGLONG, int) +%numpy_typemaps(float , NPY_FLOAT , int) +%numpy_typemaps(double , NPY_DOUBLE , int) +%numpy_typemaps(int8_t , NPY_INT8 , int) +%numpy_typemaps(int16_t , NPY_INT16 , int) +%numpy_typemaps(int32_t , NPY_INT32 , int) +%numpy_typemaps(int64_t , NPY_INT64 , int) +%numpy_typemaps(uint8_t , NPY_UINT8 , int) +%numpy_typemaps(uint16_t , NPY_UINT16 , int) +%numpy_typemaps(uint32_t , NPY_UINT32 , int) +%numpy_typemaps(uint64_t , NPY_UINT64 , int) + + +/* *************************************************************** + * The follow macro expansion does not work, because C++ bool is 4 + * bytes and NPY_BOOL is 1 byte + * + * %numpy_typemaps(bool, NPY_BOOL, int) + */ + +/* *************************************************************** + * On my Mac, I get the following warning for this macro expansion: + * 'swig/python detected a memory leak of type 'long double *', no destructor found.' + * + * %numpy_typemaps(long double, NPY_LONGDOUBLE, int) + */ + +#ifdef __cplusplus + +%include + +%numpy_typemaps(std::complex, NPY_CFLOAT , int) +%numpy_typemaps(std::complex, NPY_CDOUBLE, int) + +#endif + +#endif /* SWIGPYTHON */ diff --git a/src/pyfragments.swg.in b/src/pyfragments.swg.in new file mode 100644 index 000000000..6d3e6ff41 --- /dev/null +++ b/src/pyfragments.swg.in @@ -0,0 +1,112 @@ +/*-*- C -*-*/ + +/**********************************************************************/ + +/* For numpy versions prior to 1.0, the names of certain data types + * are different than in later versions. This fragment provides macro + * substitutions that allow us to support old and new versions of + * numpy. + */ + +/**********************************************************************/ + +/* Override the SWIG_AsVal_frag(long) fragment so that it also checks + * for numpy scalar array types. The code through the %#endif is + * essentially cut-and-paste from pyprimtype.swg + */ + +%fragment(SWIG_AsVal_frag(long), "header", + fragment="SWIG_CanCastAsInteger", + fragment="NumPy_Backward_Compatibility") +{ + SWIGINTERN int + SWIG_AsVal_dec(long)(PyObject * obj, long * val) + { + if (PyLong_Check(obj)) { + long v = PyLong_AsLong(obj); + if (v != -1 || !PyErr_Occurred()) { + if (val) *val = v; + return SWIG_OK; + } else { + PyErr_Clear(); + } + } +%#ifdef SWIG_PYTHON_CAST_MODE + { + int dispatch = 0; + long v = PyLong_AsLong(obj); + if (v != -1 || !PyErr_Occurred()) { + if (val) *val = v; + return SWIG_AddCast(SWIG_OK); + } else { + PyErr_Clear(); + } + if (!dispatch) { + double d; + int res = SWIG_AddCast(SWIG_AsVal(double)(obj,&d)); + if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, LONG_MIN, LONG_MAX)) { + if (val) *val = (long)(d); + return res; + } + } + } +%#endif + if (!PyArray_IsScalar(obj,Integer)) return SWIG_TypeError; + if (!val) return SWIG_OK; + PyArray_Descr * longDescr = PyArray_DescrFromType(NPY_LONG); + PyArray_CastScalarToCtype(obj, (void*)val, longDescr); + Py_DECREF(longDescr); + return SWIG_OK; + } +} + + +/* Override the SWIG_AsVal_frag(unsigned long) fragment so that it + * also checks for numpy scalar array types. The code through the + * %#endif is essentially cut-and-paste from pyprimtype.swg + */ + +%fragment(SWIG_AsVal_frag(unsigned long),"header", + fragment="SWIG_CanCastAsInteger", + fragment="NumPy_Backward_Compatibility") +{ + SWIGINTERN int + SWIG_AsVal_dec(unsigned long)(PyObject *obj, unsigned long *val) + { + if (PyLong_Check(obj)) { + unsigned long v = PyLong_AsUnsignedLong(obj); + if (!PyErr_Occurred()) { + if (val) *val = v; + return SWIG_OK; + } else { + PyErr_Clear(); + } + } +%#ifdef SWIG_PYTHON_CAST_MODE + { + int dispatch = 0; + unsigned long v = PyLong_AsUnsignedLong(obj); + if (!PyErr_Occurred()) { + if (val) *val = v; + return SWIG_AddCast(SWIG_OK); + } else { + PyErr_Clear(); + } + if (!dispatch) { + double d; + int res = SWIG_AddCast(SWIG_AsVal(double)(obj,&d)); + if (SWIG_IsOK(res) && SWIG_CanCastAsInteger(&d, 0, ULONG_MAX)) { + if (val) *val = (unsigned long)(d); + return res; + } + } + } +%#endif + if (!PyArray_IsScalar(obj,Integer)) return SWIG_TypeError; + if (!val) return SWIG_OK; + PyArray_Descr * ulongDescr = PyArray_DescrFromType(NPY_ULONG); + PyArray_CastScalarToCtype(obj, (void*)val, ulongDescr); + Py_DECREF(ulongDescr); + return SWIG_OK; + } +} diff --git a/src/swig/CMakeLists.txt b/src/swig/CMakeLists.txt new file mode 100644 index 000000000..74851c46b --- /dev/null +++ b/src/swig/CMakeLists.txt @@ -0,0 +1,5 @@ +include(${SWIG_USE_FILE}) + +if (PHREEQCRM_BUILD_PYTHON) + add_subdirectory(python) +endif() diff --git a/src/swig/python/AdvectBMI_py.py b/src/swig/python/AdvectBMI_py.py new file mode 100644 index 000000000..24f200f34 --- /dev/null +++ b/src/swig/python/AdvectBMI_py.py @@ -0,0 +1,202 @@ +import phreeqcrm +import numpy as np +#ifdef USE_YAML + #module mydata + # double precision, dimension(:), pointer :: K_ptr + # integer :: rm_id + #end module mydata + +def AdvectBMI_f90(): + + # Based on PHREEQC Example 11 + + # -------------------------------------------------------------------------- + # Create PhreeqcRM + # -------------------------------------------------------------------------- + yaml_file = "AdvectBMI_py.yaml" + + # phreeqc_rm.GetGridCellCountYAML must be called BEFORE + # the PhreeqcRM instance is created. The + # return value can be used to create the + # PhreeqcRM instance. + # + # If the YAML file does not contain + # a node "SetGridCellCount:" (usually written + # using the YAMLPhreeqcRM class and the method + # YAMLSetGridCellCount), the return + # value is zero. + ###nxyz = GetGridCellCountYAML(yaml_file) + nxyz = 40 + # Bogus conductivity field for Basic callback demonstration + #hydraulic_K = [i*2.0 for i in range(nxyz)] + hydraulic_K = [0.0] * nxyz + for i in range(nxyz): + hydraulic_K[i] = i*2.0 + nthreads = 3 + phreeqc_rm = phreeqcrm.PhreeqcRM(nxyz, nthreads) + # Initialize with YAML file + status = phreeqc_rm.InitializeYAML(yaml_file) + ###phreeqc_rm.BMI_Initialize(yaml_file) + + # Demonstrate add to Basic: Set a function for Basic CALLBACK after LoadDatabase + #TODO CALL register_basic_callback_fortran() +#ifdef USE_MPI + # Optional callback for MPI + #TODO status = do_something() # only root is calling do_something here +#endif + + phreeqc_rm.BMI_GetValue("ComponentCount", ncomps) + # Print some of the reaction module information + print("Number of threads: ", phreeqc_rm.GetThreadCount()) + phreeqc_rm.OutputMessage(string1) + #write(string1, "(A,I10)") "Number of MPI processes: ", phreeqc_rm.GetMpiTasks() + print("MPI task number: ", phreeqc_rm.GetMpiMyself()) + print("File prefix: ", phreeqc_rm.BMI_GetValue("FilePrefix", prefix)) + print("Number of grid cells in the user's model: ", nxyz) + print("Number of chemistry cells in the reaction module: ", nchem) + print("Number of components for transport: ", ncomps) + # Get component information + phreeqc_rm.BMI_GetValue("Components", components) + phreeqc_rm.BMI_GetValue("Gfw", gfw) + for i in range(ncomps): + print(components(i)), gfw(i) + print() + # Get initial temperatures + phreeqc_rm.BMI_GetValue("Temperature", temperature) + # Get initial temperature + phreeqc_rm.BMI_GetValue("Saturation", sat) + # Get initial porosity + phreeqc_rm.BMI_GetValue("Porosity", por) + # Get initial temperature + phreeqc_rm.BMI_GetValue("SolutionVolume", volume) + # Get initial concentrations + c = phreeqcrm.DoubleVector() + phreeqc_rm.BMI_GetValue("Concentrations", c) + # Set density, pressure, and temperature (previously allocated) + density = [1.0] * nxyz + phreeqc_rm.BMI_SetValue("Density", density) + pressure = [2.0] * nxyz + phreeqc_rm.BMI_SetValue("Pressure", pressure) + temperature = [20.0] * nxyz + phreeqc_rm.BMI_SetValue("Temperature", temperature) + # -------------------------------------------------------------------------- + # Set boundary condition + # -------------------------------------------------------------------------- + nbound = 1 + bc1 = [0] # solution 0 from Initial IPhreeqc instance + bc2 = [-1] # no bc2 solution for mixing + bc_f1 = [1.0] # mixing fraction for bc1 + bc_conc = phreeqcrm.DoubleVector() + phreeqc_rm.InitialPhreeqc2Concentrations(bc_conc, nbound, bc1, bc2, bc_f1) + # -------------------------------------------------------------------------- + # Transient loop + # -------------------------------------------------------------------------- + nsteps = 10 + time = 0.0 + phreeqc_rm.BMI_SetValue("Time", time) + time_step = 86400.0 + phreeqc_rm.BMI_SetValue("TimeStep", time_step) + for i in range(nsteps): + print("Beginning transport calculation ", time/86400., " days") + phreeqc_rm.SetScreenOn(1) + print(" Time step ", time_step / 86400., " days") + # Transport calculation here, changes c + advectionbmi_py(c, bc_conc, ncomps, nxyz) + + # Transfer data to PhreeqcRM for reactions + print_selected_output_on = (steps == nsteps - 1) + print_chemistry_on = (steps == nsteps - 1) + phreeqc_rm.SetSelectedOutputOn(print_selected_output_on) + phreeqc_rm.SetPrintChemistryOn(print_chemistry_on, False, False) # workers, initial_phreeqc, utility + phreeqc_rm.SetConcentrations(c) # Transported concentrations + time += time_step + status = phreeqc_rm.SetTime(time) + # Transfer data to PhreeqcRM after transport + phreeqc_rm.BMI_SetValue("Concentrations", c) # Transported concentrations + # Optionally, if values changed during transport + phreeqc_rm.BMI_SetValue("Porosity", por) + phreeqc_rm.BMI_SetValue("Saturation", sat) + phreeqc_rm.BMI_SetValue("Temperature", temperature) + phreeqc_rm.BMI_SetValue("Pressure", pressure) + phreeqc_rm.BMI_SetValue("TimeStep", time_step) + # Set new time + time = time + time_step + phreeqc_rm.BMI_SetValue("Time", time) # Current time + # Run cells with transported conditions + print("Beginning reaction calculation ", time / 86400., " days") + # Demonstration of state + phreeqc_rm.StateSave(1) + phreeqc_rm.StateApply(1) + phreeqc_rm.StateDelete(1) + # Run chemistry + phreeqc_rm.BMI_Update() + # Get new data calculated by PhreeqcRM for transport + phreeqc_rm.BMI_GetValue("Concentrations", c) + density = phreeqc_rm.DoubleVector() + phreeqc_rm.BMI_GetValue("Density", density) + volume = phreeqc_rm.DoubleVector() + phreeqc_rm.BMI_GetValue("SolutionVolume", volume) + # Print results at last time step + if (isteps == nsteps): + print("Current distribution of cells for workers") + print("Worker First cell Last Cell") + n = phreeqc_rm.GetThreadCount() * phreeqc_rm.GetMpiTasks() + sc = phreeqc_rm.IntVector() + ec = phreeqc_rm.IntVector() + phreeqc_rm.GetStartCell(sc) + phreeqc_rm.GetEndCell(ec) + for i in range(n): + print(i," ", sc(i)," ",ec(i)) + + # Loop through possible multiple selected output definitions + phreeqc_rm.BMI_GetValue("SelectedOutputCount", n) + + for isel in range(n): + i = isel + phreeqc_rm.BMI_SetValue("NthSelectedOutput", i) + phreeqc_rm.BMI_GetValue("CurrentSelectedOutputUserNumber", n_user) + print("Selected output sequence number: ", isel) + print("Selected output user number: ", n_user) + # Get 2D array of selected output values + phreeqc_rm.BMI_GetValue("SelectedOutputColumnCount", col) + phreeqc_rm.BMI_GetValue("SelectedOutputRowCount", rows) + selected_out = phreeqc_rm.DoubleVector() + # Get headings + phreeqc_rm.BMI_GetValue("SelectedOutputHeadings", headings) + # Get selected output + phreeqc_rm.BMI_GetValue("SelectedOutput", selected_out) + # Print results + for i in range(rows//2): + print("Cell number ", i) + print(" Density: ", density[i]) + print(" Volume: ", volume[i]) + print(" Components: ") + for j in range(ncomps): + print(j, " ",components[j], ": ", c[j * nxyz + i]) + print(" Selected output: ") + for j in range(col): + print(j, " ", headings[j],": ", selected_out[j * nxyz + i]) + + + # Clean up + phreeqc_rm.CloseFiles() + phreeqc_rm.MpiWorkerBreak() + phreeqc_rm.BMI_Finalize() + + +def advectionbmi_py(c, bc_conc, ncomps, nxyz): + # Advect + for i in range(nxyz - 1, 0, -1): + for j in range(ncomps): + c[j * nxyz + i] = c[j * nxyz + i - 1] # component j + + # Cell zero gets boundary condition + for j in range(ncomps): + c[j * nxyz] = bc_conc[j * dim]; # component j + + +if __name__ == '__main__': + AdvectBMI_f90() + + +#endif # USE_YAML diff --git a/src/swig/python/CMakeLists.txt b/src/swig/python/CMakeLists.txt new file mode 100644 index 000000000..91cead042 --- /dev/null +++ b/src/swig/python/CMakeLists.txt @@ -0,0 +1,133 @@ +set(PYTHON_TARGET_NAME phreeqcrmpy) + +set(phreeqcrm_INTERFACE PhreeqcRM.i) + +set(phreeqcrm_INTERFACE_FULLPATH ${CMAKE_CURRENT_SOURCE_DIR}/../../${phreeqcrm_INTERFACE}) + +# copy PhreeqcRM.i in order to not have pyfragments.swg be automatically included +# configure_file(${CMAKE_CURRENT_SOURCE_DIR}/../../${phreeqcrm_INTERFACE} ${phreeqcrm_INTERFACE} COPYONLY) + +# @todo +# configure_file(${CMAKE_CURRENT_SOURCE_DIR}/../../pyfragments.swg.in pyfragments.swg COPYONLY) + +# copy database to build directory for testing +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/../../../database/phreeqc.dat phreeqc.dat COPYONLY) + +# copy advect.pqi to build directory for testing +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/../../../Tests/advect.pqi advect.pqi COPYONLY) + +# copy database to build directory for testing +configure_file(SimpleAdvect.py SimpleAdvect.py COPYONLY) + +get_target_property(PhreeqcRM_SOURCES PhreeqcRM SOURCES) + +set_source_files_properties(${phreeqcrm_INTERFACE_FULLPATH} PROPERTIES SWIG_FLAGS "-Wall") +set_source_files_properties(${phreeqcrm_INTERFACE_FULLPATH} PROPERTIES CPLUSPLUS ON) + +swig_add_library( + ${PYTHON_TARGET_NAME} + LANGUAGE python + TYPE MODULE + SOURCES ${phreeqcrm_INTERFACE_FULLPATH} ${PhreeqcRM_SOURCES} +) + +target_compile_features(${PYTHON_TARGET_NAME} PUBLIC cxx_std_11) + +if(PHREEQCRM_WITH_YAML_CPP AND yaml-cpp_FOUND) + target_compile_definitions(${PYTHON_TARGET_NAME} PUBLIC USE_YAML) + target_link_libraries(${PYTHON_TARGET_NAME} PUBLIC yaml-cpp) +endif() + +target_link_libraries(${PYTHON_TARGET_NAME} + PRIVATE + Python::Python + # Python::NumPy +) + +get_target_property(PhreeqcRM_INC PhreeqcRM INCLUDE_DIRECTORIES) +target_include_directories(${PYTHON_TARGET_NAME} + PUBLIC + ${PhreeqcRM_INC} +) + +get_property(IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) + +if(NOT CMAKE_DEBUG_POSTFIX) + # SWIG BUG -- PyInit__phreeqcrmpy is misnamed when either of these properties is used: + # set_target_properties(${PYTHON_TARGET_NAME} PROPERTIES DEBUG_POSTFIX "_d") + # set_target_properties(${PYTHON_TARGET_NAME} PROPERTIES OUTPUT_NAME_DEBUG "${PYTHON_TARGET_NAME}_d") + if(WIN32) + # copy _phreeqcrmpy.pyd to _phreeqcrmpy_d.pyd + add_custom_command(TARGET ${PYTHON_TARGET_NAME} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + $ + $/_$$<$:_d>$ + ) + endif() +endif() + +if(IS_MULTI_CONFIG) + add_test(NAME SimpleAdvect.py + COMMAND ${Python_EXECUTABLE} SimpleAdvect.py + CONFIGURATIONS Release RelWithDebInfo MinSizeRel + ) + set_tests_properties(SimpleAdvect.py PROPERTIES ENVIRONMENT "PYTHONPATH=$") +else() + if("${CMAKE_BUILD_TYPE}" MATCHES "^([Rr][Ee][Ll][Ee][Aa][Ss][Ee])$") + add_test(NAME SimpleAdvect.py + COMMAND ${Python_EXECUTABLE} SimpleAdvect.py + ) + endif() +endif() + +if(WIN32) + string(REPLACE python.exe python_d.exe Python_d_EXECUTABLE ${Python_EXECUTABLE}) + + if(IS_MULTI_CONFIG) + add_test(NAME SimpleAdvect_d.py + COMMAND ${Python_d_EXECUTABLE} SimpleAdvect.py + CONFIGURATIONS Debug + ) + set_tests_properties(SimpleAdvect_d.py PROPERTIES ENVIRONMENT "PYTHONPATH=$") + else() + if("${CMAKE_BUILD_TYPE}" MATCHES "^([Dd][Ee][Bb][Uu][Gg])$") + add_test(NAME SimpleAdvect_d.py + COMMAND ${Python_d_EXECUTABLE} SimpleAdvect.py + ) + endif() + endif() + if(NOT EXISTS ${Python_d_EXECUTABLE}) + message(STATUS "Debug python interpreter not found") + if(IS_MULTI_CONFIG) + set_tests_properties(SimpleAdvect_d.py PROPERTIES DISABLED TRUE) + else() + if("${CMAKE_BUILD_TYPE}" MATCHES "^([Dd][Ee][Bb][Uu][Gg])$") + set_tests_properties(SimpleAdvect_d.py PROPERTIES DISABLED TRUE) + endif() + endif() + endif() +endif() + +if(MSVC) + # setup python Debugging + # Configuration Properties->Debugging + + # Get the base name + get_filename_component(base_name ${Python_EXECUTABLE} NAME_WLE) + + # Get the extension + get_filename_component(ext ${Python_EXECUTABLE} LAST_EXT) + + # Get the directory of the input file + get_filename_component(dir_name ${Python_EXECUTABLE} DIRECTORY) + + set_target_properties(${PYTHON_TARGET_NAME} PROPERTIES VS_DEBUGGER_COMMAND "${dir_name}/${base_name}$<$:_d>${ext}") + # set_target_properties(${PYTHON_TARGET_NAME} PROPERTIES VS_DEBUGGER_ENVIRONMENT "PYTHONPATH=$") + set_target_properties(${PYTHON_TARGET_NAME} PROPERTIES VS_DEBUGGER_ENVIRONMENT "PYTHONPATH=$(OutDirFullPath)") + set_target_properties(${PYTHON_TARGET_NAME} PROPERTIES VS_DEBUGGER_COMMAND_ARGUMENTS "SimpleAdvect.py") +endif() + +# include(CMakePrintHelpers) +# cmake_print_variables(Python_EXECUTABLE) +# cmake_print_variables(Python_d_EXECUTABLE) +# cmake_print_variables(IS_MULTI_CONFIG) diff --git a/src/swig/python/PhreeqcRM_docstrings.i b/src/swig/python/PhreeqcRM_docstrings.i new file mode 100644 index 000000000..7d96f2096 --- /dev/null +++ b/src/swig/python/PhreeqcRM_docstrings.i @@ -0,0 +1,3195 @@ +%define GetGridCellCountYAML_DOCSTRING +"GetGridCellCountYAML will read the YAML file and extract the value of +GridCellCount, which can be used to construct a PhreeqcRM instance. The +constructor for a PhreeqcRM instance requires a value for the number of +cells. If a GUI or preprocessor is used to write a YAML file to initialize +PhreeqcRM, the number of cells can be written to the YAML file and extracted +with this method. + +Args: + YAML_file (string): String containing the YAML file name. + +Returns: + int: Number of grid cells specified in the YAML file; returns zero if + GridCellCount is not defined." +%enddef +%feature("docstring") PhreeqcRM::GetGridCellCountYAML GetGridCellCountYAML_DOCSTRING + + +%define PhreeqcRM_DOCSTRING +"Constructor for the PhreeqcRM reaction module. PhreeqcRM is a reaction +module for reactive-transport simulators. Based on IPhreeqc, it +allows access to all PHREEQC reaction capabilities. It contains methods for +initial and boundary conditions, running reactions on all model cells, +transfer of data to and from the module, and parallelization +by MPI or OpenMP. + +If the code is compiled with the preprocessor directive USE_OPENMP, +the reaction module use OPENMP and multiple threads. If the code is +compiled with the preprocessor directive USE_MPI, the reaction module +will use MPI and multiple processes. If neither preprocessor directive +is used, the reaction module will be serial (unparallelized). + +Args: + nxyz (int): The number of grid cells in the users model. + thread_count_or_communicator (int): If multithreaded, the number of + threads to use in parallel segments of the code. If + thread_count_or_communicator is <= 0, the number of threads is set equal to + the number of processors in the computer. If multiprocessor, the MPI + communicator to use within the reaction module. + io(PHRQ_io): Optionally, a PHRQ_io input/output object can be provided to + the constructor. By default a PHRQ_io object is constructed to handle + reading and writing files." +%enddef +%feature("docstring") PhreeqcRM::PhreeqcRM PhreeqcRM_DOCSTRING + + +%define CloseFiles_DOCSTRING +"Close the output and log files. + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::CloseFiles CloseFiles_DOCSTRING + + +%define Concentrations2Utility_DOCSTRING +"N sets of component concentrations are converted to SOLUTIONs numbered 1-n +in the Utility IPhreeqc. The solutions can be reacted and manipulated with +the methods of IPhreeqc. If solution concentration units +(:meth:`SetUnitsSolution`) are per liter, one liter of solution is created in +the Utility instance; if solution concentration units are mass fraction, one +kilogram of solution is created in the Utility instance. The motivation for +this method is the mixing of solutions in wells, where it may be necessary to +calculate solution properties (pH for example) or react the mixture to form +scale minerals. + +Args: + c (float list, numpy.ndarray, or tuple): Vector of concentrations to be + made SOLUTIONs in Utility IPhreeqc. Vector contains n values for + each component (:meth:`GetComponentCount`) in sequence. + tc (float list, numpy.ndarray, or tuple): Vector of temperatures to apply + to the SOLUTIONs, in degrees C. Vector of size n. + p_atm (float list, numpy.ndarray, or tuple): Vector of pressures to apply + to the SOLUTIONs, in atm. Vector of size n. + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::Concentrations2Utility Concentrations2Utility_DOCSTRING + + +%define CreateMapping_DOCSTRING +"Provides a mapping from grid cells in the user model to reaction cells for +which chemistry needs to be run. The mapping is used to eliminate inactive +cells and to use symmetry to decrease the number of cells for which chemistry +must be run. The array grid2chem of size nxyz (the number of grid cells, +:meth:`GetGridCellCount`) must contain the set of all integers 0 <= i < +count_chemistry, where count_chemistry is a number less than or equal to +nxyz. Inactive cells are assigned a negative integer. The mapping may be +many-to-one to account for symmetry. Default is a one-to-one mapping--all +user grid cells are reaction cells (equivalent to grid2chem values of +0,1,2,3,...,nxyz-1). + +Args: + grid2chem (int list, numpy.ndarray, or tuple): A vector of integers: + Nonnegative is a reaction-cell number (0 based), negative is an + inactive cell. Vector is of size nxyz (number of grid cells, + :meth:`GetGridCellCount`). + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::CreateMapping CreateMapping_DOCSTRING + + +%define DecodeError_DOCSTRING +"If result is negative, this method prints an error message corresponding to +IRM_RESULT result. If result is non-negative, no action is taken. + +Args: + result (IRM_RESULT): An IRM_RESULT value returned by one of the reaction- + module methods. + +IRM_RESULT definition: +typedef enum { +IRM_OK = 0, //Success +IRM_OUTOFMEMORY = -1, //Failure, Out of memory +IRM_BADVARTYPE = -2, //Failure, Invalid VAR type +IRM_INVALIDARG = -3, //Failure, Invalid argument +IRM_INVALIDROW = -4, //Failure, Invalid row +IRM_INVALIDCOL = -5, //Failure, Invalid column +IRM_BADINSTANCE = -6, //Failure, Invalid rm instance id +IRM_FAIL = -7, //Failure, Unspecified +} IRM_RESULT;" +%enddef +%feature("docstring") PhreeqcRM::DecodeError DecodeError_DOCSTRING + + +%define DumpModule_DOCSTRING +"Writes the contents of all workers to file in _RAW formats (see appendix of +PHREEQC version 3 manual), including SOLUTIONs and all reactants. + +Args: + dump_on (Boolean): Signal for writing the dump file, true or false. + append (Boolean): Signal to append to the contents of the dump file, true + or false. + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::DumpModule DumpModule_DOCSTRING + + +%define ErrorHandler_DOCSTRING +"Checks result for an error code. If result is negative, the result is +decoded (:meth:`DecodeError`), and printed as an error message along with +the e_string, and an exception is thrown. If the result is nonnegative, no +action is taken. + +Args: + result (IRM_RESULT): IRM_RESULT to be checked for an error. + e_string (string): String to be printed if an error is found." +%enddef +%feature("docstring") PhreeqcRM::ErrorHandler ErrorHandler_DOCSTRING + + +%define ErrorMessage_DOCSTRING +"Send an error message to the screen, the output file, and the log file. + +Args: + error_string (string): String to be printed. + prepend (Boolean): True, prepends error_string with 'Error: '; false, + error_string is used with no prepended text." +%enddef +%feature("docstring") PhreeqcRM::ErrorMessage ErrorMessage_DOCSTRING + + +%define FindComponents_DOCSTRING +"This method accumulates a list of elements. Elements are those that have +been defined in a solution or any other reactant (EQUILIBRIUM_PHASE, +KINETICS, and others), including charge imbalance. This method can be called +multiple times and the list that is created is cummulative. The list is the +set of components that needs to be transported. By default the list includes +water, excess H and excess O (the H and O not contained in water); +alternatively, the list may be set to contain total H and total O +(:meth:`SetComponentH2O`), which requires transport results to be accurate +to eight or nine significant digits. If multicomponent diffusion (MCD) is +to be modeled, there is a capability to retrieve aqueous species +concentrations (:meth:`GetSpeciesConcentrations`) and to set new solution +concentrations after MCD by using individual species concentrations +(:meth:`SpeciesConcentrations2Module`). To use these methods the save-species +property needs to be turned on (:meth:`SetSpeciesSaveOn`). If the +save-species property is on, FindComponents will generate a list of aqueous +species (:meth:`GetSpeciesCount`, :meth:`GetSpeciesNames`), their diffusion +coefficients at 25 C (:meth:`GetSpeciesD25`), and their charge +(:meth:`GetSpeciesZ`). + +Returns: + int: Number of components currently in the list, or IRM_RESULT error code + (negative value, see :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::FindComponents FindComponents_DOCSTRING + + +%define GetBackwardMapping_DOCSTRING +"Returns a vector of vectors, where the nth vector is a vector of grid-cell +numbers that are mapped to reaction-cell number n. Each reaction-cell number +has a vector of one or more grid-cell numbers. + +Returns: + IntVector: Vector of vectors of ints. For each reaction cell n, + the nth vector in the vector of vectors contains the grid-cell + numbers that map to the reaction cell." +%enddef +%feature("docstring") PhreeqcRM::GetBackwardMapping GetBackwardMapping_DOCSTRING + + +%define GetChemistryCellCount_DOCSTRING +"Returns the number of reaction cells in the reaction module. The number of +reaction cells is defined by the set of non-negative integers in the mapping +from grid cells (:meth:`CreateMapping`), or, by default, the number of grid +cells (:meth:`GetGridCellCount`). The number of reaction cells is less than +or equal to the number of grid cells in the user model. + +Returns: + int: Number of reaction cells." +%enddef +%feature("docstring") PhreeqcRM::GetChemistryCellCount GetChemistryCellCount_DOCSTRING + + +%define GetComponentCount_DOCSTRING +"Returns the number of components in the reaction-module component list. + +Returns: + int: The number of components in the reaction-module component list. The + component list is generated by calls to :meth:`FindComponents`. The + return value from the last call to :meth:`FindComponents` is equal + to the return value from GetComponentCount." +%enddef +%feature("docstring") PhreeqcRM::GetComponentCount GetComponentCount_DOCSTRING + + +%define GetComponents_DOCSTRING +"Returns a reference to the reaction-module component list that was generated +by calls to :meth:`FindComponents`. + +Returns: + tuple of strings: A vector of strings; each string is a component name." +%enddef +%feature("docstring") PhreeqcRM::GetComponents GetComponents_DOCSTRING + + +%define GetConcentrations_DOCSTRING +"Transfer solution concentrations from each reaction cell to the +concentration vector given in the argument list (c). Units of concentration +for c are defined by :meth:`SetUnitsSolution`. For per liter concentration +units, solution volume is used to calculate the concentrations for c. For +mass-fraction concentration units, the solution mass is used to calculate +concentrations for c. Two options are available for the volume and mass of +solution that are used in converting to transport concentrations: (1) the +volume and mass of solution are calculated by PHREEQC, or (2) the volume of +solution is the product of saturation (:meth:`SetSaturation`), porosity +(:meth:`SetPorosity`), and representative volume +(:meth:`SetRepresentativeVolume`), and the mass of solution is volume +times density as defined by :meth:`SetDensity`. +:meth:`UseSolutionDensityVolume` determines which option is used. For option 1 +, the databases that have partial molar volume definitions needed to +accurately calculate solution volume are phreeqc.dat, Amm.dat, and pitzer.dat. + + +Args: + c (DoubleVector): Vector to receive the concentrations. Dimension of the + vector is set to ncomps times nxyz, where, ncomps is the result of + :meth:` FindComponents` or :meth:`GetComponentCount`, and nxyz is + the number of user grid cells (:meth:`GetGridCellCount`). + Values for inactive cells are set to 1e30. + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::GetConcentrations GetConcentrations_DOCSTRING + + +%define GetCurrentSelectedOutputUserNumber_DOCSTRING +"Returns the user number of the current selected-output definition. +:meth:`SetCurrentSelectedOutputUserNumber` or :meth:`SetNthSelectedOutput` +specifies which of the selected-output definitions is used. + +Returns: + int: User number of the the current selected-output definition, + negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::GetCurrentSelectedOutputUserNumber GetCurrentSelectedOutputUserNumber_DOCSTRING + + +%define GetDatabaseFileName_DOCSTRING +"Returns the file name of the database. Should be called after :meth:`LoadDatabase`. + +Returns: + string: The file name defined in :meth:`LoadDatabase`." +%enddef +%feature("docstring") PhreeqcRM::GetDatabaseFileName GetDatabaseFileName_DOCSTRING + + +%define GetDensity_DOCSTRING +"Transfer solution densities from the reaction-module workers to the +vector given in the argument list (density). This method always +returns the calculated densities; :meth:`SetDensity` does not +affect the result. + +Args: + density (DoubleVector): Vector to receive the densities. Dimension + of the array is set to nxyz, where nxyz is the number of + user grid cells (:meth:`GetGridCellCount`). Values for + inactive cells are set to 1e30. Densities are those calculated + by the reaction module. Only the following databases + distributed with PhreeqcRM have molar volume information + needed to accurately calculate density: phreeqc.dat, Amm.dat, + and pitzer.dat. + +Returns: + IRM_RESULT: 0 is success, negative is failure + (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::GetDensity GetDensity_DOCSTRING + + +%define GetEndCell_DOCSTRING +"Returns a vector of integers that contains the largest reaction-cell number +assigned to each worker. Each worker is assigned a range of reaction-cell +numbers that are run during a call to :meth:`RunCells`. The range of reaction +cells for a worker may vary as load rebalancing occurs. At any point in the +calculations, the first cell and last cell to be run by a worker can be found +in the vectors returned by :meth:`GetStartCell` and :meth:`GetEndCell`. Each +method returns a vector of integers that has length of the number of threads +(:meth:`GetThreadCount`), if using OPENMP, or the number of processes +(:meth:`GetMpiTasks`), if using MPI. + +Returns: + IRM_RESULT: Vector of integers, one for each worker, that gives the last + reaction cell to be run by each worker." +%enddef +%feature("docstring") PhreeqcRM::GetEndCell GetEndCell_DOCSTRING + + +%define GetEquilibriumPhases_DOCSTRING +"Returns a reference to the vector of all equilibrium phases. The list +includes all phases included in any EQUILIBRIUM_PHASES definitions in the +initial-phreeqc module. :meth:`FindComponents` must be called before +:meth:`GetEquilibriumPhases`. This method may be useful when generating +selected output definitions related to equilibrium phases. + +Returns: + const tuple of strings: A vector of strings; each string is a unique + equilibrium phases name." +%enddef +%feature("docstring") PhreeqcRM::GetEquilibriumPhases GetEquilibriumPhases_DOCSTRING + + +%define GetEquilibriumPhasesCount_DOCSTRING +"Returns the number of equilibrium phases in the initial-phreeqc module. +:meth:`FindComponents` must be called before +:meth:`GetEquilibriumPhasesCount`. This method may be useful when generating +selected output definitions related to equilibrium phases. + + +Returns: + int: The number of equilibrium phases in the initial-phreeqc module." +%enddef +%feature("docstring") PhreeqcRM::GetEquilibriumPhasesCount GetEquilibriumPhasesCount_DOCSTRING + + +%define GetErrorHandlerMode_DOCSTRING +"Get the setting for the action to be taken when the reaction module +encounters an error. Options are 0, return to calling program with an error +return code (default); 1, throw an exception, which can be caught in C++ (for +C and Fortran, the program will exit); 2, attempt to exit gracefully. + +Returns: + int: Current setting for the error handling mode: 0, 1, or 2." +%enddef +%feature("docstring") PhreeqcRM::GetErrorHandlerMode GetErrorHandlerMode_DOCSTRING + + +%define GetErrorString_DOCSTRING +"Returns a standard string containing error messages related to the last call +to a PhreeqcRM method. + +Returns: + string: Error messages related to the last call to a PhreeqcRM method." +%enddef +%feature("docstring") PhreeqcRM::GetErrorString GetErrorString_DOCSTRING + + +%define GetExchangeNames_DOCSTRING +"Returns a reference to the vector of exchange names (such as 'X') that +correspond with the exchange species names. :meth:`FindComponents` must be +called before :meth:`GetExchangeNames`. The exchange names vector is the same +length as the exchange species names vector and provides the corresponding +exchange site. This method may be useful when generating selected output +definitions related to exchangers. + + +Returns: + const tuple of strings: A vector of strings; each string is an exchange + name corresponding to the exchange species vector; an exchange + name may occur multiple times." +%enddef +%feature("docstring") PhreeqcRM::GetExchangeNames GetExchangeNames_DOCSTRING + + +%define GetExchangeSpecies_DOCSTRING +"Returns a reference to the vector of exchange species names (such as 'NaX'). +The list of exchange species (such as 'NaX') is derived from the list of +components (:meth:`FindComponents`) and the list of all exchange names (such +as 'X') that are included in EXCHANGE definitions in the initial-phreeqc +module. :meth:`FindComponents` must be called before +:meth:`GetExchangeSpecies`. This method may be useful when generating +selected output definitions related to exchangers. + +Returns: + const tuple of strings: Vector of strings; each string is a + unique exchange species name." +%enddef +%feature("docstring") PhreeqcRM::GetExchangeSpecies GetExchangeSpecies_DOCSTRING + + +%define GetExchangeSpeciesCount_DOCSTRING +"Returns the number of exchange species in the initial-phreeqc module. +:meth:`FindComponents` must be called before :meth:`GetExchangeSpeciesCount`. +This method may be useful when generating selected output definitions related +to exchangers. + +Returns: + int: The number of exchange species in the initial-phreeqc module." +%enddef +%feature("docstring") PhreeqcRM::GetExchangeSpeciesCount GetExchangeSpeciesCount_DOCSTRING + + +%define GetFilePrefix_DOCSTRING +"Returns the file prefix for the output (.chem.txt) and log files (.log.txt). + +Returns: + string: The file prefix as set by :meth:`SetFilePrefix`, or 'myrun', by + default." +%enddef +%feature("docstring") PhreeqcRM::GetFilePrefix GetFilePrefix_DOCSTRING + + +%define GetForwardMapping_DOCSTRING +"Returns a reference to a vector of ints that is a mapping from grid cells to +reaction cells. The mapping is used to eliminate cells that are inactive and +cells that are unnecessary because of symmetry from the list of cells for +which reactions must be run. The mapping may be many-to-one to account for +symmetry. The mapping is set by :meth:`CreateMapping`, or, by default, is a +one-to-one mapping--all grid cells are reaction cells (vector contains +0,1,2,3,...,nxyz-1). + +Returns: + const IntVector: A vector of integers of size nxyz (number of grid cells, + :meth:`GetGridCellCount`). Nonnegative is a reaction-cell number + (0 based), negative is an inactive cell." +%enddef +%feature("docstring") PhreeqcRM::GetForwardMapping GetForwardMapping_DOCSTRING + + +%define GetGasComponents_DOCSTRING +"Returns a reference to the vector of all gas components in the +initial-phreeqc module. The list includes all gas components included in any +GAS_PHASE definitions in the initial-phreeqc module. :meth:`FindComponents` +must be called before :meth:`GetGasComponents`. This method may be useful +when generating selected output definitions related to gas phases. + +Returns: + const tuple of strings: Vector of strings; each string is a unique + gas component name." +%enddef +%feature("docstring") PhreeqcRM::GetGasComponents GetGasComponents_DOCSTRING + + +%define GetGasComponentsCount_DOCSTRING +"Returns the number of gas phase components in the initial-phreeqc module. +:meth:`FindComponents` must be called before :meth:`GetGasComponentsCount`. +This method may be useful when generating selected output definitions related +to gas phases. + +Returns: + int: The number of gas phase components in the initial-phreeqc module." +%enddef +%feature("docstring") PhreeqcRM::GetGasComponentsCount GetGasComponentsCount_DOCSTRING + + +%define GetGasCompMoles_DOCSTRING +"Transfer moles of gas components from each reaction cell to the vector given +in the argument list (gas_moles). + + +Args: + gas_moles (DoubleVector): Vector to receive the moles of gas components. + Dimension of the vector is set to ngas_comps times nxyz, where, + ngas_comps is the result of :meth:`GetGasComponentsCount`, and nxyz + is the number of user grid cells (:meth:`GetGridCellCount`). If a + gas component is not defined for a cell, the number of moles is set + to -1. Values for inactive cells are set to 1e30. + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::GetGasCompMoles GetGasCompMoles_DOCSTRING + + +%define GetGasCompPressures_DOCSTRING +"Transfer pressures of gas components from each reaction cell +to the vector given in the argument list (gas_pressure). + + +Args: + gas_pressure (DoubleVector): Vector to receive the pressures of gas + components. Dimension of the vector is set to ngas_comps times nxyz, where + ngas_comps is the result of :meth:`GetGasComponentsCount`, and nxyz is + the number of user grid cells (:meth:`GetGridCellCount`). If a gas + component is not defined for a cell, the pressure is set to -1. Values + for inactive cells are set to 1e30. + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::GetGasCompPressures GetGasCompPressures_DOCSTRING + + +%define GetGasCompPhi_DOCSTRING +"Transfer fugacity coefficients (phi) of gas components from each reaction +cell to the vector given in the argument list (gas_phi). Fugacity is equal to +the gas component pressure times the fugacity coefficient. + +Args: + gas_phi (DoubleVector): Vector to receive the fugacity coefficients of gas + components. Dimension of the vector is set to ngas_comps times nxyz, + where, ngas_comps is the result of :meth:`GetGasComponentsCount`, and + nxyz is the number of user grid cells (:meth:`GetGridCellCount`). If + a gas component is not defined for a cell, the fugacity coefficient + is set to -1. + Values for inactive cells are set to 1e30. + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::GetGasCompPhi GetGasCompPhi_DOCSTRING + + +%define GetGasPhaseVolume_DOCSTRING +"Transfer volume of gas phase from each reaction cell to the vector given in +the argument list (gas_volume). + + +Args: + gas_volume (DoubleVector): Vector to receive the gas phase volumes. + Dimension of the vector is set to nxyz, where, nxyz is the number of user + grid cells (:meth:`GetGridCellCount`). If a gas phase is not defined for + a cell, the volume is set to -1. Values for inactive cells are set to 1e30. + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::GetGasPhaseVolume GetGasPhaseVolume_DOCSTRING + + +%define GetGfw_DOCSTRING +"Returns a reference to a vector of doubles that contains the gram-formula +weight of each component. Called after :meth:`FindComponents`. Order of weights +corresponds to the list of components from :meth:`GetComponents`. + +Returns: + const DoubleVector: A vector of doubles; each value is a component gram- + formula weight, g/mol." +%enddef +%feature("docstring") PhreeqcRM::GetGfw GetGfw_DOCSTRING + + +%define GetGridCellCount_DOCSTRING +"Returns the number of grid cells in the user model, which is defined in the +call to the constructor for the reaction module. The mapping from grid cells to +reaction cells is defined by :meth:`CreateMapping`. The number of reaction cells +may be less than the number of grid cells if there are inactive regions or there +is symmetry in the model definition. + +Returns: + int: Number of grid cells in the user model." +%enddef +%feature("docstring") PhreeqcRM::GetGridCellCount GetGridCellCount_DOCSTRING + + +%define GetIPhreeqcPointer_DOCSTRING +"Returns an IPhreeqc pointer to the ith IPhreeqc instance in the reaction +module. For the threaded version, there are nthreads + 2 IPhreeqc instances, +where nthreads is defined in the constructor (:meth:`PhreeqcRM`::PhreeqcRM). The +number of threads can be determined by :meth:`GetThreadCount`. The first +nthreads (0 based) instances will be the workers, the next (nthreads) is the +InitialPhreeqc instance, and the next (nthreads + 1) is the Utility instance. +Getting the IPhreeqc pointer for one of these instances allows the user to use +any of the IPhreeqc methods on that instance. For MPI, each process has exactly +three IPhreeqc instances, one worker (number 0), one InitialPhreeqc instance +(number 1), and one Utility instance (number 2). + +Args: + i (int): The number of the IPhreeqc instance (0 based) to be retrieved. + +Returns: + IPhreeqc pointer to the ith IPhreeqc instance (0 based) in the reaction + module." +%enddef +%feature("docstring") PhreeqcRM::GetIPhreeqcPointer GetIPhreeqcPointer_DOCSTRING + + +%define GetKineticReactions_DOCSTRING +"Returns a reference to the vector of all kinetic reactions in the +initial-phreeqc module. The list includes all kinetic reactions included in any +KINETICS definitions in the reaction model. :meth:`FindComponents` must be +called before :meth:`GetKineticReactions`. This method may be useful when +generating selected output definitions related to kinetic reactions. + +Returns: + const tuple of strings: Vector of strings; each string is a unique + kinetic reaction name." +%enddef +%feature("docstring") PhreeqcRM::GetKineticReactions GetKineticReactions_DOCSTRING + + +%define GetKineticReactionsCount_DOCSTRING +"Returns the number of kinetic reactions in the initial-phreeqc module. +:meth:`FindComponents` must be called before :meth:`GetKineticReactionsCount`. +This method may be useful when generating selected output definitions related to +kinetic reactions. + + +Returns: + int: The number of kinetic reactions in the initial-phreeqc module." +%enddef +%feature("docstring") PhreeqcRM::GetKineticReactionsCount GetKineticReactionsCount_DOCSTRING + + +%define GetMpiMyself_DOCSTRING +"Returns the MPI process (task) number. For the MPI version, the root task +number is zero, and all MPI tasks have unique task numbers greater than zero. +The number of tasks can be obtained with :meth:`GetMpiTasks`. The number of +tasks and computer hosts is determined at run time by the mpiexec command, and +the number of reaction-module processes is defined by the communicator used in +constructing the reaction modules (:meth:`PhreeqcRM`::PhreeqcRM). For the OPENMP +version, the task number is always zero, and the result of :meth:`GetMpiTasks` +is one. + +Returns: + int: The MPI task number for a process." +%enddef +%feature("docstring") PhreeqcRM::GetMpiMyself GetMpiMyself_DOCSTRING + + +%define GetMpiTasks_DOCSTRING +"Returns the number of MPI processes (tasks) assigned to the reaction module. +For the MPI version, the number of tasks and computer hosts is specified at run +time by the mpiexec command. The number of MPI processes used for reaction +calculations is determined by the MPI communicator used in constructing the +reaction modules. The communicator may define a subset of the total number of +MPI processes. The root task number is zero, and all other MPI tasks have unique +task numbers greater than zero. For the OPENMP version, the number of tasks is +one, and the task number returned by :meth:`GetMpiMyself` is zero. + +Returns: + int: The number of MPI processes assigned to the reaction module." +%enddef +%feature("docstring") PhreeqcRM::GetMpiTasks GetMpiTasks_DOCSTRING + + +%define GetNthSelectedOutputUserNumber_DOCSTRING +"Returns the user number for the nth selected-output definition. Definitions are +sorted by user number. Phreeqc allows multiple selected-output definitions, each +of which is assigned a nonnegative integer identifier by the user. The number of +definitions can be obtained by :meth:`GetSelectedOutputCount`. To cycle through +all of the definitions, GetNthSelectedOutputUserNumber can be used to identify +the user number for each selected-output definition in sequence. +:meth:`SetCurrentSelectedOutputUserNumber` is then used to select that user +number for selected-output processing. + +Args: + n (int): The sequence number of the selected-output definition for which + the user number will be returned. Fortran, 1 based; C, 0 based. + +Returns: + int: The user number of the nth selected-output definition, negative is + failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::GetNthSelectedOutputUserNumber GetNthSelectedOutputUserNumber_DOCSTRING + + +%define GetPartitionUZSolids_DOCSTRING +"Returns the setting for partitioning solids between the saturated and +unsaturated parts of a partially saturated cell. The option is intended to be +used by saturated-only flow codes that allow a variable water table. The value +has meaning only when saturations less than 1.0 are encountered. The partially +saturated cells may have a small water-to-rock ratio that causes reactions to +proceed slowly relative to fully saturated cells. By setting +:meth:`SetPartitionUZSolids` to true, the amounts of solids and gases are +partioned according to the saturation. If a cell has a saturation of 0.5, then +the water interacts with only half of the solids and gases; the other half is +unreactive until the water table rises. As the saturation in a cell varies, +solids and gases are transferred between the saturated and unsaturated +(unreactive) reservoirs of the cell. Unsaturated-zone flow and transport codes +will probably use the default (false), which assumes all gases and solids are +reactive regardless of saturation. + +Returns: + Boolean: True, the fraction of solids and gases available for reaction is + equal to the saturation; False (default), all solids and gases are + reactive regardless of saturation." +%enddef +%feature("docstring") PhreeqcRM::GetPartitionUZSolids GetPartitionUZSolids_DOCSTRING + + +%define GetPoreVolume_DOCSTRING +"Returns the current set of pore volumes as defined by the last use of +:meth:`SetPoreVolume` or the default (0.1 L). Pore volume is used with cell +volume (:meth:`SetCellVolume`) in calculating porosity. Pore volumes may change +as a function of pressure, in which case they can be updated with +:meth:`SetPoreVolume`. + +Returns: + const DoubleVector: A vector reference to the pore volumes. + Size of vector is nxyz, the number of grid cells in the user model + (:meth:`GetGridCellCount`)." +%enddef +%feature("docstring") PhreeqcRM::GetPoreVolume GetPoreVolume_DOCSTRING + + +%define GetPorosity_DOCSTRING +"Returns the porosity for each cell. By default, the porosity vector is +initialized with 0.1, unitless. PhreeqcRM does not change the porosity, so the +values that are retrieved are either the default, or the values set by the last +call to :meth:`SetPorosity`. + +Returns: + const DoubleVector: A vector reference to the porosities in each cell, + unitless. Size of vector is nxyz, the number of grid cells in the user + model (:meth:`GetGridCellCount`)." +%enddef +%feature("docstring") PhreeqcRM::GetPorosity GetPorosity_DOCSTRING + + +%define GetPressure_DOCSTRING +"Returns the pressure for each cell. By default, the pressure vector is +initialized with 1 atm; if :meth:`SetPressure` has not been called, worker +solutions will have pressures as defined in input files (:meth:`RunFile`) or +input strings (:meth:`RunString`); if :meth:`SetPressure` has been called, +worker solutions will have the pressures as defined by :meth:`SetPressure`. +Pressure effects are considered by three PHREEQC databases: phreeqc.dat, +Amm.dat, and pitzer.dat. + +Returns: + const DoubleVector: A vector reference to the pressures in each cell, in atm. + Size of vector is nxyz, the number of grid cells in the user model + (:meth:`GetGridCellCount`)." +%enddef +%feature("docstring") PhreeqcRM::GetPressure GetPressure_DOCSTRING + + +%define GetPrintChemistryMask_DOCSTRING +"Return a reference to the vector of print flags that enable or disable detailed +output for each cell. Printing for a cell will occur only when the printing is +enabled with :meth:`SetPrintChemistryOn`, and the value in the vector for the +cell is 1. + +Returns: + IntVector: Vector of integers. Size of vector is nxyz, where nxyz is the + number of grid cells in the user model (:meth:`GetGridCellCount`). A value of + 0 for a cell indicates printing is disabled; a value of 1 for a cell + indicates printing is enabled." +%enddef +%feature("docstring") PhreeqcRM::GetPrintChemistryMask GetPrintChemistryMask_DOCSTRING + + +%define GetPrintChemistryOn_DOCSTRING +"Returns a vector reference to the current print flags for detailed output for +the three sets of IPhreeqc instances: the workers, the InitialPhreeqc instance, +and the Utility instance. Dimension of the vector is 3. Printing of detailed +output from reaction calculations to the output file is enabled when the vector +value is true, disabled when false. The detailed output prints all of the output +typical of a PHREEQC reaction calculation, which includes solution descriptions +and the compositions of all other reactants. The output can be several hundred +lines per cell, which can lead to a very large output file (prefix.chem.txt, +:meth:`OpenFiles`). For the worker instances, the output can be limited to a set +of cells (:meth:`SetPrintChemistryMask`) and, in general, the amount of +information printed can be limited by use of options in the PRINT data block of +PHREEQC (applied by using :meth:`RunFile` or :meth:`RunString`). Printing the +detailed output for the workers is generally used only for debugging, and +PhreeqcRM will run faster when printing detailed output for the workers is +disabled (:meth:`SetPrintChemistryOn`). + +Returns: + const BoolVector: Print flag for the workers, InitialPhreeqc, and Utility + IPhreeqc instances, respectively." +%enddef +%feature("docstring") PhreeqcRM::GetPrintChemistryOn GetPrintChemistryOn_DOCSTRING + + +%define GetRebalanceByCell_DOCSTRING +"Get the load-rebalancing method used for parallel processing. PhreeqcRM +attempts to rebalance the load of each thread or process such that each thread +or process takes the same amount of time to run its part of a :meth:`RunCells` +calculation. Two algorithms are available: one accounts for cells that were not +run because saturation was zero (true), and the other uses the average time to +run all of the cells assigned to a process or thread (false), . The methods are +similar, but preliminary results indicate the default is better in most cases. + +Returns: + Boolean: True indicates individual cell run times are used in rebalancing + (default); False, indicates average run times are used in rebalancing." +%enddef +%feature("docstring") PhreeqcRM::GetRebalanceByCell GetRebalanceByCell_DOCSTRING + + +%define GetRebalanceFraction_DOCSTRING +"Get the fraction used to determine the number of cells to transfer among +threads or processes. PhreeqcRM attempts to rebalance the load of each thread or +process such that each thread or process takes the same amount of time to run +its part of a :meth:`RunCells` calculation. The rebalancing transfers cell +calculations among threads or processes to try to achieve an optimum balance. +:meth:`SetRebalanceFraction` adjusts the calculated optimum number of cell +transfers by a fraction from 0 to 1.0 to determine the number of cell transfers +that actually are made. A value of zero eliminates load rebalancing. A value +less than 1.0 is suggested to avoid possible oscillations, where too many cells +are transferred at one iteration, requiring reverse transfers at the next +iteration. Default is 0.5. + +Returns: + float: Fraction used in rebalance, 0.0 to 1.0." +%enddef +%feature("docstring") PhreeqcRM::GetRebalanceFraction GetRebalanceFraction_DOCSTRING + + +%define GetSaturation_DOCSTRING +"Returns a vector of saturations (sat) as calculated by the reaction +module. This method always returns solution_volume/(rv * porosity); +the method :meth:`SetSaturation` has no effect on the values returned. +Reactions will change the volume of solution in a cell. The transport +code must decide whether to ignore or account for this change in +solution volume due to reactions. Following reactions, the cell +saturation is calculated as solution volume (:meth:`GetSolutionVolume`) +divided by the product of representative volume +(:meth:`SetRepresentativeVolume`) and the porosity (:meth:`SetPorosity`). The +cell saturation returned by GetSaturation may be less than or greater +than the saturation set by the transport code (:meth:`SetSaturation`), +and may be greater than or less than 1.0, even in fully saturated +simulations. Only the following databases distributed with PhreeqcRM +have molar volume information needed to accurately calculate solution +volume and saturation: phreeqc.dat, Amm.dat, and pitzer.dat. + +Args: + sat (DoubleVector): Vector to receive the saturations. Dimension + of the array is set to nxyz, where nxyz is the number of user + grid cells (:meth:`GetGridCellCount`). Values for inactive + cells are set to 1e30. + +Returns: + IRM_RESULT: 0 is success, negative is failure + (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::GetSaturation GetSaturation_DOCSTRING + + +%define GetSelectedOutput_DOCSTRING +"Returns the array of selected-output values for the current +selected-output definition. :meth:`SetCurrentSelectedOutputUserNumber` +specifies which of the selected-output definitions is returned to the +vector (so). + +Args: + so (DoubleVector): A vector to contain the selected-output values. + Size of the vector is set to col times nxyz, where col is the + number of columns in the selected-output definition + (:meth:`GetSelectedOutputColumnCount`), and nxyz is the number + of grid cells in the user model (:meth:`GetGridCellCount`). + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::GetSelectedOutput GetSelectedOutput_DOCSTRING + + +%define GetSelectedOutputColumnCount_DOCSTRING +"Returns the number of columns in the current selected-output definition. +:meth:`SetCurrentSelectedOutputUserNumber` specifies which of the +selected-output definitions is used. + +Returns: + int: Number of columns in the current selected-output definition, + negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::GetSelectedOutputColumnCount GetSelectedOutputColumnCount_DOCSTRING + + +%define GetSelectedOutputCount_DOCSTRING +"Returns the number of selected-output definitions. +:meth:`SetCurrentSelectedOutputUserNumber` specifies which of the +selected-output definitions is used. + +Returns: + int: Number of selected-output definitions, negative is failure + (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::GetSelectedOutputCount GetSelectedOutputCount_DOCSTRING + + +%define GetSelectedOutputHeading_DOCSTRING +"Returns a selected-output heading. The number of headings is determined +by :meth:`GetSelectedOutputColumnCount`. +:meth:`SetCurrentSelectedOutputUserNumber` specifies which of the +selected-output definitions is used. + +Args: + icol (int): The sequence number of the heading to be retrieved, + 0 based. + heading(string): A string to receive the heading. + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::GetSelectedOutputHeading GetSelectedOutputHeading_DOCSTRING + + +%define GetSelectedOutputHeadings_DOCSTRING +"Returns a list of the current selected-output headings. The number of +headings is determined by :meth:`GetSelectedOutputColumnCount`. +:meth:`SetCurrentSelectedOutputUserNumber` or +:meth:`BMI_SetValue`('NthSelectedOutput',i) are used to specify which +of the selected-output definitions is used. + +Args: + headings (tuple of strings): A vector of std::strings to receive + the headings. + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::GetSelectedOutputHeadings GetSelectedOutputHeadings_DOCSTRING + + +%define GetSelectedOutputOn_DOCSTRING +"Returns the current value of the selected-output property. A value of +true for this property indicates that selected output data will be +requested this time step. A value of false indicates that selected +output will not be retrieved for this time step; processing the selected +output is avoided with some time savings. + +Returns: + Boolean: True, selected output will be requested; false, selected + output will not be retrieved." +%enddef +%feature("docstring") PhreeqcRM::GetSelectedOutputOn GetSelectedOutputOn_DOCSTRING + + +%define GetSelectedOutputRowCount_DOCSTRING +"Returns the number of rows in the current selected-output definition. +However, the method is included only for convenience; the number of +rows is always equal to the number of grid cells in the user model +(:meth:`GetGridCellCount`). + +Returns: + int: Number of rows in the current selected-output definition, + negative is failure." +%enddef +%feature("docstring") PhreeqcRM::GetSelectedOutputRowCount GetSelectedOutputRowCount_DOCSTRING + + +%define GetSICount_DOCSTRING +"Returns the number of phases in the initial-phreeqc module for which +saturation indices could be calculated. :meth:`FindComponents` must be +called before :meth:`GetSICount`. This method may be useful when +generating selected output definitions related to saturation indices. + +Returns: + int: The number of phases in the initial-phreeqc module for which + saturation indices could be calculated." +%enddef +%feature("docstring") PhreeqcRM::GetSICount GetSICount_DOCSTRING + + +%define GetSINames_DOCSTRING +"Returns a reference to the vector of the names of all phases for which +saturation indices (SIs) could be calculated. The list includes all phases that +contain only elements included in the components in the initial-phreeqc module. +The list assumes that all components are present to be able to calculate the +entire list of SIs; it may be that one or more components are missing in any +specific cell. :meth:`FindComponents` must be called before :meth:`GetSINames`. +This method may be useful when generating selected output definitions related to +saturation indices. + + +Returns: + const tuple of strings: Vector of strings; each string is a unique + phase name." +%enddef +%feature("docstring") PhreeqcRM::GetSINames GetSINames_DOCSTRING + + +%define GetSolidSolutionComponents_DOCSTRING +"Returns a reference to the vector of solid solution components. The list of +solid solution components includes all components in any SOLID_SOLUTION +definitions in the initial-phreeqc module. :meth:`FindComponents` must be +called before :meth:`GetSolidSolutionComponents`. This method may be useful +when generating selected output definitions related to solid solutions. + + +Returns: + const tuple of strings: Vector of strings; each string is a + unique solid solution component." +%enddef +%feature("docstring") PhreeqcRM::GetSolidSolutionComponents GetSolidSolutionComponents_DOCSTRING + + +%define GetSolidSolutionComponentsCount_DOCSTRING +"Returns the number of solid solution components in the initial-phreeqc module. +:meth:`FindComponents` must be called before +:meth:`GetSolidSolutionComponentsCount`. This method may be useful when +generating selected output definitions related to solid solutions. + + +Returns: + int: The number of solid solution components in the initial-phreeqc + module." +%enddef +%feature("docstring") PhreeqcRM::GetSolidSolutionComponentsCount GetSolidSolutionComponentsCount_DOCSTRING + + +%define GetSolidSolutionNames_DOCSTRING +"Returns a reference to the vector of solid solution names that correspond with +the solid solution components. :meth:`FindComponents` must be called before +:meth:`GetSolidSolutionNames`. The solid solution names vector is the same +length as the solid solution components vector and provides the corresponding +name of solid solution containing the component. This method may be useful when +generating selected output definitions related to solid solutions. + +Returns: + const tuple of strings: Vector of strings; each string is a solid solution + name corresponding to the solid solution components vector; a solid solution + name may occur multiple times." +%enddef +%feature("docstring") PhreeqcRM::GetSolidSolutionNames GetSolidSolutionNames_DOCSTRING + + +%define GetSolutionVolume_DOCSTRING +"Return a vector reference to the current solution volumes as calculated by the +reaction module. Dimension of the vector will be nxyz, where nxyz is the number +of user grid cells. Values for inactive cells are set to 1e30. Only the +following databases distributed with PhreeqcRM have molar volume information +needed to accurately calculate solution volume: phreeqc.dat, Amm.dat, and +pitzer.dat. + +Returns: + DoubleVector: Vector reference to current solution volumes." +%enddef +%feature("docstring") PhreeqcRM::GetSolutionVolume GetSolutionVolume_DOCSTRING + + +%define GetSpeciesConcentrations_DOCSTRING +"Returns a vector reference to aqueous species concentrations (species_conc). +This method is intended for use with multicomponent-diffusion transport +calculations, and :meth:`SetSpeciesSaveOn` must be set to true. The list of +aqueous species is determined by :meth:`FindComponents` and includes all +aqueous species that can be made from the set of components. Solution volumes +used to calculate mol/L are calculated by the reaction module. Only the +following databases distributed with PhreeqcRM have molar volume information +needed to accurately calculate solution volume: phreeqc.dat, Amm.dat, and +pitzer.dat. + +Args: + species_conc (DoubleVector): Vector to receive the aqueous species + concentrations. Dimension of the vector is set to nspecies times nxyz, + where nspecies is the number of aqueous species (:meth:`GetSpeciesCount`), and + nxyz is the number of grid cells (:meth:`GetGridCellCount`). + Concentrations are moles per liter. Values for inactive cells are set + to 1e30. + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::GetSpeciesConcentrations GetSpeciesConcentrations_DOCSTRING + + +%define GetSpeciesCount_DOCSTRING +"Returns the number of aqueous species used in the reaction module. This method +is intended for use with multicomponent-diffusion transport calculations, and +:meth:`SetSpeciesSaveOn` must be set to true. The list of aqueous species is +determined by :meth:`FindComponents` and includes all aqueous species that can +be made from the set of components. + +Returns: + int: The number of aqueous species." +%enddef +%feature("docstring") PhreeqcRM::GetSpeciesCount GetSpeciesCount_DOCSTRING + + +%define GetSpeciesD25_DOCSTRING +"Returns a vector reference to diffusion coefficients at 25C for the set of +aqueous species. This method is intended for use with multicomponent-diffusion +transport calculations, and :meth:`SetSpeciesSaveOn` must be set to true. +Diffusion coefficients are defined in SOLUTION_SPECIES data blocks, normally in +the database file. Databases distributed with the reaction module that have +diffusion coefficients defined are phreeqc.dat, Amm.dat, and pitzer.dat. + +Returns: + DoubleVector: Vector reference to the diffusion coefficients at 25 C, m^2/s. + Dimension of the vector is nspecies, where nspecies is the number of + aqueous species (:meth:`GetSpeciesCount`)." +%enddef +%feature("docstring") PhreeqcRM::GetSpeciesD25 GetSpeciesD25_DOCSTRING + + +%define GetSpeciesLog10Gammas_DOCSTRING +"Returns a vector reference to log10 aqueous species activity coefficients +(species_log10gammas). This method is intended for use with +multicomponent-diffusion transport calculations, and :meth:`SetSpeciesSaveOn` +must be set to true. The list of aqueous species is determined by +:meth:`FindComponents` and includes all aqueous species that can be made from +the set of components. + + +Args: + species_log10gammas (DoubleVector): Vector to receive the log10 aqueous + species activity coefficients. Dimension of the vector is set to nspecies + times nxyz, where nspecies is the number of aqueous species (:meth:` + GetSpeciesCount`), and nxyz is the number of grid cells (:meth:` + GetGridCellCount`). Values for inactive cells are set to 1e30. + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::GetSpeciesLog10Gammas GetSpeciesLog10Gammas_DOCSTRING + + +%define GetSpeciesLog10Molalities_DOCSTRING +"Returns a vector reference to log10 aqueous species molalities +(species_log10molalities). To use this method :meth:`SetSpeciesSaveOn` must be +set to true. The list of aqueous species is determined by +:meth:`FindComponents` and includes all aqueous species that can be made from +the set of components. + +Args: + species_log10molalities (DoubleVector): Vector to receive the log10 aqueous + species molalites. Dimension of the vector is set to nspecies times nxyz, + where nspecies is the number of aqueous species (:meth:`GetSpeciesCount`), + and nxyz is the number of grid cells (:meth:`GetGridCellCount`). + Values for inactive cells are set to 1e30. + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::GetSpeciesLog10Molalities GetSpeciesLog10Molalities_DOCSTRING + + +%define GetSpeciesNames_DOCSTRING +"Returns a vector reference to the names of the aqueous species. This method is +intended for use with multicomponent-diffusion transport calculations, and +:meth:`SetSpeciesSaveOn` must be set to true. The list of aqueous species is +determined by :meth:`FindComponents` and includes all aqueous species that can +be made from the set of components. + +Returns: + tuple of strings: Vector of strings containing the names of the aqueous + species. Dimension of the vector is nspecies, where nspecies is the number + of aqueous species (:meth:`GetSpeciesCount`)." +%enddef +%feature("docstring") PhreeqcRM::GetSpeciesNames GetSpeciesNames_DOCSTRING + + +%define GetSpeciesSaveOn_DOCSTRING +"Returns the value of the species-save property. By default, concentrations of +aqueous species are not saved. Setting the species-save property to true allows +aqueous species concentrations to be retrieved with +:meth:`GetSpeciesConcentrations`, and solution compositions to be set with +:meth:`SpeciesConcentrations2Module`. + + +Returns: + Boolean: True indicates solution species concentrations are saved and can be + used for multicomponent-diffusion calculations; False indicates that + solution species concentrations are not saved." +%enddef +%feature("docstring") PhreeqcRM::GetSpeciesSaveOn GetSpeciesSaveOn_DOCSTRING + + +%define GetSpeciesStoichiometry_DOCSTRING +"Returns a vector reference to the stoichiometry of each aqueous species. This +method is intended for use with multicomponent-diffusion transport +calculations, and :meth:`SetSpeciesSaveOn` must be set to true. + + +Returns: + Vector of cxxNameDouble instances (maps) that contain the component names + and associated stoichiometric coefficients for each aqueous species. + Dimension of the vector is nspecies, where nspecies is the number of + aqueous species (:meth:`GetSpeciesCount`)." +%enddef +%feature("docstring") PhreeqcRM::GetSpeciesStoichiometry GetSpeciesStoichiometry_DOCSTRING + + +%define GetSpeciesZ_DOCSTRING +"Returns a vector reference to the charge on each aqueous species. This method +is intended for use with multicomponent-diffusion transport calculations, and +:meth:`SetSpeciesSaveOn` must be set to true. + +Returns: + DoubleVector: Vector containing the charge on each aqueous species. + Dimension of the vector is nspecies, where nspecies is the number of + aqueous species (:meth:`GetSpeciesCount`)." +%enddef +%feature("docstring") PhreeqcRM::GetSpeciesZ GetSpeciesZ_DOCSTRING + + +%define GetStartCell_DOCSTRING +"Returns a vector of integers that contains the smallest reaction-cell number +assigned to each worker. Each worker is assigned a range of reaction-cell +numbers that are run during a call to :meth:`RunCells`. The range of reaction +cell numbers for a worker may vary as load rebalancing occurs. At any point in +the calculations, the first cell and last cell to be run by a worker can be +found in the vectors returned by GetStartCell and :meth:`GetEndCell`. Each +method returns a vector of integers that has size of the number of threads +(:meth:`GetThreadCount`), if using OPENMP, or the number of processes +(:meth:`GetMpiTasks`), if using MPI. + +Returns: + IntVector: Vector of integers, one for each worker, that gives the first + reaction cell to be run by each worker." +%enddef +%feature("docstring") PhreeqcRM::GetStartCell GetStartCell_DOCSTRING + + +%define GetSurfaceNames_DOCSTRING +"Returns a reference to the vector of surface names (such as 'Hfo') that +correspond with the surface species names. The vectors referenced by +:meth:`GetSurfaceSpecies` and :meth:`GetSurfaceNames` are the same length. +:meth:`FindComponents` must be called before :meth:`GetSurfaceNames`. This +method may be useful when generating selected output definitions related to +surfaces. + +Returns: + const tuple of strings: Vector of strings; each string is a + surface name corresponding to the surface species vector; + a surface name may occur multiple times." +%enddef +%feature("docstring") PhreeqcRM::GetSurfaceNames GetSurfaceNames_DOCSTRING + + +%define GetSurfaceSpecies_DOCSTRING +"Returns a reference to the vector of surface species names (such as +'Hfo_wOH'). The list of surface species is derived from the list of components +(:meth:`FindComponents`) and the list of all surface site types (such as +'Hfo_w') that are included in SURFACE definitions in the initial-phreeqc +module. :meth:`FindComponents` must be called before :meth:`GetSurfaceSpecies`. +This method may be useful when generating selected output definitions related +to surfaces. + + +Returns: + const tuple of strings: Each string is a unique surface species name." +%enddef +%feature("docstring") PhreeqcRM::GetSurfaceSpecies GetSurfaceSpecies_DOCSTRING + + +%define GetSurfaceSpeciesCount_DOCSTRING +"Returns the number of surface species (such as 'Hfo_wOH') in the +initial-phreeqc module. :meth:`FindComponents` must be called before +:meth:`GetSurfaceSpeciesCount`. This method may be useful when generating +selected output definitions related to surfaces. + +Returns: + int: The number of surface species in the initial-phreeqc module." +%enddef +%feature("docstring") PhreeqcRM::GetSurfaceSpeciesCount GetSurfaceSpeciesCount_DOCSTRING + + +%define GetSurfaceTypes_DOCSTRING +"Returns a reference to the vector of surface site types (such as 'Hfo_w') that +correspond with the surface species names. The vectors referenced by +:meth:`GetSurfaceSpecies` and :meth:`GetSurfaceTypes` are the same length. +:meth:`FindComponents` must be called before :meth:`GetSurfaceTypes`. This +method may be useful when generating selected output definitions related to +surfaces. + + +Returns: + const tuple of strings: Vector of strings; each string is a surface site + type for the corresponding species in the surface species vector; a + surface site type may occur multiple times." +%enddef +%feature("docstring") PhreeqcRM::GetSurfaceTypes GetSurfaceTypes_DOCSTRING + + +%define GetTemperature_DOCSTRING +"Vector reference to the current temperatures of the cells. By default, the +temperature vector is initialized to 25 C; if :meth:`SetTemperature` has not +been called, worker solutions will have temperatures as defined in input files +(:meth:`RunFile`) or input strings (:meth:`RunString`); if +:meth:`SetTemperature` has been called, worker solutions will have the +temperatures as defined by :meth:`SetTemperature`. + +Returns: + DoubleVector: Vector of temperatures, in degrees C. Size of vector is nxyz, + where nxyz is the number of grid cells in the user model (:meth:` + GetGridCellCount`)." +%enddef +%feature("docstring") PhreeqcRM::GetTemperature GetTemperature_DOCSTRING + + +%define GetThreadCount_DOCSTRING +"Returns the number of threads, which is equal to the number of workers used to +run in parallel with OPENMP. For the OPENMP version, the number of threads is +set implicitly or explicitly with the constructor +(:meth:`PhreeqcRM`::PhreeqcRM). For the MPI version, the number of threads is +always one for each process. + +Returns: + int: The number of threads used for OPENMP parallel processing." +%enddef +%feature("docstring") PhreeqcRM::GetThreadCount GetThreadCount_DOCSTRING + + +%define GetTime_DOCSTRING +"Returns the current simulation time in seconds. The reaction module does not +change the time value, so the returned value is equal to the default (0.0) or +the last time set by :meth:`SetTime`. + +Returns: + float: The current simulation time, in seconds." +%enddef +%feature("docstring") PhreeqcRM::GetTime GetTime_DOCSTRING + + +%define GetTimeConversion_DOCSTRING +"Returns a multiplier to convert time from seconds to another unit, as +specified by the user. The reaction module uses seconds as the time unit. The +user can set a conversion factor (:meth:`SetTimeConversion`) and retrieve it +with GetTimeConversion. The reaction module only uses the conversion factor +when printing the long version of cell chemistry (:meth:`SetPrintChemistryOn`), +which is rare. Default conversion factor is 1.0. + +Returns: + float: Multiplier to convert seconds to another time unit." +%enddef +%feature("docstring") PhreeqcRM::GetTimeConversion GetTimeConversion_DOCSTRING + + +%define GetTimeStep_DOCSTRING +"Returns the current simulation time step in seconds. This is the time over +which kinetic reactions are integrated in a call to :meth:`RunCells`. The +reaction module does not change the time-step value, so the returned value is +equal to the default (0.0) or the last time step set by :meth:`SetTimeStep`. + +Returns: + float: The current simulation time step, in seconds." +%enddef +%feature("docstring") PhreeqcRM::GetTimeStep GetTimeStep_DOCSTRING + + +%define GetUnitsExchange_DOCSTRING +"Returns the input units for exchangers. In PHREEQC input, exchangers are +defined by moles of exchange sites (Mp). :meth:`SetUnitsExchange` specifies how +the number of moles of exchange sites in a reaction cell (Mc) is calculated +from the input value (Mp). + +Options are 0, Mp is mol/L of RV (default), Mc = Mp*RV, where RV is the +representative volume (:meth:`SetRepresentativeVolume`); 1, Mp is mol/L of +water in the RV, Mc = Mp*P*RV, where P is porosity (:meth:`SetPorosity`); or +2, Mp is mol/L of rock in the RV, Mc = Mp*(1-P)*RV. + +Returns: + int: Input units for exchangers." +%enddef +%feature("docstring") PhreeqcRM::GetUnitsExchange GetUnitsExchange_DOCSTRING + + +%define GetUnitsGasPhase_DOCSTRING +"Returns the input units for gas phases. In PHREEQC input, gas phases are +defined by moles of component gases (Mp). :meth:`SetUnitsGasPhase` specifies +how the number of moles of component gases in a reaction cell (Mc) is +calculated from the input value (Mp). + +Options are 0, Mp is mol/L of RV (default), Mc = Mp*RV, where RV is the +representative volume (:meth:`SetRepresentativeVolume`); 1, Mp is mol/L of +water in the RV, Mc = Mp*P*RV, where P is porosity (:meth:`SetPorosity`); or +2, Mp is mol/L of rock in the RV, Mc = Mp*(1-P)*RV. + +Returns: + int: Input units for gas phases (0, 1, or 2)." +%enddef +%feature("docstring") PhreeqcRM::GetUnitsGasPhase GetUnitsGasPhase_DOCSTRING + + +%define GetUnitsKinetics_DOCSTRING +"Returns the input units for kinetic reactants. In PHREEQC input, kinetics are +defined by moles of kinetic reactants (Mp). :meth:`SetUnitsKinetics` specifies +how the number of moles of kinetic reactants in a reaction cell (Mc) is +calculated from the input value (Mp). + +Options are 0, Mp is mol/L of RV (default), Mc = Mp*RV, where RV is +the representative volume (:meth:`SetRepresentativeVolume`); 1, Mp is +mol/L of water in the RV, Mc = Mp*P*RV, where P is porosity +(:meth:`SetPorosity`); or 2, Mp is mol/L of rock in the RV, Mc = Mp*(1-P)*RV. + +Returns: + int: Input units for kinetic reactants (0, 1, or 2)." +%enddef +%feature("docstring") PhreeqcRM::GetUnitsKinetics GetUnitsKinetics_DOCSTRING + + +%define GetUnitsPPassemblage_DOCSTRING +"Returns the input units for pure phase assemblages (equilibrium phases). In +PHREEQC input, equilibrium phases are defined by moles of each phase (Mp). +:meth:`SetUnitsPPassemblage` specifies how the number of moles of phases in a +reaction cell (Mc) is calculated from the input value (Mp). + +Options are 0, Mp is mol/L of RV (default), Mc = Mp*RV, where RV is +the representative volume (:meth:`SetRepresentativeVolume`); 1, Mp is +mol/L of water in the RV, Mc = Mp*P*RV, where P is porosity +(:meth:`SetPorosity`); or 2, Mp is mol/L of rock in the RV, Mc = Mp*(1-P)*RV. + +Returns: + int: Input units for equilibrium phases (0, 1, or 2)." +%enddef +%feature("docstring") PhreeqcRM::GetUnitsPPassemblage GetUnitsPPassemblage_DOCSTRING + + +%define GetUnitsSolution_DOCSTRING +"Returns the units of concentration used by the transport model. Options are 1, +mg/L; 2 mol/L; or 3, mass fraction, kg/kgs. In PHREEQC, solutions are defined +by the number of moles of each element in the solution. The units of transport +concentration are used when transport concentrations are converted to solution +moles by :meth:`SetConcentrations` and :meth:`Concentrations2Utility`. The +units of solution concentration also are used when solution moles are converted +to transport concentrations by :meth:`GetConcentrations`. + +To convert from mg/L to moles of element in the representative volume of a +reaction cell, mg/L is converted to mol/L and multiplied by the solution volume, + which is the product of porosity (:meth:`SetPorosity`), saturation +(:meth:` SetSaturation`), and representative volume +(:meth:` SetRepresentativeVolume`). To convert from mol/L to moles of element +in a cell , mol/L is multiplied by the solution volume. To convert from mass +fraction to moles of element in a cell, kg /kgs is converted to mol/kgs, +multiplied by density (:meth:`SetDensity`) and multiplied by the solution volume. + +To convert from moles of element in the representative volume of a reaction cell + to mg/L, the number of moles of an element is divided by the solution volume +resulting in mol/L, and then converted to mg/L. To convert from moles of element + in the representative volume of a reaction cell to mol/L, the number of moles +of an element is divided by the solution volume resulting in mol/L. To convert +from moles of element in the representative volume of a reaction cell to mass +fraction, the number of moles of an element is converted to kg and divided by +the total mass of the solution. Two options are available for the volume and +mass of solution that are used in converting to transport concentrations: (1) +the volume and mass of solution are calculated by PHREEQC, or (2) the volume of +solution is the product of porosity, saturation, and representative volume, and +the mass of solution is volume times density as defined by :meth:`SetDensity`. +Which option is used is determined by :meth:`UseSolutionDensityVolume`. + +Returns: + int: Units for concentrations in transport." +%enddef +%feature("docstring") PhreeqcRM::GetUnitsSolution GetUnitsSolution_DOCSTRING + + +%define GetUnitsSSassemblage_DOCSTRING +"Returns the input units for solid-solution assemblages. In PHREEQC input, +solid solutions are defined by moles of each component (Mp). +:meth:`SetUnitsSSassemblage` specifies how the number of moles in a reaction +cell (Mc) is calculated from the input value (Mp). + +Options are 0, Mp is mol/L of RV (default), Mc = Mp*RV, where RV is the +representative volume (:meth:`SetRepresentativeVolume`); 1, Mp is mol/L of +water in the RV, Mc = Mp*P*RV, where P is porosity (:meth:`SetPorosity`); or +2, Mp is mol/L of rock in the RV, Mc = Mp*(1-P)*RV. + +Returns: + int: Input units for solid solutions (0, 1, or 2)." +%enddef +%feature("docstring") PhreeqcRM::GetUnitsSSassemblage GetUnitsSSassemblage_DOCSTRING + + +%define GetUnitsSurface_DOCSTRING +"Returns the input units for surfaces. In PHREEQC input, surfaces are defined +by moles of surface sites (Mp). :meth:`SetUnitsSurface` specifies how the +number of moles of surface sites in a reaction cell (Mc) is calculated from the +input value (Mp). + +Options are 0, Mp is mol/L of RV (default), Mc = Mp*RV, where RV is the +representative volume (:meth:`SetRepresentativeVolume`); 1, Mp is mol/L of +water in the RV, Mc = Mp*P*RV, where P is porosity (:meth:`SetPorosity`); or +2, Mp is mol/L of rock in the RV, Mc = Mp*(1-P)*RV. + +Returns: + int: Input units for solid surfaces (0, 1, or 2)." +%enddef +%feature("docstring") PhreeqcRM::GetUnitsSurface GetUnitsSurface_DOCSTRING + + +%define GetWorkers_DOCSTRING +"Returns a reference to the vector of IPhreeqcPhast instances. IPhreeqcPhast +inherits from IPhreeqc, and the vector can be interpreted as a vector of +pointers to the worker, InitialPhreeqc, and Utility IPhreeqc instances. For +OPENMP, there are nthreads workers, where nthreads is defined in the +constructor (:meth:`PhreeqcRM`::PhreeqcRM). For MPI, there is a single worker. +For OPENMP and MPI, there is one InitialPhreeqc and one Utility instance. + +Returns: + Vector of IPhreeqcPhast instances." +%enddef +%feature("docstring") PhreeqcRM::GetWorkers GetWorkers_DOCSTRING + + +%define InitializeYAML_DOCSTRING +"A YAML file can be used to initialize an instance of PhreeqcRM. + +Args: + yamlfile (string): String containing the YAML file name. + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`). + +The file contains a YAML map of PhreeqcRM methods +and the arguments corresponding to the methods. For example, + +LoadDatabase: phreeqc.dat +RunFile: +workers: true +initial_phreeqc: true +utility: true +chemistry_name: advect.pqi + +:meth:`InitializeYAML` will read the YAML file and execute the specified methods + with the specified arguments. Using YAML terminology, the argument(s) for a +method may be a scalar, a sequence, or a map, depending if the argument is a +single item, a single vector, or there are multiple arguments. In the case of a +map, the names associated with each argument (for example 'chemistry_name' above) +is arbitrary. The names of the map keys for map arguments are not used in +parsing the YAML file; only the order of the arguments is important. + +The class YAMLPhreeqcRM can be used to write a YAML file. The methods defined in +the YAMLPhreeqcRM class include the following list; all but SetGridCellCount +correspond to PhreeqcRM methods. + +CloseFiles(void); +CreateMapping(float list, numpy.ndarray, or tuple: grid2chem); +DumpModule(); +FindComponents(); +InitialPhreeqc2Module(int list, numpy.ndarray, or tuple: initial_conditions1); +InitialPhreeqc2Module_mix(int list, numpy.ndarray, or tuple: initial_conditions1, + int list, numpy.ndarray, or tuple initial_conditions2, + float list, numpy.ndarray, or tuple: fraction1); +InitialPhreeqcCell2Module(int n, int list, numpy.ndarray, or tuple cell_numbers); +LoadDatabase(string database); +OpenFiles(void); +OutputMessage(string str); +RunCells(void); +RunFile(Boolean workers, Boolean initial_phreeqc, Boolean utility, string chemistry_name); +RunString(Boolean workers, Boolean initial_phreeqc, Boolean utility, string input_string); +ScreenMessage(string str); +SetComponentH2O(Boolean tf); +SetConcentrations(float list, numpy.ndarray, or tuple: c); +SetCurrentSelectedOutputUserNumber(int n_user); +SetDensity(float list, numpy.ndarray, or tuple: density); +SetDumpFileName(string dump_name); +SetErrorHandlerMode(int mode); +SetErrorOn(Boolean tf); +SetFilePrefix(string prefix); +SetGasCompMoles(float list, numpy.ndarray, or tuple: gas_moles); +SetGasPhaseVolume(float list, numpy.ndarray, or tuple: gas_volume); +SetGridCellCount(int nxyz); +SetPartitionUZSolids(Boolean tf); +SetPorosity(float list, numpy.ndarray, or tuple: por); +SetPressure(float list, numpy.ndarray, or tuple: p); +SetPrintChemistryMask(int list, numpy.ndarray, or tuple: cell_mask); +SetPrintChemistryOn(Boolean workers, Boolean initial_phreeqc, Boolean utility); +SetRebalanceByCell(Boolean tf); +SetRebalanceFraction(float f); +SetRepresentativeVolume(float list, numpy.ndarray, or tuple: rv); +SetSaturation(float list, numpy.ndarray, or tuple: sat); +SetScreenOn(Boolean tf); +SetSelectedOutputOn(Boolean tf); +SetSpeciesSaveOn(Boolean save_on); +SetTemperature(float list, numpy.ndarray, or tuple: t); +SetTime(float time); +SetTimeConversion(float conv_factor); +SetTimeStep(float time_step); +SetUnitsExchange(int option); +SetUnitsGasPhase(int option); +SetUnitsKinetics(int option); +SetUnitsPPassemblage(int option); +SetUnitsSolution(int option); +SetUnitsSSassemblage(int option); +SetUnitsSurface(int option); +SpeciesConcentrations2Module(float list, numpy.ndarray, or tuple: species_conc); +StateSave(int istate); +StateApply(int istate); +StateDelete(int istate); +UseSolutionDensityVolume(Boolean tf); +WarningMessage(string warnstr); + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::InitializeYAML InitializeYAML_DOCSTRING + + +%define InitialPhreeqc2Concentrations_DOCSTRING +"Fills a vector (destination_c) with concentrations from solutions in the +InitialPhreeqc instance. The method is used to obtain concentrations for +boundary conditions. If a negative value is used for a cell in +boundary_solution1, then the highest numbered solution in the InitialPhreeqc +instance will be used for that cell. + +Args: + destination_c (DoubleVector): Vector to receive the concentrations.The + dimension of destination_c is set to ncomps times n_boundary, where + ncomps is the number of components returned from :meth:`FindComponents` + or :meth:`GetComponentCount`, and n_boundary is the dimension of the + vector boundary_solution1. + boundary_solution1(float list, numpy.ndarray, or tuple): Vector of solution + index numbers that refer to solutions in the InitialPhreeqc instance. + Size is n_boundary. + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::InitialPhreeqc2Concentrations InitialPhreeqc2Concentrations_DOCSTRING + + +%define InitialPhreeqc2Concentrations_mix_DOCSTRING +"Fills a vector (destination_c) with concentrations from solutions in the +InitialPhreeqc instance. The method is used to obtain concentrations for +boundary conditions that are mixtures of solutions. If a negative value is used +for a cell in boundary_solution1, then the highest numbered solution in the +InitialPhreeqc instance will be used for that cell. Concentrations may be a +mixture of two solutions, boundary_solution1 and boundary_solution2, with a +mixing fraction for boundary_solution1 of fraction1 and mixing fraction for +boundary_solution2 of (1 - fraction1). A negative value for boundary_solution2 +implies no mixing, and the associated value for fraction1 is ignored. + +Args: + destination_c (DoubleVector): Vector of concentrations extracted from the + InitialPhreeqc instance. The dimension of destination_c is set to ncomps + times n_boundary, where ncomps is the number of components returned from : + meth:`FindComponents` or :meth:`GetComponentCount`, and n_boundary is the + dimension of the vectors boundary_solution1, boundary_solution2, and + fraction1. + boundary_solution1 (int list, numpy.ndarray, or tuple): Vector of solution + index numbers that refer to solutions in the InitialPhreeqc instance. Size + is n_boundary. + boundary_solution2 (int list, numpy.ndarray, or tuple): Vector of solution + index numbers that that refer to solutions in the InitialPhreeqc instance + and are defined to mix with boundary_solution1. Size is n_boundary. + fraction1 (float list, numpy.ndarray, or tuple): Fraction of + boundary_solution1 that mixes with (1 - fraction1) of boundary_solution2. + Size is n_boundary. + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::InitialPhreeqc2Concentrations_mix InitialPhreeqc2Concentrations_mix_DOCSTRING + + +%define InitialPhreeqc2Module_DOCSTRING +"Transfer solutions and reactants from the InitialPhreeqc instance to the +reaction-module workers. Initial_conditions1 is used to select initial +conditions, including solutions and reactants, for each cell of the model, +without mixing. Initial_conditions1 is dimensioned 7 times nxyz, where nxyz is +the number of grid cells in the user model (:meth:`GetGridCellCount`). The +dimension of 7 refers to solutions and reactants in the following order: (0) +SOLUTIONS, (1) EQUILIBRIUM_PHASES, (2) EXCHANGE, (3) SURFACE, (4) GAS_PHASE, +(5) SOLID_SOLUTIONS, and (6) KINETICS. The definition initial_solution1[3*nxyz ++ 99] = 2, indicates that cell 99 (0 based) contains the SURFACE definition +(index 3) defined by SURFACE 2 in the InitialPhreeqc instance (created in the +InitialPhreeqc instance either by :meth:`RunFile` or :meth:`RunString`). + +Args: + initial_conditions1 (int list, numpy.ndarray, or tuple): Vector of solution + and reactant index numbers that refer to definitions in the InitialPhreeqc + instance. Size is 7 times nxyz. The order of definitions is given above. + Negative values are ignored, resulting in no definition of that entity for + that cell. + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::InitialPhreeqc2Module InitialPhreeqc2Module_DOCSTRING + + +%define InitialPhreeqc2Module_mix_DOCSTRING +"Transfer solutions and reactants from the InitialPhreeqc instance to the +reaction-module workers, possibly with mixing. In its simplest form, +initial_conditions1 is used to select initial conditions, including solutions +and reactants, for each cell of the model, without mixing. Initial_conditions1 +is dimensioned 7 times nxyz, where nxyz is the number of grid cells in the +user model (:meth:`GetGridCellCount`). The dimension of 7 refers to solutions +and reactants in the following order: (0) SOLUTIONS, (1) EQUILIBRIUM_PHASES, +(2) EXCHANGE, (3) SURFACE, (4) GAS_PHASE, (5) SOLID_SOLUTIONS, and (6) +KINETICS. The definition initial_solution1[3*nxyz + 99] = 2, indicates that +cell 99 (0 based) contains the SURFACE definition (index 3) defined by SURFACE +2 in the InitialPhreeqc instance (either by :meth:`RunFile` or +:meth:`RunString`). + +It is also possible to mix solutions and reactants to obtain the initial +conditions for cells. For mixing, initials_conditions2 contains numbers for a +second entity that mixes with the entity defined in initial_conditions1. +Fraction1 contains the mixing fraction for initial_conditions1, whereas (1 - +fraction1) is the mixing fraction for initial_conditions2. The definitions +initial_solution1[3*nxyz + 99] = 2, initial_solution2[3*nxyz + 99] = 3, +fraction1[3*nxyz + 99] = 0.25 indicates that cell 99 (0 based) contains a +mixture of 0.25 SURFACE 2 and 0.75 SURFACE 3, where the surface compositions +have been defined in the InitialPhreeqc instance. If the user number in +initial_conditions2 is negative, no mixing occurs. + +Args: + initial_conditions1 (int list, numpy.ndarray, or tuple): Vector of solution + and reactant index numbers that refer to definitions in the InitialPhreeqc + instance. Size is 7 times nxyz, where nxyz is the number of grid cells in + the user model (:meth:`GetGridCellCount`). The order of definitions is given + above. Negative values are ignored, resulting in no definition of that + entity for that cell. + initial_conditions2 (int list, numpy.ndarray, or tuple): Vector of solution + and reactant index numbers that refer to definitions in the InitialPhreeqc + instance. Nonnegative values of initial_conditions2 result in mixing with + the entities defined in initial_conditions1. Negative values result in no + mixing. Size is 7 times nxyz. The order of definitions is given above. + fraction1 (float list, numpy.ndarray, or tuple): Fraction of + initial_conditions1 that mixes with (1 - fraction1) of initial_conditions2. + Size is 7 times nxyz. The order of definitions is given above. + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::InitialPhreeqc2Module_mix InitialPhreeqc2Module_mix_DOCSTRING + + +%define InitialPhreeqc2SpeciesConcentrations_DOCSTRING +"Fills a vector destination_c with aqueous species concentrations from +solutions in the InitialPhreeqc instance. This method is intended for use with +multicomponent-diffusion transport calculations, and :meth:`SetSpeciesSaveOn` +must be set to true. The method is used to obtain aqueous species +concentrations for boundary conditions. If a negative value is used for a cell +in boundary_solution1, then the highest numbered solution in the InitialPhreeqc +instance will be used for that cell. + +Args: + destination_c (DoubleVector): Vector of aqueous concentrations extracted + from the InitialPhreeqc instance. The dimension of species_c is nspecies + times n_boundary, where nspecies is the number of aqueous species returned + from :meth:`GetSpeciesCount`, and n_boundary is the dimension of + boundary_solution1. + boundary_solution1 (int list, numpy.ndarray, or tuple): Vector of solution + index numbers that refer to solutions in the InitialPhreeqc instance. + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::InitialPhreeqc2SpeciesConcentrations InitialPhreeqc2SpeciesConcentrations_DOCSTRING + + +%define InitialPhreeqc2SpeciesConcentrations_mix_DOCSTRING +"Fills a vector destination_c with aqueous species concentrations from +solutions in the InitialPhreeqc instance. This method is intended for use with +multicomponent-diffusion transport calculations, and :meth:`SetSpeciesSaveOn` +must be set to true. The method is used to obtain aqueous species +concentrations for boundary conditions. If a negative value is used for a cell +in boundary_solution1, then the highest numbered solution in the InitialPhreeqc +instance will be used for that cell. Concentrations may be a mixture of two +solutions, boundary_solution1 and boundary_solution2, with a mixing fraction +for boundary_solution1 of fraction1 and mixing fraction for boundary_solution2 +of (1 - fraction1). A negative value for boundary_solution2 implies no mixing, +and the associated value for fraction1 is ignored. + +Args: + destination_c (DoubleVector): Vector of aqueous concentrations extracted + from the InitialPhreeqc instance. The dimension of species_c is nspecies + times n_boundary, where nspecies is the number of aqueous species returned + from :meth:`GetSpeciesCount`, and n_boundary is the dimension of + boundary_solution1. + boundary_solution1 (int list, numpy.ndarray, or tuple): Vector of solution + index numbers that refer to solutions in the InitialPhreeqc instance. + boundary_solution2 (int list, numpy.ndarray, or tuple): Vector of solution + index numbers that refer to solutions in the InitialPhreeqc instance and are + defined to mix with boundary_solution1. Size is same as boundary_solution1. + fraction1 (float list, numpy.ndarray, or tuple): Vector of fractions of + boundary_solution1 that mix with (1 - fraction1) of boundary_solution2. Size + is same as boundary_solution1. + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::InitialPhreeqc2SpeciesConcentrations_mix InitialPhreeqc2SpeciesConcentrations_mix_DOCSTRING + + +%define InitialPhreeqcCell2Module_DOCSTRING +"A cell numbered n in the InitialPhreeqc instance is selected to populate a +series of transport cells. All reactants with the number n are transferred +along with the solution. If MIX n exists, it is used for the definition of the +solution. If n is negative, n is redefined to be the largest solution or MIX +number in the InitialPhreeqc instance. All reactants for each cell in the list +cell_numbers are removed before the cell definition is copied from the +InitialPhreeqc instance to the workers. + +Args: + n (int): Number that refers to a solution or MIX and associated reactants in + the InitialPhreeqc instance. + cell_numbers (int): A vector of grid-cell numbers (user grid-cell numbering + system) that will be populated with cell n from the InitialPhreeqc instance. + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::InitialPhreeqcCell2Module InitialPhreeqcCell2Module_DOCSTRING + + +%define LoadDatabase_DOCSTRING +"Load a database for all IPhreeqc instances--workers, InitialPhreeqc, and +Utility. All definitions of the reaction module are cleared (SOLUTION_SPECIES, +PHASES, SOLUTIONs, etc.), and the database is read. + +Args: + database (string): String containing the database name. + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::LoadDatabase LoadDatabase_DOCSTRING + + +%define LogMessage_DOCSTRING +"Print a message to the log file. + +Args: + str (string): String to be printed." +%enddef +%feature("docstring") PhreeqcRM::LogMessage LogMessage_DOCSTRING + + +%define MpiAbort_DOCSTRING +"MPI only. Calls MPI_Abort, which aborts MPI, and makes the reaction module +unusable. Should be used only on encountering an unrecoverable error." +%enddef +%feature("docstring") PhreeqcRM::MpiAbort MpiAbort_DOCSTRING + + +%define MpiWorker_DOCSTRING +"MPI only. Nonroot processes (processes with :meth:`GetMpiMyself` > 0) must +call MpiWorker to be able to respond to messages from the root to accept data, +perform calculations, and (or) return data within the reaction module. +MpiWorker contains a loop that reads a message from root, performs a task, and +waits for another message from root. :meth:`SetConcentrations`, +:meth:`RunCells`, and :meth:`GetConcentrations` are examples of methods that +send a message from root to get the workers to perform a task. The workers will +respond to all methods that are designated 'workers must be in the loop of +MpiWorker' in the MPI section of the method documentation. The workers will +continue to respond to messages from root until root calls +:meth:`MpiWorkerBreak`. + +(Advanced) The list of tasks that the workers perform can be extended by using : +meth:`SetMpiWorkerCallbackC`. It is then possible to use the MPI processes to +perform other developer-defined tasks, such as transport calculations, without +exiting from the MpiWorker loop. Alternatively, root calls :meth:`MpiWorkerBreak +` to allow the workers to continue past a call to MpiWorker. The workers perform +developer-defined calculations, and then MpiWorker is called again to respond +to requests from root to perform reaction-module tasks. + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`). +MpiWorker returns a value only when :meth:`MpiWorkerBreak` is called by root." +%enddef +%feature("docstring") PhreeqcRM::MpiWorker MpiWorker_DOCSTRING + + +%define MpiWorkerBreak_DOCSTRING +"MPI only. This method is called by root to force nonroot processes (processes +with :meth:`GetMpiMyself` > 0) to return from a call to :meth:`MpiWorker`. +:meth:`MpiWorker` contains a loop that reads a message from root, performs a +task, and waits for another message from root. The workers respond to all +methods that are designated 'workers must be in the loop of MpiWorker' in the +MPI section of the method documentation. The workers will continue to respond +to messages from root until root calls MpiWorkerBreak. + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::MpiWorkerBreak MpiWorkerBreak_DOCSTRING + + +%define OpenFiles_DOCSTRING +"Opens the output and log files. Files are named prefix.chem.txt and +prefix.log.txt based on the prefix defined by :meth:`SetFilePrefix`. + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::OpenFiles OpenFiles_DOCSTRING + + +%define OutputMessage_DOCSTRING +"Print a message to the output file. + +Args: + str (string) String to be printed." +%enddef +%feature("docstring") PhreeqcRM::OutputMessage OutputMessage_DOCSTRING + + +%define RunCells_DOCSTRING +"Runs a reaction step for all reaction cells in the reaction module. Normally, +tranport concentrations are transferred to the reaction cells +(:meth:`SetConcentrations`) before reaction calculations are run. The length of +time over which kinetic reactions are integrated is set by :meth:`SetTimeStep`. +Other properties that may need to be updated as a result of the transport +calculations include porosity (:meth:`SetPorosity`), saturation +(:meth:`SetSaturation`), temperature (:meth:`SetTemperature`), and pressure +(:meth:`SetPressure`). + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::RunCells RunCells_DOCSTRING + + +%define ReturnHandler_DOCSTRING +"Process an IRM_RESULT return code. If the return code is nonnegative, no +action is taken. If the return code is negative, the return code is decoded and +printed as an error message along with the second argument (std::string). On an +error, the method will return the same return code, throw an exception, or exit +the program depending on the setting for :meth:`SetErrorHandlerMode`. + +Args: + result (IRM_RESULT): Return code to be processed. + e_string (string): Error message to be printed in case of an error. + +Returns: + IRM_RESULT: The first argument to the method is returned." +%enddef +%feature("docstring") PhreeqcRM::ReturnHandler ReturnHandler_DOCSTRING + + +%define RunFile_DOCSTRING +"Run a PHREEQC input file. The first three arguments determine which IPhreeqc +instances will run the file--the workers, the InitialPhreeqc instance, and (or) +the Utility instance. Input files that modify the thermodynamic database should +be run by all three sets of instances. Files with SELECTED_OUTPUT definitions +that will be used during the time-stepping loop need to be run by the workers. +Files that contain initial conditions or boundary conditions should be run by +the InitialPhreeqc instance. + +Args: + workers (Boolean): True, the workers will run the file; False, the workers + will not run the file. + initial_phreeqc (Boolean): True, the InitialPhreeqc instance will run the + file; False, the InitialPhreeqc will not run the file. + utility (Boolean): True, the Utility instance will run the file; False, the + Utility instance will not run the file. + chemistry_name (string): Name of the file to run. + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::RunFile RunFile_DOCSTRING + + +%define RunString_DOCSTRING +"Run a PHREEQC input string. The first three arguments determine which IPhreeqc +instances will run the string--the workers, the InitialPhreeqc instance, and +(or) the Utility instance. Input strings that modify the thermodynamic database +should be run by all three sets of instances. Strings with SELECTED_OUTPUT +definitions that will be used during the time-stepping loop need to be run by +the workers. Strings that contain initial conditions or boundary conditions +should be run by the InitialPhreeqc instance. + +Args: + workers (Boolean): True, the workers will run the string; False, the workers + will not run the string. + initial_phreeqc (Boolean): True, the InitialPhreeqc instance will run the + string; False, the InitialPhreeqc will not run the string. + utility (Boolean): True, the Utility instance will run the string; False, + the Utility instance will not run the string. + input_string (string): String containing PHREEQC input. + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::RunString RunString_DOCSTRING + + +%define ScreenMessage_DOCSTRING +"Print message to the screen. + +Args: + str (string): String to be printed." +%enddef +%feature("docstring") PhreeqcRM::ScreenMessage ScreenMessage_DOCSTRING + + +%define SetComponentH2O_DOCSTRING +"Select whether to include H2O in the component list. The concentrations of H +and O must be known accurately (8 to 10 significant digits) for the numerical +method of PHREEQC to produce accurate pH and pe values. Because most of the H +and O are in the water species, it may be more robust (require less accuracy in +transport) to transport the excess H and O (the H and O not in water) and +water. The default setting (true) is to include water, excess H, and excess O +as components. A setting of false will include total H and total O as +components. SetComponentH2O must be called before :meth:`FindComponents`. + +Args: + tf (Boolean): True (default), excess H, excess O, and water are included in + the component list; False, total H and O are included in the component list. + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::SetComponentH2O SetComponentH2O_DOCSTRING + + +%define SetConcentrations_DOCSTRING +"Use the vector of concentrations (c) to set the moles of components in each +reaction cell. The volume of water in a cell is the product of porosity +(:meth:`SetPorosity`), saturation (:meth:`SetSaturation`), and reference volume +(:meth:`SetRepresentativeVolume`). The moles of each component are determined +by the volume of water and per liter concentrations. If concentration units +(:meth:`SetUnitsSolution`) are mass fraction, the density (as specified by +:meth:`SetDensity`) is used to convert from mass fraction to per mass per liter. + +Args: + c (double list, numpy.ndarray, or tuple): Component concentrations. Size of + vector is ncomps times nxyz, where ncomps is the number of components as + determined by :meth:`FindComponents` or :meth:`GetComponentCount` and nxyz + is the number of grid cells in the user model (:meth:`GetGridCellCount`). + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::SetConcentrations SetConcentrations_DOCSTRING + + +%define SetCurrentSelectedOutputUserNumber_DOCSTRING +"Select the current selected output by user number. The user may define +multiple SELECTED_OUTPUT data blocks for the workers. A user number is +specified for each data block. The value of the argument n_user selects which +of the SELECTED_OUTPUT definitions will be used for selected-output operations. + +Args: + n_user (int): User number of the SELECTED_OUTPUT data block that is to be used. + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::SetCurrentSelectedOutputUserNumber SetCurrentSelectedOutputUserNumber_DOCSTRING + + +%define SetDensity_DOCSTRING +"Set the density for each reaction cell. These density values are used when +converting from transported mass-fraction concentrations +(:meth:`SetUnitsSolution`) to produce per liter concentrations during a call to +:meth:`SetConcentrations`. They are also used when converting from +reaction-cell concentrations to transport concentrations +(:meth:`GetConcentrations`), if :meth:`UseSolutionDensityVolume` is set to +false. + +Args: + density (float list, numpy.ndarray, or tuple): Densities. Size of vector is + nxyz, where nxyz is the number of grid cells in the user model (:meth:` + GetGridCellCount`). + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::SetDensity SetDensity_DOCSTRING + + +%define SetDumpFileName_DOCSTRING +"Set the name of the dump file. It is the name used by :meth:`DumpModule`. + +Args: + dump_name (string): Name of dump file. + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::SetDumpFileName SetDumpFileName_DOCSTRING + + +%define SetErrorHandlerMode_DOCSTRING +"Set the action to be taken when the reaction module encounters an error. +Options are 0, return to calling program with an error return code (default); +1, throw an exception, in C++, the exception can be caught, for C and Fortran, +the program will exit; or 2, attempt to exit gracefully. + +Args: + mode (int): Error handling mode: 0, 1, or 2. + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::SetErrorHandlerMode SetErrorHandlerMode_DOCSTRING + + +%define SetErrorOn_DOCSTRING +"Set the property that controls whether error messages are generated and +displayed. Messages include PHREEQC 'ERROR' messages, and any messages written +with :meth:`ErrorMessage`. + +Args: + tf (Boolean): True, enable error messages; False, disable error messages. + Default is true. + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::SetErrorOn SetErrorOn_DOCSTRING + + +%define SetFilePrefix_DOCSTRING +"Set the prefix for the output (prefix.chem.txt) and log (prefix.log.txt) +files. These files are opened by :meth:`OpenFiles`. + +Args: + prefix (string): Prefix used when opening the output and log files. + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::SetFilePrefix SetFilePrefix_DOCSTRING + + +%define SetGasCompMoles_DOCSTRING +"Transfer moles of gas components from the vector given in the argument list +(gas_moles) to each reaction cell. + +Args: + gas_moles (float list, numpy.ndarray, or tuple): Moles of gas components. + Dimension of the vector is set to ngas_comps times nxyz, where, ngas_comps + is the result of :meth:`GetGasComponentsCount`, and nxyz is the number of + user grid cells (:meth:`GetGridCellCount`). If the number of moles is set to + a negative number, the gas component will not be defined for the GAS_PHASE + of the reaction cell. + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::SetGasCompMoles SetGasCompMoles_DOCSTRING + + +%define SetGasPhaseVolume_DOCSTRING +"Transfer volumes of gas phases from the vector given in the argument list +(gas_volume) to each reaction cell. The gas-phase volume affects the +gas-component pressures calculated for fixed-volume gas phases. If a gas-phase +volume is defined with this methood for a GAS_PHASE in a cell, the gas phase is +forced to be a fixed-volume gas phase. + +Args: + gas_volume (float list, numpy.ndarray, or tuple): Volumes for each gas phase. + Dimension of the vector is nxyz, where nxyz is the number of user grid cells (: + meth:`GetGridCellCount`). If the volume is set to a negative number for a cell, + the gas-phase volume for that cell is not changed. + + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::SetGasPhaseVolume SetGasPhaseVolume_DOCSTRING + + +%define SetMpiWorkerCallbackC_DOCSTRING +"MPI and C/C++ only. Defines a callback function that allows additional tasks +to be done by the workers. The method :meth:`MpiWorker` contains a loop, where +the workers receive a message (an integer), run a function corresponding to +that integer, and then wait for another message. SetMpiWorkerCallbackC allows C +or C++ developers to add another function that responds to additional integer +messages by calling developer-defined functions corresponding to those +integers. :meth:`MpiWorker` calls the callback function when the message number +is not one of the PhreeqcRM message numbers. Messages are unique integer +numbers. PhreeqcRM uses integers in a range beginning at 0. It is suggested +that developers use message numbers starting at 1000 or higher for their tasks. +The callback function calls a developer-defined function specified by the +message number and then returns to :meth:`MpiWorker` to wait for another +message. + +In C and C++, an additional pointer can be supplied to find the data necessary +to do the task. A void pointer may be set with :meth:`SetMpiWorkerCallbackCookie`. +This pointer is passed to the callback function through a void pointer +argument in addition to the integer message argument. The pointer may be to a +struct or class instance that provides a number of additional pointers to data. +:meth:`SetMpiWorkerCallbackCookie` must be called by each worker before :meth:` +MpiWorker` is called. + +The motivation for this method is to allow the workers to perform other tasks, +for instance, parallel transport calculations, within the structure of +:meth:`MpiWorker`. The callback function can be used to allow the workers to +receive data, perform transport calculations, and (or) send results, without +leaving the loop of :meth:`MpiWorker`. Alternatively, it is possible for the +workers to return from :meth:`MpiWorker` by a call to :meth:`MpiWorkerBreak` by +root. The workers could then call subroutines to receive data, calculate +transport, and send data, and then resume processing PhreeqcRM messages from +root with another call to :meth:`MpiWorker`. + +Args: + fcn (function pointer): A function that returns an integer and has an + integer argument and a void * argument. + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::SetMpiWorkerCallbackC SetMpiWorkerCallbackC_DOCSTRING + + +%define SetMpiWorkerCallbackCookie_DOCSTRING +"MPI and C/C++ only. Defines a void pointer that can be used by C and C++ +functions called from the callback function (:meth:`SetMpiWorkerCallbackC`) to +locate data for a task. The C callback function that is registered with +:meth:`SetMpiWorkerCallbackC` has two arguments, an integer message to identify +a task, and a void pointer. SetMpiWorkerCallbackCookie sets the value of the +void pointer that is passed to the callback function. The void pointer may be a +pointer to a struct of class instance that contains additonal pointers to data. + +Args: + cookie Void pointer that can be used by subroutines called from + the callback function to locate data needed to perform a task. + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::SetMpiWorkerCallbackCookie SetMpiWorkerCallbackCookie_DOCSTRING + + +%define SetNthSelectedOutput_DOCSTRING +"Specify the current selected output by sequence number. The user may define +multiple SELECTED_OUTPUT data blocks for the workers. A user number is +specified for each data block, and the blocks are stored in user-number order. +The value of the argument n selects the sequence number of the SELECTED_OUTPUT +definition that will be used for selected-output operations. + +Args: + n (int): Sequence number of the SELECTED_OUTPUT data block that is to be + used. + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::SetNthSelectedOutput SetNthSelectedOutput_DOCSTRING + + +%define SetPartitionUZSolids_DOCSTRING +"Sets the property for partitioning solids between the saturated and +unsaturated parts of a partially saturated cell. + +The option is intended to be used by saturated-only flow codes that allow a +variable water table. The value has meaning only when saturations less than 1.0 +are encountered. The partially saturated cells may have a small water-to-rock +ratio that causes reactions to proceed differently relative to fully saturated +cells. By setting SetPartitionUZSolids to true, the amounts of solids and gases + are partioned according to the saturation. If a cell has a saturation of 0.5, +then the water interacts with only half of the solids and gases; the other half +is unreactive until the water table rises. As the saturation in a cell varies, +solids and gases are transferred between the saturated and unsaturated ( +unreactive) reservoirs of the cell. Unsaturated-zone flow and transport codes +will probably use the default (false), which assumes all gases and solids are +reactive regardless of saturation. + +Args: + tf (Boolean): True, the fraction of solids and gases available for reaction + is equal to the saturation; False (default), all solids and gases are + reactive regardless of saturation. + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::SetPartitionUZSolids SetPartitionUZSolids_DOCSTRING + + +%define SetPorosity_DOCSTRING +"Set the porosity for each reaction cell. The volume of water in a reaction +cell is the product of porosity, saturation (:meth:`SetSaturation`), and +representative volume (:meth:`SetRepresentativeVolume`). + +Args: + por (float list, numpy.ndarray, or tuple): Porosities, unitless. Default is + 0.1. Size of vector is nxyz, where nxyz is the number of grid cells in the + user model (:meth:`GetGridCellCount`). + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::SetPorosity SetPorosity_DOCSTRING + + +%define SetPressure_DOCSTRING +"Set the pressure for each reaction cell. Pressure effects are considered only +in three of the databases distributed with PhreeqcRM: phreeqc.dat, Amm.dat, and +pitzer.dat. + +Args: + p (float list, numpy.ndarray, or tuple): Pressures, in atm. Size of vector + is nxyz, where nxyz is the number of grid cells in the user model (:meth:` + GetGridCellCount`). + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::SetPressure SetPressure_DOCSTRING + + +%define SetPrintChemistryMask_DOCSTRING +"Enable or disable detailed output for each reaction cell. Printing for a +reaction cell will occur only when the printing is enabled with +:meth:`SetPrintChemistryOn` and the cell_mask value is 1. + +Args: + cell_mask (Intfloat list, numpy.ndarray, or tuple): Vector of integers. + Size of vector is nxyz, where nxyz is the number of grid cells in + the user model (:meth:`GetGridCellCount`). A value of 0 will disable + printing detailed output for the cell; a value of 1 will enable + printing detailed output for a cell. + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::SetPrintChemistryMask SetPrintChemistryMask_DOCSTRING + + +%define SetPrintChemistryOn_DOCSTRING +"Set property that enables or disables printing detailed output from reaction +calculations to the output file for a set of cells defined by +:meth:`SetPrintChemistryMask`. The detailed output prints all of the output +typical of a PHREEQC reaction calculation, which includes solution descriptions +and the compositions of all other reactants. The output can be several hundred +lines per cell, which can lead to a very large output file (prefix.chem.txt, +:meth:`OpenFiles`). For the worker instances, the output can be limited to a +set of cells (:meth:`SetPrintChemistryMask`) and, in general, the amount of +information printed can be limited by use of options in the PRINT data block of +PHREEQC (applied by using :meth:`RunFile` or :meth:`RunString`). Printing the +detailed output for the workers is generally used only for debugging, and +PhreeqcRM will run significantly faster when printing detailed output for the +workers is disabled. + +Args: + workers (Boolean): True, enable detailed printing in the worker instances; + False, disable detailed printing in the worker instances. + initial_phreeqc (Boolean): True, enable detailed printing in the + InitialPhreeqc instance; False, disable detailed printing in the + InitialPhreeqc instance. + utility (Boolean): True, enable detailed printing in the Utility instance; + False, disable detailed printing in the Utility instance. + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::SetPrintChemistryOn SetPrintChemistryOn_DOCSTRING + + +%define SetRebalanceByCell_DOCSTRING +"Set the load-balancing algorithm. PhreeqcRM attempts to rebalance the load of +each thread or process such that each thread or process takes the same amount +of time to run its part of a :meth:`RunCells` calculation. Two algorithms are +available; one uses individual times for each cell and accounts for cells that +were not run because saturation was zero (default), and the other assigns an +average time to all cells. The methods are similar, but limited testing +indicates the default method performs better. + +Args: + tf (Boolean): True, indicates individual cell times are used in rebalancing +(default); False, indicates average times are used in rebalancing. + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::SetRebalanceByCell SetRebalanceByCell_DOCSTRING + + +%define SetRebalanceFraction_DOCSTRING +"Sets the fraction of cells that are transferred among threads or processes +when rebalancing. PhreeqcRM attempts to rebalance the load of each thread or +process such that each thread or process takes the same amount of time to run +its part of a :meth:`RunCells` calculation. The rebalancing transfers cell +calculations among threads or processes to try to achieve an optimum balance. +SetRebalanceFraction adjusts the calculated optimum number of cell transfers by +a fraction from 0 to 1.0 to determine the actual number of cell transfers. A +value of zero eliminates load rebalancing. A value less than 1.0 is suggested +to slow the approach to the optimum cell distribution and avoid possible +oscillations when too many cells are transferred at one iteration, requiring +reverse transfers at the next iteration. Default is 0.5. + +Args: + f (float): Fraction from 0.0 to 1.0. + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::SetRebalanceFraction SetRebalanceFraction_DOCSTRING + + +%define SetRepresentativeVolume_DOCSTRING +"Set the representative volume of each reaction cell. By default the +representative volume of each reaction cell is 1 liter. The volume of water in +a reaction cell is determined by the product of the representative volume, the +porosity (:meth:`SetPorosity`), and the saturation (:meth:`SetSaturation`). The +numerical method of PHREEQC is more robust if the water volume for a reaction +cell is within a couple orders of magnitude of 1.0. Small water volumes caused +by small porosities and (or) small saturations (and (or) small representative +volumes) may cause non-convergence of the numerical method. In these cases, a +larger representative volume may help. Note that increasing the representative +volume also increases the number of moles of the reactants in the reaction cell +(minerals, surfaces, exchangers, and others), which are defined as moles per +representative volume. + +Args: + rv (float list, numpy.ndarray, or tuple): Representative volumes, in liters. + Default is 1.0 liter. Size of array is nxyz, where nxyz is the number of + grid cells in the user model (:meth:`GetGridCellCount`). + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::SetRepresentativeVolume SetRepresentativeVolume_DOCSTRING + + +%define SetSaturation_DOCSTRING +"Set the saturation of each reaction cell. Saturation is a fraction ranging +from 0 to 1. The volume of water in a cell is the product of porosity +(:meth:`SetPorosity`), saturation (SetSaturation), and representative volume +(:meth:`SetRepresentativeVolume`). As a result of a reaction calculation, +solution properties (density and volume) will change; the databases +phreeqc.dat, Amm.dat, and pitzer.dat have the molar volume data to calculate +these changes. The methods :meth:`GetDensity`, :meth:`GetSolutionVolume`, and +:meth:`GetSaturation` can be used to account for these changes in the +succeeding transport calculation. SetRepresentativeVolume should be called +before initial conditions are defined for the reaction cells. + +Args: + sat (float list, numpy.ndarray, or tuple): Saturations, unitless. Default + 1.0. Size of vector is nxyz, where nxyz is the number of grid cells in the + user model (:meth:`GetGridCellCount`). + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::SetSaturation SetSaturation_DOCSTRING + + +%define SetScreenOn_DOCSTRING +"Set the property that controls whether messages are written to the screen. +Messages include information about rebalancing during :meth:`RunCells`, and +any messages written with :meth:`ScreenMessage`. + + +Args: + tf (Boolean): True, enable screen messages; False, disable screen messages. + Default is true. + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::SetScreenOn SetScreenOn_DOCSTRING + + +%define SetSelectedOutputOn_DOCSTRING +"Set the property that controls whether selected-output results are available +to be retrieved with :meth:`GetSelectedOutput`. True indicates that +selected-output results will be accumulated during :meth:`RunCells` and can be +retrieved with :meth:`GetSelectedOutput`; False indicates that selected-output +results will not be accumulated during :meth:`RunCells`. + +Args: + tf (Boolean): True, enable selected output; False, disable selected output. + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::SetSelectedOutputOn SetSelectedOutputOn_DOCSTRING + + +%define SetSpeciesSaveOn_DOCSTRING +"Sets the value of the species-save property. This method enables or disables +use of PhreeqcRM with multicomponent-diffusion transport calculations. By +default, concentrations of aqueous species are not saved. Setting the +species-save property to true allows aqueous species concentrations to be +retrieved with :meth:`GetSpeciesConcentrations`, and solution compositions to +be set with :meth:`SpeciesConcentrations2Module`. SetSpeciesSaveOn must be +called before calls to :meth:`FindComponents`. + +Args: + save_on (Boolean): True indicates species concentrations are saved; + False indicates species concentrations are not saved. + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::SetSpeciesSaveOn SetSpeciesSaveOn_DOCSTRING + + +%define SetTemperature_DOCSTRING +"Set the temperature for each reaction cell. If SetTemperature is not called, +worker solutions will have temperatures as defined by initial conditions +(:meth:`InitialPhreeqc2Module` and :meth:`InitialPhreeqcCell2Module`). + +Args: + t (float list, numpy.ndarray, or tuple): Temperatures, in degrees C. Size of + vector is nxyz, where nxyz is the number of grid cells in the user model + (: meth:`GetGridCellCount`). + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::SetTemperature SetTemperature_DOCSTRING + + +%define SetTime_DOCSTRING +"Set current simulation time for the reaction module. + +Args: + time (float): Current simulation time, in seconds. + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::SetTime SetTime_DOCSTRING + + +%define SetTimeConversion_DOCSTRING +"Set a factor to convert from seconds to user time units. Factor times seconds +produces user time units. + +Args: + conv_factor (float): Factor to convert seconds to user time units. + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::SetTimeConversion SetTimeConversion_DOCSTRING + + +%define SetTimeStep_DOCSTRING +"Set current time step for the reaction module. This is the length +of time over which kinetic reactions are integrated. + +Args: + time_step (float): Time step, in seconds. + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::SetTimeStep SetTimeStep_DOCSTRING + + +%define SetUnitsExchange_DOCSTRING +"Sets input units for exchangers. In PHREEQC input, exchangers are defined by +moles of exchange sites (Mp). SetUnitsExchange specifies how the number of +moles of exchange sites in a reaction cell (Mc) +is calculated from the input value (Mp). + +Options are 0, Mp is mol/L of RV (default), Mc = Mp*RV, where RV is the +representative volume (:meth:`SetRepresentativeVolume`); 1, Mp is mol/L of +water in the RV, Mc = Mp*P*RV, where P is porosity (:meth:`SetPorosity`); or +2, Mp is mol/L of rock in the RV, Mc = Mp*(1-P)*RV. + +If a single EXCHANGE definition is used for cells with different initial +porosity, the three options scale quite differently. For option 0, the number of +moles of exchangers will be the same regardless of porosity. For option 1, the +number of moles of exchangers will be vary directly with porosity and inversely +with rock volume. For option 2, the number of moles of exchangers will vary +directly with rock volume and inversely with porosity. + +Args: + option (int): Units option for exchangers: 0, 1, or 2. + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::SetUnitsExchange SetUnitsExchange_DOCSTRING + + +%define SetUnitsGasPhase_DOCSTRING +"Set input units for gas phases. In PHREEQC input, gas phases are defined by +moles of component gases (Mp). SetUnitsGasPhase specifies how the number of +moles of component gases in a reaction cell (Mc) is calculated from the input +value (Mp). + +Options are 0, Mp is mol/L of RV (default), Mc = Mp*RV, where RV is the +representative volume (:meth:`SetRepresentativeVolume`); 1, Mp is mol/L of water +in the RV, Mc = Mp*P*RV, where P is porosity (:meth:`SetPorosity`); or 2, Mp is +mol/L of rock in the RV, Mc = Mp*(1-P)*RV. + +If a single GAS_PHASE definition is used for cells with different initial +porosity, the three options scale quite differently. For option 0, the number of +moles of a gas component will be the same regardless of porosity. For option 1, +the number of moles of a gas component will be vary directly with porosity and +inversely with rock volume. For option 2, the number of moles of a gas component +will vary directly with rock volume and inversely with porosity. + +Args: + option (int): Units option for gas phases: 0, 1, or 2. + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::SetUnitsGasPhase SetUnitsGasPhase_DOCSTRING + + +%define SetUnitsKinetics_DOCSTRING +"Set input units for kinetic reactants. + +In PHREEQC input, kinetics are defined by moles of kinetic reactants (Mp). +SetUnitsKinetics specifies how the number of moles of kinetic reactants in a +reaction cell (Mc) is calculated from the input value (Mp). + +Options are 0, Mp is mol/L of RV (default), Mc = Mp*RV, where RV is the +representative volume (:meth:`SetRepresentativeVolume`); 1, Mp is mol/L of water +in the RV, Mc = Mp*P*RV, where P is porosity (:meth:`SetPorosity`); or 2, Mp is +mol/L of rock in the RV, Mc = Mp*(1-P)*RV. + +If a single KINETICS definition is used for cells with different initial +porosity, the three options scale quite differently. For option 0, the number of +moles of kinetic reactants will be the same regardless of porosity. For option +1, the number of moles of kinetic reactants will be vary directly with porosity +and inversely with rock volume. For option 2, the number of moles of kinetic +reactants will vary directly with rock volume and inversely with porosity. + +Note that the volume of water in a cell in the reaction module is equal to the +product of porosity (:meth:`SetPorosity`), the saturation (:meth:`SetSaturation`), +and representative volume (:meth: `SetRepresentativeVolume`), which is +usually less than 1 liter. It is important to write the RATES definitions for +homogeneous (aqueous) kinetic reactions to account for the current volume of +water, often by calculating the rate of reaction per liter of water and +multiplying by the volume of water (Basic function SOLN_VOL). + +Rates that depend on surface area of solids, are not dependent on the volume of +water. However, it is important to get the correct surface area for the kinetic +reaction. To scale the surface area with the number of moles, the specific area +(m^2 per mole of reactant) can be defined as a parameter (KINETICS; -parm), +which is multiplied by the number of moles of reactant (Basic function M) in +RATES to obtain the surface area. + +Args: + option (int): Units option for kinetic reactants: 0, 1, or 2. + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::SetUnitsKinetics SetUnitsKinetics_DOCSTRING + + +%define SetUnitsPPassemblage_DOCSTRING +"Set input units for pure phase assemblages (equilibrium phases). In PHREEQC +input, equilibrium phases are defined by moles of each phase (Mp). +SetUnitsPPassemblage specifies how the number of moles of phases in a reaction +cell (Mc) is calculated from the input value (Mp). + +Options are 0, Mp is mol/L of RV (default), Mc = Mp*RV, where RV is the +representative volume (:meth:`SetRepresentativeVolume`); 1, Mp is mol/L of water +in the RV, Mc = Mp*P*RV, where P is porosity (:meth:`SetPorosity`); or 2, Mp is +mol/L of rock in the RV, Mc = Mp*(1-P)*RV. + +If a single EQUILIBRIUM_PHASES definition is used for cells with different +initial porosity, the three options scale quite differently. For option 0, the +number of moles of a mineral will be the same regardless of porosity. For option +1, the number of moles of a mineral will be vary directly with porosity and +inversely with rock volume. For option 2, the number of moles of a mineral will +vary directly with rock volume and inversely with porosity. + +Args: + option (int): Units option for equilibrium phases: 0, 1, or 2. + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::SetUnitsPPassemblage SetUnitsPPassemblage_DOCSTRING + + +%define SetUnitsSolution_DOCSTRING +"Solution concentration units used by the transport model. Options are 1, mg/L; +2 mol/L; or 3, mass fraction, kg/kgs. PHREEQC defines solutions by the number +of moles of each element in the solution. + +To convert from mg/L to moles of element in the representative volume of a +reaction cell, mg/L is converted to mol/L and multiplied by the solution volume, + which is the product of porosity (:meth:`SetPorosity`), saturation (:meth:` +SetSaturation`), and representative volume (:meth:`SetRepresentativeVolume`). To + convert from mol/L to moles of element in the representative volume of a +reaction cell, mol/L is multiplied by the solution volume. To convert from mass +fraction to moles of element in the representative volume of a reaction cell, kg +/kgs is converted to mol/kgs, multiplied by density (:meth:`SetDensity`) and +multiplied by the solution volume. + +To convert from moles of element in the representative volume of a reaction cell +to mg/L, the number of moles of an element is divided by the solution volume +resulting in mol/L, and then converted to mg/L. To convert from moles of element +in a cell to mol/L, the number of moles of an element is divided by the +solution volume resulting in mol/L. To convert from moles of element in a cell +to mass fraction, the number of moles of an element is converted to kg and +divided by the total mass of the solution. Two options are available for the +volume and mass of solution that are used in converting to transport +concentrations: (1) the volume and mass of solution are calculated by PHREEQC, +or (2) the volume of solution is the product of porosity (:meth:`SetPorosity`), +saturation (:meth:`SetSaturation`), and representative volume +(:meth:`SetRepresentativeVolume`), and the mass of solution is volume times +density as defined by :meth:`SetDensity`. Which option is used is determined by +:meth:`UseSolutionDensityVolume`. + +Args: + option (int): Units option for solutions: 1, 2, or 3, default is 1, mg/L. + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::SetUnitsSolution SetUnitsSolution_DOCSTRING + + +%define SetUnitsSSassemblage_DOCSTRING +"Set input units for solid-solution assemblages. In PHREEQC, solid solutions +are defined by moles of each component (Mp). SetUnitsSSassemblage specifies how +the number of moles of solid-solution components in a reaction cell (Mc) is +calculated from the input value (Mp). + +Options are 0, Mp is mol/L of RV (default), Mc = Mp*RV, where RV is the +representative volume (:meth:`SetRepresentativeVolume`); 1, Mp is mol/L of water +in the RV, Mc = Mp*P*RV, where P is porosity (:meth:`SetPorosity`); or 2, Mp is +mol/L of rock in the RV, Mc = Mp*(1-P)*RV. + +If a single SOLID_SOLUTION definition is used for cells with different initial +porosity, the three options scale quite differently. For option 0, the number of +moles of a solid-solution component will be the same regardless of porosity. +For option 1, the number of moles of a solid-solution component will be vary +directly with porosity and inversely with rock volume. For option 2, the number +of moles of a solid-solution component will vary directly with rock volume and +inversely with porosity. + +Args: + option (int): Units option for solid solutions: 0, 1, or 2. + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::SetUnitsSSassemblage SetUnitsSSassemblage_DOCSTRING + + +%define SetUnitsSurface_DOCSTRING +"Set input units for surfaces. In PHREEQC input, surfaces are defined by moles +of surface sites (Mp). SetUnitsSurface specifies how the number of moles of +surface sites in a reaction cell (Mc) is calculated from the input value (Mp). + +Options are 0, Mp is mol/L of RV (default), Mc = Mp*RV, where RV is the +representative volume (:meth:`SetRepresentativeVolume`); 1, Mp is mol/L of water +in the RV, Mc = Mp*P*RV, where P is porosity (:meth:`SetPorosity`); or 2, Mp is +mol/L of rock in the RV, Mc = Mp*(1-P)*RV. + +If a single SURFACE definition is used for cells with different initial porosity, +the three options scale quite differently. For option 0, the number of moles +of surface sites will be the same regardless of porosity. For option 1, the +number of moles of surface sites will be vary directly with porosity and +inversely with rock volume. For option 2, the number of moles of surface sites +will vary directly with rock volume and inversely with porosity. + +Args: + option (int): Units option for surfaces: 0, 1, or 2. + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::SetUnitsSurface SetUnitsSurface_DOCSTRING + + +%define SpeciesConcentrations2Module_DOCSTRING +"Set solution concentrations in the reaction cells based on the vector of +aqueous species concentrations (species_conc). This method is intended for use +with multicomponent-diffusion transport calculations, and +:meth:`SetSpeciesSaveOn` must be set to true. The list of aqueous species is +determined by :meth:`FindComponents` and includes all aqueous species that can +be made from the set of components. The method determines the total +concentration of a component by summing the molarities of the individual +species times the stoichiometric coefficient of the element in each species. +Solution compositions in the reaction cells are updated with these component +concentrations. + +Args: + species_conc (float list, numpy.ndarray, or tuple): Aqueous species + concentrations. Dimension of the array is nspecies times nxyz, where + nspecies is the number of aqueous species (:meth:`GetSpeciesCount`), and + nxyz is the number of user grid cells (:meth:`GetGridCellCount`). + Concentrations are moles per liter. + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::SpeciesConcentrations2Module SpeciesConcentrations2Module_DOCSTRING + + +%define StateSave_DOCSTRING +"Save the state of the chemistry in all model cells, including SOLUTIONs, +EQUILIBRIUM_PHASES, EXCHANGEs, GAS_PHASEs, KINETICS, SOLID_SOLUTIONs, and +SURFACEs. Although not generally used, MIXes, REACTIONs, REACTION_PRESSUREs, +and REACTION_TEMPERATUREs will be saved for each cell, if they have been +defined in the worker IPhreeqc instances. The distribution of cells among the +workers and the chemistry of fully or partially unsaturated cells are also +saved. The state is saved in memory; use :meth:`DumpModule` to save the state +to file. PhreeqcRM can be reset to this state by using :meth:`StateApply`. A +state is identified by an integer, and multiple states can be saved. + +Args: + istate (int): Integer identifying the state that is saved. + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::StateSave StateSave_DOCSTRING + + +%define StateApply_DOCSTRING +"Reset the state of the module to a state previously saved with +:meth:`StateSave`. The chemistry of all model cells are reset, including +SOLUTIONs, EQUILIBRIUM_PHASES, EXCHANGEs, GAS_PHASEs, KINETICS, +SOLID_SOLUTIONs, and SURFACEs. MIXes, REACTIONs, REACTION_PRESSUREs, and +REACTION_TEMPERATUREs will be reset for each cell, if they were defined in the +worker IPhreeqc instances at the time the state was saved. The distribution of +cells among the workers and the chemistry of fully or partially unsaturated +cells are also reset to the saved state. The state to be applied is identified +by an integer. + +Args: + istate (int): Integer identifying the state that is to be applied. + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::StateApply StateApply_DOCSTRING + + +%define StateDelete_DOCSTRING +"Delete a state previously saved with :meth:`StateSave`. + +Args: + istate (int): Integer identifying the state that is to be deleted. + +Returns: + IRM_RESULT: 0 is success, negative is failure (See :meth:`DecodeError`)." +%enddef +%feature("docstring") PhreeqcRM::StateDelete StateDelete_DOCSTRING + + +%define UseSolutionDensityVolume_DOCSTRING +"Determines the volume and density to use when converting from the +reaction-cell concentrations to transport concentrations +(:meth:`GetConcentrations`). Two options are available to convert concentration +units: (1) the density and solution volume calculated by PHREEQC are used, or +(2) the specified density (:meth:`SetDensity`) and solution volume are +determined by the product of saturation (:meth:`SetSaturation`), porosity +(:meth:`SetPorosity`), and representative volume +(:meth:`SetRepresentativeVolume`). Transport models that consider +density-dependent flow will probably use the PHREEQC-calculated density and +solution volume (default), whereas transport models that assume +constant-density flow will probably use specified values of density and +solution volume. Only the following databases distributed with PhreeqcRM have +molar-volume information needed to accurately calculate density and solution +volume: phreeqc.dat, Amm.dat, and pitzer.dat. Density is only used when +converting to or from transport units of mass fraction. + +Args: + tf (Boolean): True indicates that the solution density and volume as + calculated by PHREEQC will be used to calculate concentrations. False + indicates that the solution density set by :meth:`SetDensity` and the volume + determined by the product of :meth:`SetSaturation`, :meth:`SetPorosity`, + and :meth:`SetRepresentativeVolume`, will be used to calculate + concentrations retrieved by :meth:`GetConcentrations`." +%enddef +%feature("docstring") PhreeqcRM::UseSolutionDensityVolume UseSolutionDensityVolume_DOCSTRING + + +%define WarningMessage_DOCSTRING +"Print a warning message to the screen and the log file. + +Args: + warnstr (string): String to be printed." +%enddef +%feature("docstring") PhreeqcRM::WarningMessage WarningMessage_DOCSTRING + + +%define BMI_GetComponentName_DOCSTRING +"Basic Model Interface method that returns the component name--PhreeqcRM. The +BMI interface to PhreeqcRM is only partial, and provides only the most basic +functions. The native PhreeqcRM methods (those without the the BMI_ prefix) +provide a complete interface, and it is expected that the native methods will +be used in preference to the BMI_ methods. + +Returns: + string: The string 'PhreeqcRM'." +%enddef +%feature("docstring") PhreeqcRM::BMI_GetComponentName BMI_GetComponentName_DOCSTRING + + +%define BMI_GetCurrentTime_DOCSTRING +"Basic Model Interface method that returns the current simulation time, in +seconds. (Same as :meth:`GetTime`.) The reaction module does not change the +time value, so the returned value is equal to the default (0.0) or the last +time set by :meth:`BMI_SetValue`('Time', time) or :meth:`SetTime`. + +Returns: + float: The current simulation time, in seconds." +%enddef +%feature("docstring") PhreeqcRM::BMI_GetCurrentTime BMI_GetCurrentTime_DOCSTRING + + +%define BMI_GetEndTime_DOCSTRING +"Basic Model Interface method that returns :meth:`BMI_GetCurrentTime` plus +:meth:`BMI_GetTimeStep`, in seconds. + +Returns: + float: The end of the time step, in seconds." +%enddef +%feature("docstring") PhreeqcRM::BMI_GetEndTime BMI_GetEndTime_DOCSTRING + + +%define BMI_GetInputItemCount_DOCSTRING +"Basic Model Interface method that returns count of input variables that can be +set with :meth:`BMI_SetValue`. + +Returns: + int: Count of input variables that can be set with :meth:`BMI_SetValue`." +%enddef +%feature("docstring") PhreeqcRM::BMI_GetInputItemCount BMI_GetInputItemCount_DOCSTRING + + +%define BMI_GetInputVarNames_DOCSTRING +"Basic Model Interface method that returns a list of the variable names that +can be set with :meth:`BMI_SetValue`. + +Returns: + tuple of strings: A list of the variable names that can be set with + :meth:`BMI_SetValue`." +%enddef +%feature("docstring") PhreeqcRM::BMI_GetInputVarNames BMI_GetInputVarNames_DOCSTRING + + +%define BMI_GetOutputItemCount_DOCSTRING +"Basic Model Interface method that returns count of output variables that can be +retrieved with :meth:`BMI_GetValue`. + +Returns: + int: Count of output variables that can be retrieved with + :meth:`BMI_GetValue`." +%enddef +%feature("docstring") PhreeqcRM::BMI_GetOutputItemCount BMI_GetOutputItemCount_DOCSTRING + + +%define BMI_GetOutputVarNames_DOCSTRING +"Basic Model Interface method that returns a list of the variable names that +can be retrieved with :meth:`BMI_GetValue`. + +Returns: + tuple of strings: A list of the variable names that can be retrieved with + :meth:`BMI_GetValue`." +%enddef +%feature("docstring") PhreeqcRM::BMI_GetOutputVarNames BMI_GetOutputVarNames_DOCSTRING + + +%define BMI_GetTimeStep_DOCSTRING +"Basic Model Interface method that returns the current simulation time step, in +seconds. (Same as :meth:`GetTimeStep`.) The reaction module does not change the +time-step value, so the returned value is equal to the last time step set by +:meth:`BMI_SetValue`('TimeStep', time_step) or :meth:`SetTimeStep`. + +Returns: + float: The current simulation time step, in seconds." +%enddef +%feature("docstring") PhreeqcRM::BMI_GetTimeStep BMI_GetTimeStep_DOCSTRING + + +%define BMI_GetTimeUnits_DOCSTRING +"Basic Model Interface method that returns the time units of PhreeqcRM. +All time units are seconds for PhreeqcRM. + +Returns: + string: Returns the string 'seconds'." +%enddef +%feature("docstring") PhreeqcRM::BMI_GetTimeUnits BMI_GetTimeUnits_DOCSTRING + + +%define BMI_GetValue_DOCSTRING +"Basic Model Interface method that retrieves model variables. Only variables in +the list provided by :meth:`BMI_GetOutputVarNames` can be retrieved. The BMI +interface to PhreeqcRM is only partial, and provides only the most basic +functions. The native PhreeqcRM methods (those without the the BMI_ prefix) +provide a complete interface. + +Args: + name (string): Name of the variable to retrieve. + dest (type defined below): Variable in which to place results. + +Variable names for the first argument (name) and variable type of the +second argument (dest). +'ComponentCount', dest: int; +'Components', dest: tuple of strings; +'Concentrations', dest: DoubleVector; +'CurrentSelectedOutputUserNumber', dest: int; +'Density', dest: DoubleVector; +'ErrorString', dest: std::string; +'FilePrefix', dest: std::string; +'Gfw', dest: std::vector< double >; +'GridCellCount', dest: int; +'InputVarNames', dest: tuple of strings; +'OutputVarNames', dest: tuple of strings; +'Porosity', dest: DoubleVector; +'Pressure', dest: DoubleVector; +'Saturation', dest: DoubleVector; +'SelectedOutput', dest: DoubleVector; +'SelectedOutputColumnCount', dest: int; +'SelectedOutputCount', dest: int; +'SelectedOutputHeadings', dest: tuple of strings; +'SelectedOutputOn', dest: Boolean; +'SelectedOutputRowCount', dest: int; +'SolutionVolume', dest: DoubleVector; +'Temperature', dest: DoubleVector; +'Time', dest: double; +'TimeStep', dest: double." +%enddef +%feature("docstring") PhreeqcRM::BMI_GetValue BMI_GetValue_DOCSTRING + +%define BMI_GetVarItemsize_DOCSTRING +"Basic Model Interface method that retrieves size of an individual item that +can be set or retrived. Sizes may be sizeof(int), sizeof(double), or a +character length for string variables. Only variables in the list provided by +:meth:`BMI_GetInputVarNames` can be set. Only variables in the list provided by +:meth:`BMI_GetOutputVarNames` can be retrieved. + +Args: + name (string): Name of the variable to retrieve size. + +Returns: + int: Size of one element of variable." +%enddef +%feature("docstring") PhreeqcRM::BMI_GetVarItemsize BMI_GetVarItemsize_DOCSTRING + + +%define BMI_GetVarNbytes_DOCSTRING +"Basic Model Interface method that retrieves the total number of bytes that are +set for a variable with :meth:`BMI_SetValue` or retrieved for a variable with +:meth:`BMI_GetValue`. Only variables in the list provided by +:meth:`BMI_GetInputVarNames` can be set. Only variables in the list provided by +:meth:`BMI_GetOutputVarNames` can be retrieved. + +Args: + name (string): Name of the variable to retrieve total bytes. + +Returns: + int: Total number of bytes set or retrieved for variable." +%enddef +%feature("docstring") PhreeqcRM::BMI_GetVarNbytes BMI_GetVarNbytes_DOCSTRING + + +%define BMI_GetVarType_DOCSTRING +"Basic Model Interface method that retrieves the type of a variable that can be +set with :meth:`BMI_SetValue` or retrieved with :meth:`BMI_GetValue`. Types are +'int', 'double', or 'string'. Only variables in the list provided by +:meth:`BMI_GetInputVarNames` can be set. Only variables in the list provided by +:meth:`BMI_GetOutputVarNames` can be retrieved. + +Args: + name (string): Name of the variable to retrieve type. + +Returns: + string: Character string of variable type." +%enddef +%feature("docstring") PhreeqcRM::BMI_GetVarType BMI_GetVarType_DOCSTRING + + +%define BMI_GetVarUnits_DOCSTRING +"Basic Model Interface method that retrieves the units of a variable that can +be set with :meth:`BMI_SetValue` or retrieved with :meth:`BMI_GetValue`. Only +variables in the list provided by :meth:`BMI_GetInputVarNames` can be set. Only +variables in the list provided by :meth:`BMI_GetOutputVarNames` can be +retrieved. + +Args: + name (string): Name of the variable to retrieve type. + +Returns: + string: Character string of units for variable." +%enddef +%feature("docstring") PhreeqcRM::BMI_GetVarUnits BMI_GetVarUnits_DOCSTRING + + +%define BMI_Initialize_DOCSTRING +"Basic Model Interface method that can be used to initialize a PhreeqcRM +instance. This method is equivalent to :meth:`InitializeYAML`. A YAML file can +be used in initialization. The file contains a YAML map of PhreeqcRM methods +and the arguments corresponding to the method. For example, + +LoadDatabase: phreeqc.dat +RunFile: +workers: true +initial_phreeqc: true +utility: true +chemistry_name: advect.pqi + +BMI_Initialize will read the YAML file and execute the specified methods with +the specified arguments. Using YAML terminology, the argument(s) for a method +may be a scalar, a sequence, or a map, depending if the argument is a single +item, a single vector, or there are multiple arguments. In the case of a map, +the name associated with each argument (for example 'chemistry_name' above) is +arbitrary. The names of the map keys for map arguments are not used in parsing +the YAML file; only the order of the arguments is important. + +The PhreeqcRM methods that can be specified in a YAML file include: + +CloseFiles(void); +CreateMapping(int list, numpy.ndarray, or tuple: grid2chem); +DumpModule(); +FindComponents(); +InitialPhreeqc2Module(int list, numpy.ndarray, or tuple: initial_conditions1); +InitialPhreeqc2Module(int list, numpy.ndarray, or tuple: initial_conditions1, + int list, numpy.ndarray, or tuple: initial_conditions2, + float list, numpy.ndarray, or tuple: fraction1); +InitialPhreeqcCell2Module(int n, int list, numpy.ndarray, or tuple: cell_numbers); +LoadDatabase(string database); +OpenFiles(void); +OutputMessage(string str); +RunCells(void); +RunFile(Boolean workers, Boolean initial_phreeqc, Boolean utility, string chemistry_name); +RunString(Boolean workers, Boolean initial_phreeqc, Boolean utility, string input_string); +ScreenMessage(string str); +SetComponentH2O(Boolean tf); +SetConcentrations(float list, numpy.ndarray, or tuple: c); +SetCurrentSelectedOutputUserNumber(int n_user); +SetDensity(float list, numpy.ndarray, or tuple: density); +SetDumpFileName(string dump_name); +SetErrorHandlerMode(int mode); +SetErrorOn(Boolean tf); +SetFilePrefix(string prefix); +SetGasCompMoles(float list, numpy.ndarray, or tuple: gas_moles); +SetGasPhaseVolume(float list, numpy.ndarray, or tuple: gas_volume); +SetPartitionUZSolids(Boolean tf); +SetPorosity(float list, numpy.ndarray, or tuple: por); +SetPressure(float list, numpy.ndarray, or tuple: p); +SetPrintChemistryMask(int list, numpy.ndarray, or tuple: cell_mask); +SetPrintChemistryOn(Boolean workers, Boolean initial_phreeqc, Boolean utility); +SetRebalanceByCell(Boolean tf); +SetRebalanceFraction(float f); +SetRepresentativeVolume(float list, numpy.ndarray, or tuple: rv); +SetSaturation(float list, numpy.ndarray, or tuple: sat); +SetScreenOn(Boolean tf); +SetSelectedOutputOn(Boolean tf); +SetSpeciesSaveOn(Boolean save_on); +SetTemperature(float list, numpy.ndarray, or tuple: t); +SetTime(float time); +SetTimeConversion(float conv_factor); +SetTimeStep(float time_step); +SetUnitsExchange(int option); +SetUnitsGasPhase(int option); +SetUnitsKinetics(int option); +SetUnitsPPassemblage(int option); +SetUnitsSolution(int option); +SetUnitsSSassemblage(int option); +SetUnitsSurface(int option); +SpeciesConcentrations2Module(float list, numpy.ndarray, or tuple: species_conc); +StateSave(int istate); +StateApply(int istate); +StateDelete(int istate); +UseSolutionDensityVolume(Boolean tf); +WarningMessage(string warnstr); + +Args: + config_file (string): File with YAML definitions for PhreeqcRM + initialization." +%enddef +%feature("docstring") PhreeqcRM::BMI_Initialize BMI_Initialize_DOCSTRING + + +%define BMI_SetValue_DOCSTRING +"Basic Model Interface method that sets model variables. Only variables in the +list provided by :meth:`BMI_GetInputVarNames` can be set. The BMI interface to +PhreeqcRM is only partial, and provides only the most basic functions. The +native PhreeqcRM methods (those without the the BMI_ prefix) provide a complete +interface, and it is expected that the native methods will be used in +preference to the BMI_ methods. + +Variable names for the first argument +of BMI_SetValue and the equivalent PhreeqcRM method are as follows: +'Concentrations', :meth:`SetConcentrations`; +'Density', :meth:`SetDensity`; +'FilePrefix', :meth:`SetFilePrefix`; +'NthSelectedOutput', :meth:`SetNthSelectedOutput`; +'Porosity', :meth:`SetPorosity`; +'Pressure', :meth:`SetPressure`; +'Saturation', :meth:`SetSaturation`; +'SelectedOutputOn', :meth:`SetSelectedOutputOn`; +'Temperature', :meth:`SetTemperature`; +'Time', :meth:`SetTime`; +'TimeStep', :meth:`SetTimeStep`." +%enddef +%feature("docstring") PhreeqcRM::BMI_SetValue BMI_SetValue_DOCSTRING + + +%define BMI_Update_DOCSTRING +"Basic Model Interface method that runs PhreeqcRM for one time step. This +method is equivalent to :meth:`RunCells`. PhreeqcRM will equilibrate the +solutions with all equilibrium reactants (EQUILIBRIUM_PHASES, EXCHANGE, +GAS_PHASE, SOLID_SOLUTIONS, and SURFACE) and integrate KINETICS reactions for +the specified time step (:meth:`SetTimeStep`)." +%enddef +%feature("docstring") PhreeqcRM::BMI_Update BMI_Update_DOCSTRING diff --git a/src/swig/python/SimpleAdvect.py b/src/swig/python/SimpleAdvect.py new file mode 100644 index 000000000..a47051043 --- /dev/null +++ b/src/swig/python/SimpleAdvect.py @@ -0,0 +1,194 @@ +import phreeqcrm +import sys +# import numpy as np + +""" + Functions that accept a constant vector reference + (const std::vector&) should be callable + with any of the three Python data types, namely + np.ndarray, list, and tuple. + + For example, the porosity can be initialized: + + # numpy.ndarray + porosity = np.full((nxyz,), 0.2) + + # list (using list repetition) + porosity = [0.2] * nxyz + + # list (using list comprehension) + porosity = [0.2 for i in range(nxyz)] + + # tuple (using a generator expression) + porosity = tuple(0.2 for i in range(nxyz)) + + # And used: + nxyz = 20 + nthreads = 3 + phreeqc_rm = phreeqcrm.PhreeqcRM(nxyz, nthreads) + status = phreeqc_rm.SetPorosity(porosity) + + # likewise for integers (const std::vector&) + + Currently functions that take non-const vectors (ie OUT or INOUT) + must use the SWIG wrapped vector class like this: + + c_dbl_vect = phreeqcrm.DoubleVector(nxyz * len(components)) + status = phreeqc_rm.GetConcentrations(c_dbl_vect) +""" + +def SimpleAdvect(): + nxyz = 20 + nthreads = 3 + + phreeqc_rm = phreeqcrm.PhreeqcRM(nxyz, nthreads) + + # Set properties + status = phreeqc_rm.SetComponentH2O(False) + phreeqc_rm.UseSolutionDensityVolume(False) + + # Open files + status = phreeqc_rm.SetFilePrefix("SimpleAdvect_py") + phreeqc_rm.OpenFiles() + + # Set concentration units + status = phreeqc_rm.SetUnitsSolution(2) # 1, mg/L; 2, mol/L; 3, kg/kgs + status = phreeqc_rm.SetUnitsExchange(1) # 0, mol/L cell; 1, mol/L water; 2 mol/L rock + + # Set conversion from seconds to user units (days) + time_conversion = 1.0 / 86400 + status = phreeqc_rm.SetTimeConversion(time_conversion) + + # Set initial porosity + por = [0.2] * nxyz + status = phreeqc_rm.SetPorosity(por) + + # Set cells to print chemistry when print chemistry is turned on + print_chemistry_mask = [1] * nxyz + status = phreeqc_rm.SetPrintChemistryMask(print_chemistry_mask) + nchem = phreeqc_rm.GetChemistryCellCount() + + # -------------------------------------------------------------------------- + # Set initial conditions + # -------------------------------------------------------------------------- + + # Set printing of chemistry file + status = phreeqc_rm.SetPrintChemistryOn(False, True, False) # workers, initial_phreeqc, utility + + # Load database + status = phreeqc_rm.LoadDatabase("phreeqc.dat") + + # Run file to define solutions and reactants for initial conditions, selected output + status = phreeqc_rm.RunFile(True, True, True, "advect.pqi") + + # Clear contents of workers and utility + input = "DELETE; -all" + status = phreeqc_rm.RunString(True, False, True, input) + + # Determine number of components to transport + ncomps = phreeqc_rm.FindComponents() + + # Get component information (as a tuple) + components = phreeqc_rm.GetComponents() + + for comp in components: + phreeqc_rm.OutputMessage(comp) + phreeqc_rm.OutputMessage("\n") + + # Set array of initial conditions + if 'numpy' in sys.modules: + # this may require numpy to be linked in + ic1 = np.full((nxyz * 7,), -1) + else: + ic1 = [-1] * nxyz * 7 + for i in range(nxyz): + ic1[i] = 1 # Solution 1 + ic1[nxyz + i] = -1 # Equilibrium phases none + ic1[2 * nxyz + i] = 1 # Exchange 1 + ic1[3 * nxyz + i] = -1 # Surface none + ic1[4 * nxyz + i] = -1 # Gas phase none + ic1[5 * nxyz + i] = -1 # Solid solutions none + ic1[6 * nxyz + i] = -1 # Kinetics none + status = phreeqc_rm.InitialPhreeqc2Module(ic1) + + # Initial equilibration of cells + time = 0.0 + time_step = 0.0 + status = phreeqc_rm.SetTime(time) + status = phreeqc_rm.SetTimeStep(time_step) + status = phreeqc_rm.RunCells() + + # for now use std::vector wrapper for [inout] arrays + c_dbl_vect = phreeqcrm.DoubleVector(nxyz * len(components), 0.0) + status = phreeqc_rm.GetConcentrations(c_dbl_vect) + + # -------------------------------------------------------------------------- + # Set boundary condition + # -------------------------------------------------------------------------- + + # for now use std::vector wrapper for [inout] arrays + bc_conc_dbl_vect = phreeqcrm.DoubleVector() + nbound = 1 + bc1 = [0] * nbound # solution 0 from Initial IPhreeqc instance + status = phreeqc_rm.InitialPhreeqc2Concentrations(bc_conc_dbl_vect, bc1) + + # -------------------------------------------------------------------------- + # Transient loop + # -------------------------------------------------------------------------- + status = phreeqc_rm.SetTemperature([20.0] * nxyz) + status = phreeqc_rm.SetPressure([2.0] * nxyz) + + time_step = 86400.0 + status = phreeqc_rm.SetTimeStep(time_step) + + nsteps = 10 + phreeqc_rm.SetScreenOn(True) + for steps in range(nsteps): + # Transport calculation here + + message = 'Beginning transport calculation {} days\n'.format(phreeqc_rm.GetTime() * phreeqc_rm.GetTimeConversion()) + phreeqc_rm.LogMessage(message) + phreeqc_rm.ScreenMessage(message) + + message = ' Time step {} days\n'.format(phreeqc_rm.GetTimeStep() * phreeqc_rm.GetTimeConversion()) + phreeqc_rm.LogMessage(message) + phreeqc_rm.ScreenMessage(message) + + simpleadvection(c_dbl_vect, bc_conc_dbl_vect, ncomps, nxyz, nbound) + + # Transfer data to PhreeqcRM for reactions + print_selected_output_on = (steps == nsteps - 1) + print_chemistry_on = (steps == nsteps - 1) + status = phreeqc_rm.SetSelectedOutputOn(print_selected_output_on) + status = phreeqc_rm.SetPrintChemistryOn(print_chemistry_on, False, False) # workers, initial_phreeqc, utility + status = phreeqc_rm.SetConcentrations(c_dbl_vect) # Transported concentrations + time += time_step + status = phreeqc_rm.SetTime(time) + + # Run cells with transported conditions + message = 'Beginning reaction calculation {} days\n'.format(time * phreeqc_rm.GetTimeConversion()) + phreeqc_rm.LogMessage(message) + phreeqc_rm.ScreenMessage(message) + status = phreeqc_rm.RunCells() + + # Transfer data from PhreeqcRM for transport + status = phreeqc_rm.GetConcentrations(c_dbl_vect) + + # Clean up + status = phreeqc_rm.CloseFiles() + status = phreeqc_rm.MpiWorkerBreak() +def simpleadvection(c, bc_conc, ncomps, nxyz, dim): + """ + TODO + """ + for i in range(nxyz - 1, 0, -1): + for j in range(ncomps): + c[j * nxyz + i] = c[j * nxyz + i - 1] # component j + + # Cell zero gets boundary condition + for j in range(ncomps): + c[j * nxyz] = bc_conc[j * dim]; # component j + + +if __name__ == '__main__': + SimpleAdvect() \ No newline at end of file diff --git a/src/swig/python/WriteYAMLFile_py.py b/src/swig/python/WriteYAMLFile_py.py new file mode 100644 index 000000000..fdcec519a --- /dev/null +++ b/src/swig/python/WriteYAMLFile_py.py @@ -0,0 +1,109 @@ +import numpy as np +import yamlphreeqcrm + +def WriteYAMLFile_py(): + # Create YAMLPhreeqcRM document + yrm = yamlphreeqcrm.YAMLPhreeqcRM() + # Number of cells + nxyz = 40; + # Set GridCellCount + yrm.YAMLSetGridCellCount(nxyz) + # Set some properties + yrm.YAMLSetErrorHandlerMode(1) + yrm.YAMLSetComponentH2O(False) + yrm.YAMLSetRebalanceFraction(0.5) + yrm.YAMLSetRebalanceByCell(True) + yrm.YAMLUseSolutionDensityVolume(False) + yrm.YAMLSetPartitionUZSolids(False) + # Open files + yrm.YAMLSetFilePrefix("AdvectBMI_py"); + yrm.YAMLOpenFiles(); + # Set concentration units + yrm.YAMLSetUnitsSolution(2) # 1, mg/L; 2, mol/L; 3, kg/kgs + yrm.YAMLSetUnitsPPassemblage(1) # 0, mol/L cell; 1, mol/L water; 2 mol/L rock + yrm.YAMLSetUnitsExchange(1) # 0, mol/L cell; 1, mol/L water; 2 mol/L rock + yrm.YAMLSetUnitsSurface(1) # 0, mol/L cell; 1, mol/L water; 2 mol/L rock + yrm.YAMLSetUnitsGasPhase(1) # 0, mol/L cell; 1, mol/L water; 2 mol/L rock + yrm.YAMLSetUnitsSSassemblage(1) # 0, mol/L cell; 1, mol/L water; 2 mol/L rock + yrm.YAMLSetUnitsKinetics(1) # 0, mol/L cell; 1, mol/L water; 2 mol/L rock + # Set conversion from seconds to user units (days) Only affects one print statement + time_conversion = 1.0 / 86400.0 + yrm.YAMLSetTimeConversion(time_conversion) + # Set representative volume + rv = [1] * nxyz + yrm.YAMLSetRepresentativeVolume(rv) + # Set initial density + density = [1.0] * nxyz + yrm.YAMLSetDensity(density) + # Set initial porosity + por = [0.2] * nxyz + yrm.YAMLSetPorosity(por) + # Set initial saturation + sat = [1] * nxyz + yrm.YAMLSetSaturation(sat) + # Set cells to print chemistry when print chemistry is turned on + print_chemistry_mask = [0] * nxyz + for i in range(nxyz // 2): + print_chemistry_mask[i] = 1 + yrm.YAMLSetPrintChemistryMask(print_chemistry_mask) + # Demonstation of mapping, two equivalent rows by symmetry + # zero-based indexing + grid2chem = [-1] * nxyz + for i in range(nxyz // 2): + grid2chem[i] = i + grid2chem[i + nxyz // 2] = i + yrm.YAMLCreateMapping(grid2chem) + # Set printing of chemistry file + yrm.YAMLSetPrintChemistryOn(False, True, False) # workers, initial_phreeqc, utility + # Load database + yrm.YAMLLoadDatabase("phreeqc.dat") + # Run file to define solutions and reactants for initial conditions, selected output + workers = True # Worker instances do the reaction calculations for transport + initial_phreeqc = True # InitialPhreeqc instance accumulates initial and boundary conditions + utility = True # Utility instance is available for processing + yrm.YAMLRunFile(workers, initial_phreeqc, utility, "advect.pqi") + # Clear contents of workers and utility + initial_phreeqc = False + input = "DELETE; -all" + yrm.YAMLRunString(workers, initial_phreeqc, utility, input) + # Determine number of components to transport + yrm.YAMLFindComponents() + # set array of initial conditions + ic1 = [-1]*(nxyz*7) + ic2 = [-1]*(nxyz*7) + f1 = [1]*(nxyz*7) + for i in range(nxyz): + ic1[i] = 1; # Solution 1 + ic1[nxyz + i] = -1; # Equilibrium phases none + ic1[2 * nxyz + i] = 1; # Exchange 1 + ic1[3 * nxyz + i] = -1; # Surface none + ic1[4 * nxyz + i] = -1; # Gas phase none + ic1[5 * nxyz + i] = -1; # Solid solutions none + ic1[6 * nxyz + i] = -1; # Kinetics none + yrm.YAMLInitialPhreeqc2Module_mix(ic1, ic2, f1) + # No mixing is defined, so the following is equivalent + #yrm.YAMLInitialPhreeqc2Module(ic1) + + # alternative for setting initial conditions + # cell number in first argument (-1 indicates last solution, 40 in this case) + # in advect.pqi and any reactants with the same number-- + # Equilibrium phases, exchange, surface, gas phase, solid solution, and (or) kinetics-- + # will be written to cells 18 and 19 (0 based) + module_cells = [18, 19] + yrm.YAMLInitialPhreeqcCell2Module(-1, module_cells) + # Initial equilibration of cells + time_step = 0.0 # no kinetics + yrm.YAMLSetTimeStep(time_step) + time = 0.0 + yrm.YAMLSetTime(time) + yrm.YAMLRunCells() + time_step = 86400.0 + yrm.YAMLSetTimeStep(time_step) + # Write YAML file + yrm.WriteYAMLDoc("AdvectBMI_py.yaml") + print("Done.") + +if __name__ == '__main__': + WriteYAMLFile_py() + + diff --git a/src/swig/python/YAMLPhreeqcRM.i b/src/swig/python/YAMLPhreeqcRM.i new file mode 100644 index 000000000..50b18b08c --- /dev/null +++ b/src/swig/python/YAMLPhreeqcRM.i @@ -0,0 +1,1297 @@ +%define YAMLPhreeqcRM_DOCSTRING +"Helper class that writes data to a YAML file that can be used +to initialize a PhreeqcRM instance. The stored data can be used +to set properties, run files, and set initial conditions for +a PhreeqcRM instance." +%enddef +%feature("docstring") YAMLPhreeqcRM::YAMLPhreeqcRM YAMLPhreeqcRM_DOCSTRING + +%define Clear_DOCSTRING +"Clears all definitions from the YAML document." +%enddef +%feature("docstring") YAMLPhreeqcRM::Clear Clear_DOCSTRING + + +%define WriteYAMLDoc_DOCSTRING +"Writes the YAML document to file. +Args: + file_name (string): Name of file where YAML document will be written." +%enddef +%feature("docstring") YAMLPhreeqcRM::WriteYAMLDoc WriteYAMLDoc_DOCSTRING + + +%define YAMLCloseFiles_DOCSTRING +"Inserts data into the YAML document for the PhreeqcRM method +CloseFiles. When the YAML document is written to file it can be +processed by the method InitializeYAML to initialize a PhreeqcRM +instance. + +CloseFiles closes the output and log files." +%enddef +%feature("docstring") YAMLPhreeqcRM::YAMLCloseFiles YAMLCloseFiles_DOCSTRING + + +%define YAMLCreateMapping_DOCSTRING +"Inserts data into the YAML document for the PhreeqcRM method +CreateMapping. When the YAML document is written to file it can be +processed by the method InitializeYAML to initialize a PhreeqcRM +instance. + +CreateMapping provides a mapping from grid cells in the user's model to +reaction cells for which chemistry needs to be run. The mapping is used +to eliminate inactive cells and to use symmetry to decrease the number +of cells for which chemistry must be run. The array grid2chem of size +nxyz (the number of grid cells) must contain the set of all integers 0 +<= i < count_chemistry, where count_chemistry is a number less than or +equal to nxyz. Inactive cells are assigned a negative integer. The +mapping may be many-to-one to account for symmetry. Default is a +one-to-one mapping--all user grid cells are reaction cells (equivalent +to grid2chem values of 0,1,2,3,...,nxyz-1). + +Args: + grid2chem (int list, numpy.ndarray, or tuple): A vector of integers: Nonnegative + is a reaction-cell number (0 based), negative is an inactive cell. +Vector + is of size nxyz (number of grid cells)." +%enddef +%feature("docstring") YAMLPhreeqcRM::YAMLCreateMapping YAMLCreateMapping_DOCSTRING + + +%define YAMLDumpModule_DOCSTRING +"Inserts data into the YAML document for the PhreeqcRM method +DumpModule. When the YAML document is written to file it can be +processed by the method InitializeYAML to initialize a PhreeqcRM +instance. + +DumpModule writes the contents of all workers to file in _RAW formats +(see appendix of PHREEQC version 3 manual), including SOLUTIONs and all +reactants. + +Args: + dump_on (Boolean): Signal for writing the dump file, true or false. + append (Boolean): Signal to append to the contents of the dump file, + true or false." +%enddef +%feature("docstring") YAMLPhreeqcRM::YAMLDumpModule YAMLDumpModule_DOCSTRING + + +%define YAMLFindComponents_DOCSTRING +"Inserts data into the YAML document for the PhreeqcRM method +FindComponents. When the YAML document is written to file it can be +processed by the method InitializeYAML to initialize a PhreeqcRM +instance. + +FindComponents accumulates a list of elements. Elements are those that +have been defined in a solution or any other reactant +(EQUILIBRIUM_PHASE, KINETICS, and others), including charge imbalance. +This method can be called multiple times and the list that is created is +cummulative. The list is the set of components that needs to be +transported. By default the list includes water, excess H and excess O +(the H and O not contained in water); alternatively, the list may be set +to contain total H and total O (:meth:`YAMLSetComponentH2O`), which +requires transport results to be accurate to eight or nine significant +digits. If multicomponent diffusion (MCD) is to be modeled, there is a +capability to retrieve aqueous species concentrations and to set new +solution concentrations after MCD by using individual species +concentrations (:meth:`YAMLSpeciesConcentrations2Module`). To use these +methods, the save-species property needs to be turned on +(:meth:`YAMLSetSpeciesSaveOn`). If the save-species property is on, +FindComponents will generate a list of aqueous species, their diffusion +coefficients at 25 C, and their charge." +%enddef +%feature("docstring") YAMLPhreeqcRM::YAMLFindComponents YAMLFindComponents_DOCSTRING + + +%define YAMLInitialPhreeqc2Module_DOCSTRING +"Inserts data into the YAML document for the PhreeqcRM method +InitialPhreeqc2Module. When the YAML document is written to file it can +be processed by the method InitializeYAML to initialize a PhreeqcRM +instance. + +InitialPhreeqc2Module transfers solutions and reactants from the +InitialPhreeqc instance to the reaction-module workers. +ic1 is used to select initial conditions, including +solutions and reactants, for each cell of the model, without mixing. +ic1 is dimensioned 7 times nxyz, where nxyz is the +number of grid cells in the user's model. The dimension of 7 refers to +solutions and reactants in the following order: (0) SOLUTIONS, (1) +EQUILIBRIUM_PHASES, (2) EXCHANGE, (3) SURFACE, (4) GAS_PHASE, (5) +SOLID_SOLUTIONS, and (6) KINETICS. The definition +initial_solution1[3*nxyz + 99] = 2, indicates that cell 99 (0 based) +contains the SURFACE definition (index 3) defined by SURFACE 2 in the +InitialPhreeqc instance. + +Args: + ic1 (int list, numpy.ndarray, or tuple): Vector of solution and reactant + index numbers that refer to definitions in the InitialPhreeqc + instance. Size is 7 times nxyz. The order of definitions is given + above. Negative values are ignored, resulting in no definition of + that entity for that cell." +%enddef +%feature("docstring") YAMLPhreeqcRM::YAMLInitialPhreeqc2Module YAMLInitialPhreeqc2Module_DOCSTRING + + +%define YAMLInitialPhreeqc2Module_DOCSTRING +"Inserts data into the YAML document for the PhreeqcRM method +InitialPhreeqc2Module. When the YAML document is written to file it can +be processed by the method InitializeYAML to initialize a PhreeqcRM +instance. + +InitialPhreeqc2Module transfers solutions and reactants from the +InitialPhreeqc instance to the reaction-module workers, possibly with +mixing. In its simplest form, ic1 is used to select +initial conditions, including solutions and reactants, for each cell of +the model, without mixing. Ic1 is dimensioned 7 times +nxyz, where nxyz is the number of grid cells in the user's model. The +dimension of 7 refers to solutions and reactants in the following order: +(0) SOLUTIONS, (1) EQUILIBRIUM_PHASES, (2) EXCHANGE, (3) SURFACE, (4) +GAS_PHASE, (5) SOLID_SOLUTIONS, and (6) KINETICS. The definition +ic1[3*nxyz + 99] = 2, indicates that cell 99 (0 based) +contains the SURFACE definition (index 3) defined by SURFACE 2 in the +InitialPhreeqc instance (either by RunFile or RunString). + +It is also possible to mix solutions and reactants to obtain the initial +conditions for cells. For mixing, ic2 contains numbers for a second +entity that mixes with the entity defined in ic1. F1 contains the mixing +fraction for ic1, whereas (1 - f1) is the mixing fraction for ic2. The +definitions initial_solution1[3*nxyz + 99] = 2, initial_solution2[3*nxyz ++ 99] = 3, f1[3*nxyz + 99] = 0.25 indicates that cell 99 (0 based) +contains a mixture of 0.25 SURFACE 2 and 0.75 SURFACE 3, where the +surface compositions have been defined in the InitialPhreeqc instance. +If the user number in ic2 is negative, no mixing occurs. + +Args: + ic1 (int list, numpy.ndarray, or tuple): Vector of solution and reactant index + numbers that refer to definitions in the InitialPhreeqc instance. Size is + 7 times nxyz, where nxyz is the number of grid cells in the user's model. + The order of definitions is given above. Negative values are + ignored, resulting in no definition of that entity for that cell. + ic2 (int list, numpy.ndarray, or tuple): Vector of solution and reactant index + numbers that refer to definitions in the InitialPhreeqc instance. Nonnegative + values of ic2 result in mixing with the entities defined in ic1. Negative + values result in no mixing. Size is 7 times nxyz. The order of definitions is + given above. + f1 (float list, numpy.ndarray, or tuple): Fraction of ic1 that mixes with (1 - f1) + of ic2. Size is 7 times nxyz. The order of definitions is given above." +%enddef +%feature("docstring") YAMLPhreeqcRM::YAMLInitialPhreeqc2Module YAMLInitialPhreeqc2Module_DOCSTRING + + +%define YAMLInitialPhreeqcCell2Module_DOCSTRING +"Inserts data into the YAML document for the PhreeqcRM method +InitialPhreeqcCell2Module. When the YAML document is written to file it +can be processed by the method InitializeYAML to initialize a PhreeqcRM +instance. + +InitialPhreeqcCell2Module uses a cell numbered n in the InitialPhreeqc +instance to populate a series of transport cells. All reactants with the +number n are transferred along with the solution. If MIX n exists, it is +used for the definition of the solution. If n is negative, n is +redefined to be the largest solution or MIX number in the InitialPhreeqc +instance. All reactants for each cell in the list cell_numbers are +removed before the cell definition is copied from the InitialPhreeqc +instance to the workers. + +Args: + n (int): Number that refers to a solution or MIX and associated + reactants in the InitialPhreeqc instance. + cell_numbers (int list, numpy.ndarray, or tuple): A vector of grid-cell numbers + (user's grid-cell numbering system) that will be populated with cell n from + the InitialPhreeqc instance." +%enddef +%feature("docstring") YAMLPhreeqcRM::YAMLInitialPhreeqcCell2Module YAMLInitialPhreeqcCell2Module_DOCSTRING + + +%define YAMLLoadDatabase_DOCSTRING +"Inserts data into the YAML document for the PhreeqcRM method +LoadDatabase. When the YAML document is written to file it can be +processed by the method InitializeYAML to initialize a PhreeqcRM +instance. + +LoadDatabase loads a database for all IPhreeqc instances--workers, +InitialPhreeqc, and Utility. All definitions of the reaction module are +cleared (SOLUTION_SPECIES, PHASES, SOLUTIONs, etc.), and the database is +read. + +Args: + database (string): String containing the database name." +%enddef +%feature("docstring") YAMLPhreeqcRM::YAMLLoadDatabase YAMLLoadDatabase_DOCSTRING + + +%define YAMLLogMessage_DOCSTRING +"Inserts data into the YAML document for the PhreeqcRM method +LogMessage. When the YAML document is written to file it can be +processed by the method InitializeYAML to initialize a PhreeqcRM +instance. + +LogMessage prints a message to the log file. + +Args: + str (string): String to be printed." +%enddef +%feature("docstring") YAMLPhreeqcRM::YAMLLogMessage YAMLLogMessage_DOCSTRING + + +%define YAMLOpenFiles_DOCSTRING +"Inserts data into the YAML document for the PhreeqcRM method OpenFiles. +When the YAML document is written to file it can be processed by the +method InitializeYAML to initialize a PhreeqcRM instance. + +OpenFiles opens the output and log files. Files are named +prefix.chem.txt and prefix.log.txt based on the prefix defined by +:meth:`YAMLSetFilePrefix`." +%enddef +%feature("docstring") YAMLPhreeqcRM::YAMLOpenFiles YAMLOpenFiles_DOCSTRING + + +%define YAMLOutputMessage_DOCSTRING +"Inserts data into the YAML document for the PhreeqcRM method +OutputMessage. When the YAML document is written to file it can be +processed by the method InitializeYAML to initialize a PhreeqcRM +instance. + +OutputMessage prints a message to the output file. + +Args: + str(string): String to be printed." +%enddef +%feature("docstring") YAMLPhreeqcRM::YAMLOutputMessage YAMLOutputMessage_DOCSTRING + + +%define YAMLRunCells_DOCSTRING +"Inserts data into the YAML document for the PhreeqcRM method RunCells. +When the YAML document is written to file it can be processed by the +method InitializeYAML to initialize a PhreeqcRM instance. + +RunCells runs reactions for all cells in the reaction module. During +initialization, RunCells can be used to equilibrate each solution with +all reactants in a cell while using a time step of zero +(:meth:`YAMLSetTimeStep`) to avoid kinetic reactions. Other properties +that may need to be initialized before RunCells is invoked include +porosity (:meth:`YAMLSetPorosity`), saturation +(:meth:`YAMLSetSaturation`), temperature (:meth:`YAMLSetTemperature`), +and pressure (:meth:`YAMLSetPressure`)." +%enddef +%feature("docstring") YAMLPhreeqcRM::YAMLRunCells YAMLRunCells_DOCSTRING + + +%define YAMLRunFile_DOCSTRING +"Inserts data into the YAML document for the PhreeqcRM method RunFile. +When the YAML document is written to file it can be processed by the +method InitializeYAML to initialize a PhreeqcRM instance. + +RunFile runs a PHREEQC input file. The first three arguments determine +which IPhreeqc instances will run the file--the workers, the +InitialPhreeqc instance, and (or) the Utility instance. Input files that +modify the thermodynamic database should be run by all three sets of +instances. Files with SELECTED_OUTPUT definitions that will be used +during the time-stepping loop need to be run by the workers. Files that +contain initial conditions or boundary conditions should be run by the +InitialPhreeqc instance. + +Args: + workers (Boolean): True, the workers will run the file; False, the + workers will not run the file. + initial_phreeqc (Boolean): True, the InitialPhreeqc instance will run + the file; False, the InitialPhreeqc will not run the file. + utility (Boolean): True, the Utility instance will run the file; + False, the Utility instance will not run the file. + chemistry_name (string): Name of the file to run." +%enddef +%feature("docstring") YAMLPhreeqcRM::YAMLRunFile YAMLRunFile_DOCSTRING + + +%define YAMLRunString_DOCSTRING +"Inserts data into the YAML document for the PhreeqcRM method RunString. +When the YAML document is written to file it can be processed by the +method InitializeYAML to initialize a PhreeqcRM instance. + +RunString runs a PHREEQC input string. The first three arguments +determine which IPhreeqc instances will run the string--the workers, the +InitialPhreeqc instance, and (or) the Utility instance. Input strings +that modify the thermodynamic database should be run by all three sets +of instances. Strings with SELECTED_OUTPUT definitions that will be used +during the time-stepping loop need to be run by the workers. Strings +that contain initial conditions or boundary conditions should be run by +the InitialPhreeqc instance. + +Args: + workers (Boolean): True, the workers will run the string; False, the + workers will not run the string. + initial_phreeqc (Boolean): True, the InitialPhreeqc instance will + run the string; False, the InitialPhreeqc will not run the string. + utility (Boolean): True, the Utility instance will run the string; + False, the Utility instance will not run the string. + input_string (string): String containing PHREEQC input." +%enddef +%feature("docstring") YAMLPhreeqcRM::YAMLRunString YAMLRunString_DOCSTRING + + +%define YAMLScreenMessage_DOCSTRING +"Inserts data into the YAML document for the PhreeqcRM method +ScreenMessage. When the YAML document is written to file it can be +processed by the method InitializeYAML to initialize a PhreeqcRM +instance. + +ScreenMessage prints a message to the screen. + +Args: + str (string): String to be printed." +%enddef +%feature("docstring") YAMLPhreeqcRM::YAMLScreenMessage YAMLScreenMessage_DOCSTRING + + +%define YAMLSetComponentH2O_DOCSTRING +"Inserts data into the YAML document for the PhreeqcRM method +SetComponentH2O. When the YAML document is written to file it can be +processed by the method InitializeYAML to initialize a PhreeqcRM +instance. + +SetComponentH2O selects whether to include H2O in the component list. +The concentrations of H and O must be known accurately (8 to 10 +significant digits) for the numerical method of PHREEQC to produce +accurate pH and pe values. Because most of the H and O are in the water +species, it may be more robust (require less accuracy in transport) to +transport the excess H and O (the H and O not in water) and water. The +default setting (true) is to include water, excess H, and excess O as +components. A setting of false will include total H and total O as +components. YAMLSetComponentH2O must be called before +:meth:`YAMLFindComponents`. + +Args: + tf (Boolean): True, excess H, excess O, and water are + included in the component list; False, total H and O are +included in + the component list." +%enddef +%feature("docstring") YAMLPhreeqcRM::YAMLSetComponentH2O YAMLSetComponentH2O_DOCSTRING + + +%define YAMLSetConcentrations_DOCSTRING +"Inserts data into the YAML document for the PhreeqcRM method +SetConcentrations. When the YAML document is written to file it can be +processed by the method InitializeYAML to initialize a PhreeqcRM +instance. + +The only way to use this method is to have pre-calculated PHREEQC +solution concentrations, which is not common. Concentrations are +normally initialized with :meth:`YAMLInitialPhreeqc2Module` or +:meth:`YAMLInitialPhreeqcCell2Module`. + +Args: + c (float list, numpy.ndarray, or tuple): Vector of component concentrations. + Size of vector is ncomps times nxyz, where ncomps is the number of components + as determined by FindComponents or GetComponentCount and nxyz is the + number of grid cells in the user's model." +%enddef +%feature("docstring") YAMLPhreeqcRM::YAMLSetConcentrations YAMLSetConcentrations_DOCSTRING + + +%define YAMLSetCurrentSelectedOutputUserNumber_DOCSTRING +"Inserts data into the YAML document for the PhreeqcRM method +SetCurrentSelectedOutputUserNumber. When the YAML document is written to +file it can be processed by the method InitializeYAML to initialize a +PhreeqcRM instance. + +SetCurrentSelectedOutputUserNumber selects the current selected output +by user number. The user may define multiple SELECTED_OUTPUT data blocks +for the workers. A user number is specified for each data block. The +value of the argument n_user selects which of the SELECTED_OUTPUT +definitions will be used for selected-output operations. + +Args: + n_user (int): User number of the SELECTED_OUTPUT data block that is + to be used." +%enddef +%feature("docstring") YAMLPhreeqcRM::YAMLSetCurrentSelectedOutputUserNumber YAMLSetCurrentSelectedOutputUserNumber_DOCSTRING + + +%define YAMLSetDensity_DOCSTRING +"Inserts data into the YAML document for the PhreeqcRM method +SetDensity. When the YAML document is written to file it can be +processed by the method InitializeYAML to initialize a PhreeqcRM +instance. + +SetDensity sets the density for each reaction cell. These density values +are used when converting from transported mass-fraction concentrations +(:meth:`YAMLSetUnitsSolution`) to produce per liter concentrations +during a call to SetConcentrations. They are also used when converting +from reaction-cell concentrations to transport concentrations, if +UseSolutionDensityVolume is set to false. + +Args: + density (float list, numpy.ndarray, or tuple): Vector of densities. Size of + vector is nxyz, where nxyz is the number of grid cells in the user's model." +%enddef +%feature("docstring") YAMLPhreeqcRM::YAMLSetDensity YAMLSetDensity_DOCSTRING + + +%define YAMLSetDumpFileName_DOCSTRING +"Inserts data into the YAML document for the PhreeqcRM method +SetDumpFileName. When the YAML document is written to file it can be +processed by the method InitializeYAML to initialize a PhreeqcRM +instance. + +SetDumpFileName sets the name of the dump file. It is the name used by +the method DumpModule. + +Args: + dump_name (string): Name of dump file." +%enddef +%feature("docstring") YAMLPhreeqcRM::YAMLSetDumpFileName YAMLSetDumpFileName_DOCSTRING + + +%define YAMLSetErrorHandlerMode_DOCSTRING +"Inserts data into the YAML document for the PhreeqcRM method +SetErrorHandlerMode. When the YAML document is written to file it can be +processed by the method InitializeYAML to initialize a PhreeqcRM +instance. + +SetErrorHandlerMode sets the action to be taken when the reaction module +encounters an error. Options are 0, return to calling program with an +error return code (default); 1, throw an exception, in C++, the +exception can be caught, for C and Fortran, the program will exit; or 2, +attempt to exit gracefully. + +Args: + mode (int): Error handling mode: 0, 1, or 2." +%enddef +%feature("docstring") YAMLPhreeqcRM::YAMLSetErrorHandlerMode YAMLSetErrorHandlerMode_DOCSTRING + + +%define YAMLSetErrorOn_DOCSTRING +"Inserts data into the YAML document for the PhreeqcRM method +SetErrorOn. When the YAML document is written to file it can be +processed by the method InitializeYAML to initialize a PhreeqcRM +instance. + +SetErrorOn sets the property that controls whether error messages are +generated and displayed. Messages include PHREEQC "ERROR" messages, and +any messages written with the method ErrorMessage. + +Args: + tf (Boolean): True, enable error messages; False, disable error + messages." +%enddef +%feature("docstring") YAMLPhreeqcRM::YAMLSetErrorOn YAMLSetErrorOn_DOCSTRING + + +%define YAMLSetFilePrefix_DOCSTRING +"Inserts data into the YAML document for the PhreeqcRM method +SetFilePrefix. When the YAML document is written to file it can be +processed by the method InitializeYAML to initialize a PhreeqcRM +instance. + +SetFilePrefix sets the prefix for the output (prefix.chem.txt) and log +(prefix.log.txt) files. These files are opened by the method OpenFiles. +Args: + prefix (string): Prefix used when opening the output and log files." +%enddef +%feature("docstring") YAMLPhreeqcRM::YAMLSetFilePrefix YAMLSetFilePrefix_DOCSTRING + + +%define YAMLSetGasCompMoles_DOCSTRING +"Inserts data into the YAML document for the PhreeqcRM method +SetGasCompMoles. When the YAML document is written to file it can be +processed by the method InitializeYAML to initialize a PhreeqcRM +instance. + +SetGasCompMoles transfers moles of gas components from the vector given +in the argument list (gas_moles) to each reaction cell. + +Args: + gas_moles (float list, numpy.ndarray, or tuple): Vector of moles of gas + components. Dimension of the vector is set to ngas_comps times nxyz, where, + ngas_comps is the result of GetGasComponentsCount, and nxyz is the number of user + grid cells. If the number of moles is set to a negative number, the gas + component will not be defined for the GAS_PHASE of the reaction cell." +%enddef +%feature("docstring") YAMLPhreeqcRM::YAMLSetGasCompMoles YAMLSetGasCompMoles_DOCSTRING + + +%define YAMLSetGasPhaseVolume_DOCSTRING +"Inserts data into the YAML document for the PhreeqcRM method +SetGasPhaseVolume. When the YAML document is written to file it can be +processed by the method InitializeYAML to initialize a PhreeqcRM +instance. + +SetGasPhaseVolume transfers volumes of gas phases from the vector given +in the argument list (gas_volume) to each reaction cell. The gas-phase +volume affects the gas-component pressures calculated for fixed-volume +gas phases. If a gas-phase volume is defined with this methood for a +GAS_PHASE in a cell, the gas phase is forced to be a fixed-volume gas +phase. + +Args: + gas_volume (float list, numpy.ndarray, or tuple): Vector of volumes for each + gas phase. Dimension of the vector is nxyz, where nxyz is the number of user + grid cells. If the volume is set to a negative number for a cell, + the gas-phase volume for that cell is not changed." +%enddef +%feature("docstring") YAMLPhreeqcRM::YAMLSetGasPhaseVolume YAMLSetGasPhaseVolume_DOCSTRING + + +%define YAMLSetGridCellCount_DOCSTRING +"Inserts data into the YAML document to define the number of cells in +the user's model. Once the YAML document is written, the number of model +cells can be extracted with the method GetGridCellCountYAML. +GetGridCellCountYAML is NOT a PhreeqcRM method; it is a global method +and must be used BEFORE the PhreeqcRM instance is created. +SetGridCellCount will be ignored once the PhreeqcRM instance exists. + +Args: + n (int): Number of cells for the PhreeqcRM instance. The number of + cells can be used in the creation of the PhreeqcRM instance. The + PhreeqcRM constructor takes two arguments. GetGridCellCountYAML + provides the value for the first argument. If the YAML file does not + contain the node "SetGridCellCount:", GetGridCellCountYAML will + return zero." +%enddef +%feature("docstring") YAMLPhreeqcRM::YAMLSetGridCellCount YAMLSetGridCellCount_DOCSTRING + + +%define YAMLSetNthSelectedOutput_DOCSTRING +"Inserts data into the YAML document for the PhreeqcRM method +SetNthSelectedOutput. When the YAML document is written to file it can +be processed by the method InitializeYAML to initialize a PhreeqcRM +instance. + +SetNthSelectedOutput specifies the current selected output by sequence +number. The user may define multiple SELECTED_OUTPUT data blocks for the +workers. A user number is specified for each data block, and the blocks +are stored in user-number order. The value of the argument n selects the +sequence number of the SELECTED_OUTPUT definition that will be used for +selected-output operations. + +Args: + n (int): Sequence number of the SELECTED_OUTPUT data block that is + to be used." +%enddef +%feature("docstring") YAMLPhreeqcRM::YAMLSetNthSelectedOutput YAMLSetNthSelectedOutput_DOCSTRING + + +%define YAMLSetPartitionUZSolids_DOCSTRING +"Inserts data into the YAML document for the PhreeqcRM method +SetPartitionUZSolids. When the YAML document is written to file it can +be processed by the method InitializeYAML to initialize a PhreeqcRM +instance. + +SetPartitionUZSolids sets the property for partitioning solids between +the saturated and unsaturated parts of a partially saturated cell. + +The option is intended to be used by saturated-only flow codes that +allow a variable water table. The value has meaning only when +saturations less than 1.0 are encountered. The partially saturated cells +may have a small water-to-rock ratio that causes reactions to proceed +differently relative to fully saturated cells. By setting +SetPartitionUZSolids to true, the amounts of solids and gases are +partioned according to the saturation. If a cell has a saturation of +0.5, then the water interacts with only half of the solids and gases; +the other half is unreactive until the water table rises. As the +saturation in a cell varies, solids and gases are transferred between +the saturated and unsaturated (unreactive) reservoirs of the cell. +Unsaturated-zone flow and transport codes will probably use the default +(false), which assumes all gases and solids are reactive regardless of +saturation. + +Args: + tf (Boolean): True, the fraction of solids and gases available for + reaction is equal to the saturation; False (default), all solids and + gases are reactive regardless of saturation." +%enddef +%feature("docstring") YAMLPhreeqcRM::YAMLSetPartitionUZSolids YAMLSetPartitionUZSolids_DOCSTRING + + +%define YAMLSetPorosity_DOCSTRING +"Inserts data into the YAML document for the PhreeqcRM method +SetPorosity. When the YAML document is written to file it can be +processed by the method InitializeYAML to initialize a PhreeqcRM +instance. + +SetPorosity sets the porosity for each reaction cell. The volume of +water in a reaction cell is the product of porosity, saturation +(SetSaturation), and representative volume (SetRepresentativeVolume). + +Args: + por (float list, numpy.ndarray, or tuple): Vector of porosities, unitless. + Size of vector is nxyz, where nxyz is the number of grid cells in + the user's model." +%enddef +%feature("docstring") YAMLPhreeqcRM::YAMLSetPorosity YAMLSetPorosity_DOCSTRING + + +%define YAMLSetPressure_DOCSTRING +"Inserts data into the YAML document for the PhreeqcRM method +SetPressure. When the YAML document is written to file it can be +processed by the method InitializeYAML to initialize a PhreeqcRM +instance. + +SetPressure sets the pressure for each reaction cell. Pressure effects +are considered only in three of the databases distributed with +PhreeqcRM: phreeqc.dat, Amm.dat, and pitzer.dat. + +Args: + p (float list, numpy.ndarray, or tuple): Vector of pressures, in atm. Size of + vector is nxyz, where nxyz is the number of grid cells in the user's model." +%enddef +%feature("docstring") YAMLPhreeqcRM::YAMLSetPressure YAMLSetPressure_DOCSTRING + + +%define YAMLSetPrintChemistryMask_DOCSTRING +"Inserts data into the YAML document for the PhreeqcRM method +SetPrintChemistryMask. When the YAML document is written to file it can +be processed by the method InitializeYAML to initialize a PhreeqcRM +instance. + +SetPrintChemistryMask enables or disables detailed output for each +reaction cell. Printing for a reaction cell will occur only when the +printing is enabled with SetPrintChemistryOn and the cell_mask value is +1. + +Args: + cell_mask (int list, numpy.ndarray, or tuple): Vector of integers. Size of + vector is nxyz, where nxyz is the number of grid cells in the user's + model. A value of 0 will disable printing detailed output for the cell; + a value of 1 will enable printing detailed output for a cell." +%enddef +%feature("docstring") YAMLPhreeqcRM::YAMLSetPrintChemistryMask YAMLSetPrintChemistryMask_DOCSTRING + + +%define YAMLSetPrintChemistryOn_DOCSTRING +"Inserts data into the YAML document for the PhreeqcRM method +SetPrintChemistryOn. When the YAML document is written to file it can be +processed by the method InitializeYAML to initialize a PhreeqcRM +instance. + +SetPrintChemistryOn sets the property that enables or disables printing +detailed output from reaction calculations to the output file for a set +of cells defined by SetPrintChemistryMask. The detailed output prints +all of the output typical of a PHREEQC reaction calculation, which +includes solution descriptions and the compositions of all other +reactants. The output can be several hundred lines per cell, which can +lead to a very large output file (prefix.chem.txt opened by the method +OpenFiles). For the worker instances, the output can be limited to a set +of cells (method SetPrintChemistryMask) and, in general, the amount of +information printed can be limited by use of options in the PRINT data +block of PHREEQC (applied by using methods RunFile or RunString). +Printing the detailed output for the workers is generally used only for +debugging, and PhreeqcRM will run significantly faster when printing +detailed output for the workers is disabled. + +Args: + workers (Boolean): True, enable detailed printing in the worker + instances; False, disable detailed printing in the worker + instances. + initial_phreeqc (Boolean): True, enable detailed printing in the + InitialPhreeqc instance; False, disable detailed printing in the + InitialPhreeqc instance. + utility (Boolean): True, enable detailed printing in the Utility + instance; False, disable detailed printing in the Utility + instance." +%enddef +%feature("docstring") YAMLPhreeqcRM::YAMLSetPrintChemistryOn YAMLSetPrintChemistryOn_DOCSTRING + + +%define YAMLSetRebalanceByCell_DOCSTRING +"Inserts data into the YAML document for the PhreeqcRM method +SetRebalanceByCell. When the YAML document is written to file it can be +processed by the method InitializeYAML to initialize a PhreeqcRM +instance. + +SetRebalanceByCell sets the load-balancing algorithm. PhreeqcRM attempts +to rebalance the load of each thread or process such that each thread or +process takes the same amount of time to run its part of a RunCells +calculation. Two algorithms are available; one uses individual times for +each cell and accounts for cells that were not run because saturation +was zero (default), and the other assigns an average time to all cells. +The methods are similar, but limited testing indicates the default +method performs better. + +Args: + tf (Boolean): True, indicates individual cell times are used in +rebalancing; False, indicates average times are used in rebalancing." +%enddef +%feature("docstring") YAMLPhreeqcRM::YAMLSetRebalanceByCell YAMLSetRebalanceByCell_DOCSTRING + + +%define YAMLSetRebalanceFraction_DOCSTRING +"Inserts data into the YAML document for the PhreeqcRM method +SetRebalanceFraction. When the YAML document is written to file it can +be processed by the method InitializeYAML to initialize a PhreeqcRM +instance. + +SetRebalanceFraction sets the fraction of cells that are transferred +among threads or processes when rebalancing. PhreeqcRM attempts to +rebalance the load of each thread or process such that each thread or +process takes the same amount of time to run its part of a RunCells +calculation. The rebalancing transfers cell calculations among threads +or processes to try to achieve an optimum balance. SetRebalanceFraction +adjusts the calculated optimum number of cell transfers by a fraction +from 0 to 1.0 to determine the actual number of cell transfers. A value +of zero eliminates load rebalancing. A value less than 1.0 is suggested +to slow the approach to the optimum cell distribution and avoid possible +oscillations when too many cells are transferred at one iteration, +requiring reverse transfers at the next iteration. Default is 0.5. + +Args: + f (float): Fraction from 0.0 to 1.0." +%enddef +%feature("docstring") YAMLPhreeqcRM::YAMLSetRebalanceFraction YAMLSetRebalanceFraction_DOCSTRING + + +%define YAMLSetRepresentativeVolume_DOCSTRING +"Inserts data into the YAML document for the PhreeqcRM method +SetRepresentativeVolume. When the YAML document is written to file it +can be processed by the method InitializeYAML to initialize a PhreeqcRM +instance. + +SetRepresentativeVolume sets the representative volume of each reaction +cell. By default the representative volume of each reaction cell is 1 +liter. The volume of water in a reaction cell is determined by the +product of the representative volume, the porosity (SetPorosity), and +the saturation (SetSaturation). The numerical method of PHREEQC is more +robust if the water volume for a reaction cell is within a couple orders +of magnitude of 1.0. Small water volumes caused by small porosities and +(or) small saturations (and (or) small representative volumes) may cause +non-convergence of the numerical method. In these cases, a larger +representative volume may help. Note that increasing the representative +volume also increases the number of moles of the reactants in the +reaction cell (minerals, surfaces, exchangers, and others), which are +defined as moles per representative volume. SetRepresentativeVolume +should be called before initial conditions are defined for the reaction +cells. + +Args: + rv (float list, numpy.ndarray, or tuple): Vector of representative volumes, + in liters. Size of array is nxyz, where nxyz is the + number of grid cells in the user's model." +%enddef +%feature("docstring") YAMLPhreeqcRM::YAMLSetRepresentativeVolume YAMLSetRepresentativeVolume_DOCSTRING + + +%define YAMLSetSaturation_DOCSTRING +"Inserts data into the YAML document for the PhreeqcRM method +SetSaturation. When the YAML document is written to file it can be +processed by the method InitializeYAML to initialize a PhreeqcRM +instance. + +SetSaturation sets the saturation of each reaction cell. Saturation is a +fraction ranging from 0 to 1. The volume of water in a cell is the +product of porosity (SetPorosity), saturation (SetSaturation), and +representative volume (SetRepresentativeVolume). As a result of a +reaction calculation, solution properties (density and volume) will +change; the databases phreeqc.dat, Amm.dat, and pitzer.dat have the +molar volume data to calculate these changes. The methods GetDensity, +GetSolutionVolume, and GetSaturation can be used to account for these +changes in the succeeding transport calculation. + +Args: + sat (float list, numpy.ndarray, or tuple): Vector of saturations, unitless. + Size of vector is nxyz, where nxyz is the number of grid cells in + the user's model." +%enddef +%feature("docstring") YAMLPhreeqcRM::YAMLSetSaturation YAMLSetSaturation_DOCSTRING + + +%define YAMLSetScreenOn_DOCSTRING +"Inserts data into the YAML document for the PhreeqcRM method +SetScreenOn. When the YAML document is written to file it can be +processed by the method InitializeYAML to initialize a PhreeqcRM +instance. + +SetScreenOn sets the property that controls whether messages are written +to the screen. Messages include information about rebalancing during +RunCells, and any messages written with ScreenMessage. + +Args: + tf (Boolean): True, enable screen messages; False, disable screen messages." +%enddef +%feature("docstring") YAMLPhreeqcRM::YAMLSetScreenOn YAMLSetScreenOn_DOCSTRING + + +%define YAMLSetSelectedOutputOn_DOCSTRING +"Inserts data into the YAML document for the PhreeqcRM method +SetSelectedOutputOn. When the YAML document is written to file it can be +processed by the method InitializeYAML to initialize a PhreeqcRM +instance. + +SetSelectedOutputOn sets the property that controls whether +selected-output results are available to be retrieved with +GetSelectedOutput. True indicates that selected-output results will be +accumulated during RunCells and can be retrieved with GetSelectedOutput; +False indicates that selected-output results will not be accumulated +during RunCells. + +Args: + tf (Boolean): True, enable selected output; False, disable selected + output." +%enddef +%feature("docstring") YAMLPhreeqcRM::YAMLSetSelectedOutputOn YAMLSetSelectedOutputOn_DOCSTRING + + +%define YAMLSetSpeciesSaveOn_DOCSTRING +"Inserts data into the YAML document for the PhreeqcRM method +SetSpeciesSaveOn. When the YAML document is written to file it can be +processed by the method InitializeYAML to initialize a PhreeqcRM +instance. + +SetSpeciesSaveOn sets the value of the species-save property. This +method enables or disables use of PhreeqcRM with +multicomponent-diffusion transport calculations. By default, +concentrations of aqueous species are not saved. Setting the +species-save property to true allows aqueous species concentrations to +be retrieved with GetSpeciesConcentrations, and solution compositions to +be set with SpeciesConcentrations2Module. SetSpeciesSaveOn must be +called before calls to FindComponents. + +Args: + save_on (Boolean): True indicates species concentrations are saved; + False indicates species concentrations are not saved." +%enddef +%feature("docstring") YAMLPhreeqcRM::YAMLSetSpeciesSaveOn YAMLSetSpeciesSaveOn_DOCSTRING + + +%define YAMLSetTemperature_DOCSTRING +"Inserts data into the YAML document for the PhreeqcRM method +SetTemperature. When the YAML document is written to file it can be +processed by the method InitializeYAML to initialize a PhreeqcRM +instance. + +SetTemperature sets the temperature for each reaction cell. If +SetTemperature is not called, worker solutions will have temperatures as +defined by initial conditions (InitialPhreeqc2Module and +InitialPhreeqcCell2Module). + +Args: + t (float list, numpy.ndarray, or tuple): Vector of temperatures, in degrees C. + Size of vector is nxyz, where nxyz is the number of grid cells in the user's + model." +%enddef +%feature("docstring") YAMLPhreeqcRM::YAMLSetTemperature YAMLSetTemperature_DOCSTRING + + +%define YAMLSetTime_DOCSTRING +"Inserts data into the YAML document for the PhreeqcRM method SetTime. +When the YAML document is written to file it can be processed by the +method InitializeYAML to initialize a PhreeqcRM instance. + +SetTime sets current simulation time for the reaction module. + +Args: + time (float): Current simulation time, in seconds." +%enddef +%feature("docstring") YAMLPhreeqcRM::YAMLSetTime YAMLSetTime_DOCSTRING + + +%define YAMLSetTimeConversion_DOCSTRING +"Inserts data into the YAML document for the PhreeqcRM method +SetTimeConversion. When the YAML document is written to file it can be +processed by the method InitializeYAML to initialize a PhreeqcRM +instance. + +SetTimeConversion Set a factor to convert from seconds to user time +units. Factor times seconds produces user time units that is used in +some PhreeqcRM printing. + +Args: + conv_factor (float): Factor to convert seconds to user time units." +%enddef +%feature("docstring") YAMLPhreeqcRM::YAMLSetTimeConversion YAMLSetTimeConversion_DOCSTRING + + +%define YAMLSetTimeStep_DOCSTRING +"Inserts data into the YAML document for the PhreeqcRM method +SetTimeStep. When the YAML document is written to file it can be +processed by the method InitializeYAML to initialize a PhreeqcRM +instance. + +SetTimeStep sets current time step for the reaction module. This is the +length of time over which kinetic reactions are integrated. + +Args: + time_step (float): Time step, in seconds." +%enddef +%feature("docstring") YAMLPhreeqcRM::YAMLSetTimeStep YAMLSetTimeStep_DOCSTRING + + +%define YAMLSetUnitsExchange_DOCSTRING +"Inserts data into the YAML document for the PhreeqcRM method +SetUnitsExchange. When the YAML document is written to file it can be +processed by the method InitializeYAML to initialize a PhreeqcRM +instance. + +SetUnitsExchange sets input units for exchangers. In PHREEQC input, +exchangers are defined by moles of exchange sites (Mp). +SetUnitsExchange specifies how the number of moles of exchange sites in +a reaction cell (Mc) is calculated from the input value (Mp). + +Options are 0, Mp is mol/L of RV (default), Mc = Mp*RV, where RV is +the representative volume (SetRepresentativeVolume); 1, Mp is mol/L of +water in the RV, Mc = Mp*P*RV, where P is porosity (SetPorosity); or 2, +Mp is mol/L of rock in the RV, Mc = Mp*(1-P)*RV. + +If a single EXCHANGE definition is used for cells with different +initial porosity, the three options scale quite differently. For option +0, the number of moles of exchangers will be the same regardless of +porosity. For option 1, the number of moles of exchangers will be vary +directly with porosity and inversely with rock volume. For option 2, +the number of moles of exchangers will vary directly with rock volume +and inversely with porosity. + +Args: + option (int): Units option for exchangers: 0, 1, or 2." +%enddef +%feature("docstring") YAMLPhreeqcRM::YAMLSetUnitsExchange YAMLSetUnitsExchange_DOCSTRING + + +%define YAMLSetUnitsGasPhase_DOCSTRING +"Inserts data into the YAML document for the PhreeqcRM method +SetUnitsGasPhase. When the YAML document is written to file it can be +processed by the method InitializeYAML to initialize a PhreeqcRM +instance. + +SetUnitsGasPhase sets input units for gas phases. In PHREEQC input, gas +phases are defined by moles of component gases (Mp). SetUnitsGasPhase +specifies how the number of moles of component gases in a reaction cell +(Mc) is calculated from the input value (Mp). + +Options are 0, Mp is mol/L of RV (default), Mc = Mp*RV, where RV is the +representative volume (SetRepresentativeVolume); 1, Mp is mol/L of +water in the RV, Mc = Mp*P*RV, where P is porosity (SetPorosity); or 2, +Mp is mol/L of rock in the RV, Mc = Mp*(1-P)*RV. + +If a single GAS_PHASE definition is used for cells with different +initial porosity, the three options scale quite differently. For option +0, the number of moles of a gas component will be the same regardless +of porosity. For option 1, the number of moles of a gas component will +be vary directly with porosity and inversely with rock volume. For +option 2, the number of moles of a gas component will vary directly +with rock volume and inversely with porosity. + +Args: + option (int): Units option for gas phases: 0, 1, or 2." +%enddef +%feature("docstring") YAMLPhreeqcRM::YAMLSetUnitsGasPhase YAMLSetUnitsGasPhase_DOCSTRING + + +%define YAMLSetUnitsKinetics_DOCSTRING +"Inserts data into the YAML document for the PhreeqcRM method +SetUnitsKinetics. When the YAML document is written to file it can be +processed by the method InitializeYAML to initialize a PhreeqcRM +instance. + +SetUnitsKinetics sets input units for kinetic reactants. + +In PHREEQC input, kinetics are defined by moles of kinetic reactants +(Mp). SetUnitsKinetics specifies how the number of moles of kinetic +reactants in a reaction cell (Mc) is calculated from the input value +(Mp). + +Options are 0, Mp is mol/L of RV (default), Mc = Mp*RV, where RV is the +representative volume (SetRepresentativeVolume); 1, Mp is mol/L of +water in the RV, Mc = Mp*P*RV, where P is porosity (SetPorosity); or 2, +Mp is mol/L of rock in the RV, Mc = Mp*(1-P)*RV. + +If a single KINETICS definition is used for cells with different +initial porosity, the three options scale quite differently. For option +0, the number of moles of kinetic reactants will be the same regardless +of porosity. For option 1, the number of moles of kinetic reactants +will be vary directly with porosity and inversely with rock volume. For +option 2, the number of moles of kinetic reactants will vary directly +with rock volume and inversely with porosity. + +Note that the volume of water in a cell in the reaction module is equal +to the product of porosity (SetPorosity), the saturation +(SetSaturation), and representative volume (SetRepresentativeVolume), +which is usually less than 1 liter. It is important to write the RATES +definitions for homogeneous (aqueous) kinetic reactions to account for +the current volume of water, often by calculating the rate of reaction +per liter of water and multiplying by the volume of water (Basic +function SOLN_VOL). + +Rates that depend on surface area of solids, are not dependent on the +volume of water. However, it is important to get the correct surface +area for the kinetic reaction. To scale the surface area with the +number of moles, the specific area (m^2 per mole of reactant) can be +defined as a parameter (KINETICS; -parm), which is multiplied by the +number of moles of reactant (Basic function M) in RATES to obtain the +surface area. + +Args: + option (int): Units option for kinetic reactants: 0, 1, or 2." +%enddef +%feature("docstring") YAMLPhreeqcRM::YAMLSetUnitsKinetics YAMLSetUnitsKinetics_DOCSTRING + + +%define YAMLSetUnitsPPassemblage_DOCSTRING +"Inserts data into the YAML document for the PhreeqcRM method +SetUnitsPPassemblage. When the YAML document is written to file it can +be processed by the method InitializeYAML to initialize a PhreeqcRM +instance. + +SetUnitsPPassemblage sets input units for pure phase assemblages +(equilibrium phases). In PHREEQC input, equilibrium phases are defined +by moles of each phase (Mp). SetUnitsPPassemblage specifies how the +number of moles of phases in a reaction cell (Mc) is calculated from +the input value (Mp). + +Options are 0, Mp is mol/L of RV (default), Mc = Mp*RV, where RV is the +representative volume (SetRepresentativeVolume); 1, Mp is mol/L of +water in the RV, Mc = Mp*P*RV, where P is porosity (SetPorosity); or 2, +Mp is mol/L of rock in the RV, Mc = Mp*(1-P)*RV. + +If a single EQUILIBRIUM_PHASES definition is used for cells with +different initial porosity, the three options scale quite differently. +For option 0, the number of moles of a mineral will be the same +regardless of porosity. For option 1, the number of moles of a mineral +will be vary directly with porosity and inversely with rock volume. For +option 2, the number of moles of a mineral will vary directly with rock +volume and inversely with porosity. + +Args: + option (int): Units option for equilibrium phases: 0, 1, or 2." +%enddef +%feature("docstring") YAMLPhreeqcRM::YAMLSetUnitsPPassemblage YAMLSetUnitsPPassemblage_DOCSTRING + + +%define YAMLSetUnitsSolution_DOCSTRING +"Inserts data into the YAML document for the PhreeqcRM method +SetUnitsSolution. When the YAML document is written to file it can be +processed by the method InitializeYAML to initialize a PhreeqcRM +instance. + +SetUnitsSolution sets solution concentration units used by the +transport model. Options are 1, mg/L; 2 mol/L; or 3, mass fraction, +kg/kgs. PHREEQC defines solutions by the number of moles of each +element in the solution. + +To convert from mg/L to moles of element in the representative volume +of a reaction cell, mg/L is converted to mol/L and multiplied by the +solution volume, which is the product of porosity (SetPorosity), +saturation (SetSaturation), and representative volume +(SetRepresentativeVolume). To convert from mol/L to moles of element in +the representative volume of a reaction cell, mol/L is multiplied by +the solution volume. To convert from mass fraction to moles of element +in the representative volume of a reaction cell, kg/kgs is converted to +mol/kgs, multiplied by density (SetDensity) and multiplied by the +solution volume. + +To convert from moles +of element in the representative volume of a reaction cell to mg/L, the +number of moles of an element is divided by the +solution volume resulting in mol/L, and then converted to mg/L. +To convert from moles of element in a cell to mol/L, the number of +moles of an element is divided by the solution volume resulting in +mol/L. To convert from moles of element in a cell to mass fraction, the +number of moles of an element is converted to kg and divided by the +total mass of the solution. Two options are available for the volume +and mass of solution that are used in converting to transport +concentrations: (1) the volume and mass of solution are calculated by +PHREEQC, or (2) the volume of solution is the product of porosity +(SetPorosity), saturation (SetSaturation), and representative volume +(SetRepresentativeVolume), and the mass of solution is volume times +density as defined by SetDensity. Which option is used is determined by +UseSolutionDensityVolume. + +Args: + option (int): Units option for solutions: 1, 2, or 3." +%enddef +%feature("docstring") YAMLPhreeqcRM::YAMLSetUnitsSolution YAMLSetUnitsSolution_DOCSTRING + + +%define YAMLSetUnitsSSassemblage_DOCSTRING +"Inserts data into the YAML document for the PhreeqcRM method +SetUnitsSSassemblage. When the YAML document is written to file it can +be processed by the method InitializeYAML to initialize a PhreeqcRM +instance. + +SetUnitsSSassemblage sets input units for solid-solution assemblages. +In PHREEQC, solid solutions are defined by moles of each component +(Mp). SetUnitsSSassemblage specifies how the number of moles of +solid-solution components in a reaction cell (Mc) is calculated from +the input value (Mp). + +Options are 0, Mp is mol/L of RV (default), Mc = Mp*RV, where RV is the +representative volume (SetRepresentativeVolume); 1, Mp is mol/L of +water in the RV, Mc = Mp*P*RV, where P is porosity (SetPorosity); or 2, +Mp is mol/L of rock in the RV, Mc = Mp*(1-P)*RV. + +If a single SOLID_SOLUTION definition is used for cells with different +initial porosity, the three options scale quite differently. For option +0, the number of moles of a solid-solution component will be the same +regardless of porosity. For option 1, the number of moles of a +solid-solution component will be vary directly with porosity and +inversely with rock volume. For option 2, the number of moles of a +solid-solution component will vary directly with rock volume and +inversely with porosity. + +Args: + option (int): Units option for solid solutions: 0, 1, or 2." +%enddef +%feature("docstring") YAMLPhreeqcRM::YAMLSetUnitsSSassemblage YAMLSetUnitsSSassemblage_DOCSTRING + + +%define YAMLSetUnitsSurface_DOCSTRING +"Inserts data into the YAML document for the PhreeqcRM method +SetUnitsSurface. When the YAML document is written to file it can be +processed by the method InitializeYAML to initialize a PhreeqcRM +instance. + +SetUnitsSurface sets input units for surfaces. In PHREEQC input, +surfaces are defined by moles of surface sites (Mp). SetUnitsSurface +specifies how the number of moles of surface sites in a reaction cell +(Mc) is calculated from the input value (Mp). + +Options are 0, Mp is mol/L of RV (default), Mc = Mp*RV, where RV is +the representative volume (SetRepresentativeVolume); 1, Mp is mol/L of +water in the RV, Mc = Mp*P*RV, where P is porosity (SetPorosity); or 2, +Mp is mol/L of rock in the RV, Mc = Mp*(1-P)*RV. + +If a single SURFACE definition is used for cells with different initial +porosity, the three options scale quite differently. For option 0, the +number of moles of surface sites will be the same regardless of +porosity. For option 1, the number of moles of surface sites will be +vary directly with porosity and inversely with rock volume. For option +2, the number of moles of surface sites will vary directly with rock +volume and inversely with porosity. + +Args: + option (int): Units option for surfaces: 0, 1, or 2." +%enddef +%feature("docstring") YAMLPhreeqcRM::YAMLSetUnitsSurface YAMLSetUnitsSurface_DOCSTRING + + +%define YAMLSpeciesConcentrations2Module_DOCSTRING +"Inserts data into the YAML document for the PhreeqcRM method +SpeciesConcentrations2Module. When the YAML document is written to file +it can be processed by the method InitializeYAML to initialize a +PhreeqcRM instance. + +SpeciesConcentrations2Module sets solution concentrations in the +reaction cells based on the vector of aqueous species concentrations +(species_conc). This method is intended for use with +multicomponent-diffusion transport calculations, and SetSpeciesSaveOn +must be set to true. The list of aqueous species is determined by +FindComponents and includes all aqueous species that can be made from +the set of components. The method determines the total concentration of +a component by summing the molarities of the individual species times +the stoichiometric coefficient of the element in each species. Solution +compositions in the reaction cells are updated with these component +concentrations. Usually, accurate concentrations will not be known to +use YAMLSetSpeciesConcentrations during initialization. + +Args: + species_conc (float list, numpy.ndarray, or tuple): Vector of aqueous species + concentrations. Dimension of the array is nspecies times nxyz, + where nspecies is the number of aqueous species, and nxyz is the + number of user grid cells. Concentrations are moles per liter." +%enddef +%feature("docstring") YAMLPhreeqcRM::YAMLSpeciesConcentrations2Module YAMLSpeciesConcentrations2Module_DOCSTRING + + +%define YAMLStateSave_DOCSTRING +"Inserts data into the YAML document for the PhreeqcRM method +StateSave. When the YAML document is written to file it can be +processed by the method InitializeYAML to initialize a PhreeqcRM +instance. + +StateSave saves the state of the chemistry in all model cells, +including SOLUTIONs, EQUILIBRIUM_PHASES, EXCHANGEs, GAS_PHASEs, +KINETICS, SOLID_SOLUTIONs, and SURFACEs. Although not generally used, +MIXes, REACTIONs, REACTION_PRESSUREs, and REACTION_TEMPERATUREs will be +saved for each cell, if they have been defined in the worker IPhreeqc +instances. The distribution of cells among the workers and the +chemistry of fully or partially unsaturated cells are also saved. The +state is saved in memory; use DumpModule to save the state to file. +PhreeqcRM can be reset to this state by using StateApply. A state is +identified by an integer, and multiple states can be saved. + +Args: + istate (int): Integer identifying the state that is saved." +%enddef +%feature("docstring") YAMLPhreeqcRM::YAMLStateSave YAMLStateSave_DOCSTRING + + +%define YAMLStateApply_DOCSTRING +"Inserts data into the YAML document for the PhreeqcRM method +StateApply. When the YAML document is written to file it can be +processed by the method InitializeYAML to initialize a PhreeqcRM +instance. + +StateApply resets the state of the module to a state previously saved +with StateSave. The chemistry of all model cells are reset, including +SOLUTIONs, EQUILIBRIUM_PHASES, EXCHANGEs, GAS_PHASEs, KINETICS, +SOLID_SOLUTIONs, and SURFACEs. MIXes, REACTIONs, REACTION_PRESSUREs, +and REACTION_TEMPERATUREs will be reset for each cell, if they were +defined in the worker IPhreeqc instances at the time the state was +saved. The distribution of cells among the workers and the chemistry of +fully or partially unsaturated cells are also reset to the saved state. +The state to be applied is identified by an integer. + +Args: + istate (int): Integer identifying the state that is to be applied." +%enddef +%feature("docstring") YAMLPhreeqcRM::YAMLStateApply YAMLStateApply_DOCSTRING + + +%define YAMLStateDelete_DOCSTRING "Inserts data into the YAML document +for the PhreeqcRM method StateDelete. When the YAML document is written +to file it can be processed by the method InitializeYAML to initialize +a PhreeqcRM instance. + +StateDelete deletes a state previously saved with StateSave. + +Args: + istate (int): Integer identifying the state that is to be deleted." +%enddef +%feature("docstring") YAMLPhreeqcRM::YAMLStateDelete YAMLStateDelete_DOCSTRING + + +%define YAMLUseSolutionDensityVolume_DOCSTRING +"Inserts data into the YAML document for the PhreeqcRM method +UseSolutionDensityVolume. When the YAML document is written to file it +can be processed by the method InitializeYAML to initialize a PhreeqcRM +instance. + +UseSolutionDensityVolume determines the volume and density to use when +converting from the reaction-cell concentrations to transport +concentrations (GetConcentrations). Two options are available to +convert concentration units: (1) the density and solution volume +calculated by PHREEQC are used, or (2) the specified density +(SetDensity) and solution volume are determined by the product of +saturation (SetSaturation), porosity (SetPorosity), and representative +volume (SetRepresentativeVolume). Transport models that consider +density-dependent flow will probably use the PHREEQC-calculated density +and solution volume (default), whereas transport models that assume +constant-density flow will probably use specified values of density and +solution volume. Only the following databases distributed with +PhreeqcRM have molar-volume information needed to accurately calculate +density and solution volume: phreeqc.dat, Amm.dat, and pitzer.dat. +Density is only used when converting to or from transport units of mass +fraction. + +Args: + tf (Boolean): True indicates that the solution density and volume + as calculated by PHREEQC will be used to calculate concentrations. + False indicates that the solution density set by SetDensity and the + volume determined by the product of SetSaturation, SetPorosity, + and SetRepresentativeVolume, will be used to calculate + concentrations retrieved by GetConcentrations." +%enddef +%feature("docstring") YAMLPhreeqcRM::YAMLUseSolutionDensityVolume YAMLUseSolutionDensityVolume_DOCSTRING + + +%define YAMLWarningMessage_DOCSTRING +"Inserts data into the YAML document for the PhreeqcRM method +WarningMessage. When the YAML document is written to file it can be +processed by the method InitializeYAML to initialize a PhreeqcRM +instance. + +WarningMessage prints a warning message to the screen and the log file. + +Args: + warnstr (string): String to be printed." +%enddef +%feature("docstring") YAMLPhreeqcRM::YAMLWarningMessage YAMLWarningMessage_DOCSTRING + diff --git a/src/swig/python/yamlphreeqcrm.py b/src/swig/python/yamlphreeqcrm.py new file mode 100644 index 000000000..ff14da37d --- /dev/null +++ b/src/swig/python/yamlphreeqcrm.py @@ -0,0 +1,202 @@ +import numpy as np +import yaml as yaml +import sys +""" + Helper module for generating a YAML file for + initializing a PhreeqcRM instance. The YAML + file is likely to be written by a GUI or preprocessor, + and the PhreeqcRM method InitializeYAML can be + used to execute the methods recorded in the YAML + file to set properties and initial conditions in + the PhreeqcRM instance. + + Functions that accept a constant vector reference + (const std::vector&) should be callable + with any of the three Python data types, namely + np.ndarray, list, and tuple. + + For example, the porosity can be initialized: + + # numpy.ndarray + porosity = np.full((nxyz,), 0.2) + + # list (using list repetition) + porosity = [0.2] * nxyz + + # list (using list comprehension) + porosity = [0.2 for i in range(nxyz)] + + # tuple (using a generator expression) + porosity = tuple(0.2 for i in range(nxyz)) + + # And used: + nxyz = 20 + nthreads = 3 + phreeqc_rm = phreeqcrm.PhreeqcRM(nxyz, nthreads) + status = phreeqc_rm.SetPorosity(porosity) + + # likewise for integers (const std::vector&) + + Currently functions that take non-const vectors (ie OUT or INOUT) + must use the SWIG wrapped vector class like this: + + c_dbl_vect = phreeqcrm.DoubleVector(nxyz * len(components)) + status = phreeqc_rm.GetConcentrations(c_dbl_vect) +""" + +class YAMLPhreeqcRM(object): + yaml_doc = dict() + + def Clear(self): + yaml_doc = " " + def WriteYAMLDoc(self, file_name): + file = open(file_name, "w") + yaml.dump(self.yaml_doc, file, sort_keys=False) + file.close() + def YAMLCloseFiles(self, void): + self.yaml_doc["CloseFiles"] = "" + def YAMLCreateMapping(self, g2c): + self.yaml_doc["CreateMapping"] = g2c + def YAMLDumpModule(self, dump_on, append): + node = dict() + node["dump_on"] = dump_on + node["append"] = append + self.yaml_doc["DumpModule"] = node + def YAMLFindComponents(self): + self.yaml_doc["FindComponents"] = "" + def YAMLInitialPhreeqc2Module(self, initial_conditions1): + self.yaml_doc["InitialPhreeqc2Module"] = 1 + def YAMLInitialPhreeqc2Module_mix(self, ic1, ic2, f1): + node = dict() + node["ic1"] = ic1 + node["ic2"] = ic2 + node["f1"] = f1 + self.yaml_doc["InitialPhreeqc2Module_mix"] = node + def YAMLInitialPhreeqcCell2Module(self, n, cell_numbers): + node = dict() + node["n"] = n + node["cell_numbers"] = cell_numbers + self.yaml_doc["InitialPhreeqcCell2Module"] = node + def YAMLLoadDatabase(self, database): + self.yaml_doc["LoadDatabase"] = database + def YAMLLogMessage(self, str): + self.yaml_doc["LogMessage"] = str + def YAMLOpenFiles(self): + self.yaml_doc["OpenFiles"] = "" + def YAMLOutputMessage(self, str): + self.yaml_doc["OutputMessage"] = str + def YAMLRunCells(self): + self.yaml_doc["RunCells"] = "" + def YAMLRunFile(self, workers, initial_phreeqc, utility, chemistry_name): + node = dict() + node["workers"] = workers + node["initial_phreeqc"] = initial_phreeqc + node["utility"] = utility + node["chemistry_name"] = chemistry_name + self.yaml_doc["RunFile"] = node + def YAMLRunString(self, workers, initial_phreeqc, utility, input_string): + node = dict() + node["workers"] = workers + node["initial_phreeqc"] = initial_phreeqc + node["utility"] = utility + node["input_string"] = input_string + self.yaml_doc["RunString"] = node + def YAMLScreenMessage(self, str): + self.yaml_doc["ScreenMessage"] = str + def YAMLSetComponentH2O(self, tf): + self.yaml_doc["SetComponentH2O"] = tf + def YAMLSetConcentrations(self, c): + self.yaml_doc["SetConcentrations"] = c + def YAMLSetCurrentSelectedOutputUserNumber(self, n_user): + self.yaml_doc["SetCurrentSelectedOutputUserNumber"] = n_user + def YAMLSetDensity(self, density): + self.yaml_doc["SetDensity"] = density + def YAMLSetDumpFileName(self, dump_name): + self.yaml_doc["SetDumpFileName"] = dump_name + def YAMLSetErrorHandlerMode(self, mode): + self.yaml_doc["SetErrorHandlerMode"] = mode + def YAMLSetErrorOn(self, tf): + self.yaml_doc["SetErrorOn"] = tf + def YAMLSetFilePrefix(self, prefix): + self.yaml_doc["SetFilePrefix"] = prefix + def YAMLSetGasCompMoles(self, gas_moles): + self.yaml_doc["SetGasCompMoles"] = gas_moles + def YAMLSetGasPhaseVolume(self, gas_volume): + self.yaml_doc["SetGasPhaseVolume"] = gas_volume + def YAMLSetGridCellCount(self, n): + self.yaml_doc["SetGridCellCount"] = n + def YAMLSetNthSelectedOutput(self, n): + self.yaml_doc["SetNthSelectedOutput"] = n + def YAMLSetPartitionUZSolids(self, tf): + self.yaml_doc["SetPartitionUZSolids"] = tf + def YAMLSetPorosity(self, por): + self.yaml_doc["SetPorosity"] = por + def YAMLSetPressure(self, p): + self.yaml_doc["SetPressure"] = p + def YAMLSetPrintChemistryMask(self, cell_mask): + self.yaml_doc["SetPrintChemistryMask"] = cell_mask + def YAMLSetPrintChemistryOn(self, workers, initial_phreeqc, utility): + node = dict() + node["workers"] = workers + node["initial_phreeqc"] = initial_phreeqc + node["utility"] = utility + self.yaml_doc["SetPrintChemistryOn"] = node + def YAMLSetRebalanceByCell(self, tf): + self.yaml_doc["SetRebalanceByCell"] = tf + def YAMLSetRebalanceFraction(self, f): + self.yaml_doc["SetRebalanceFraction"] = f + def YAMLSetRepresentativeVolume(self, rv): + self.yaml_doc["SetRepresentativeVolume"] = rv + def YAMLSetSaturation(self, sat): + self.yaml_doc["SetSaturation"] = sat + def YAMLSetScreenOn(self, tf): + self.yaml_doc["SetScreenOn"] = tf + def YAMLSetSelectedOutputOn(self, tf): + self.yaml_doc["SetSelectedOutputOn"] = tf + def YAMLSetSpeciesSaveOn(self, save_on): + self.yaml_doc["SetSpeciesSaveOn"] = save_on + def YAMLSetTemperature(self, t): + self.yaml_doc["SetTemperature"] = t + def YAMLSetTime(self, time): + self.yaml_doc["SetTime"] = time + def YAMLSetTimeConversion(self, conv_factor): + self.yaml_doc["SetTimeConversion"] = conv_factor + def YAMLSetTimeStep(self, time_step): + self.yaml_doc["SetTimeStep"] = time_step + def YAMLSetUnitsExchange(self, option): + self.yaml_doc["SetUnitsExchange"] = option + def YAMLSetUnitsGasPhase(self, option): + self.yaml_doc["SetUnitsGasPhase"] = option + def YAMLSetUnitsKinetics(self, option): + self.yaml_doc["SetUnitsKinetics"] = option + def YAMLSetUnitsPPassemblage(self, option): + self.yaml_doc["SetUnitsPPassemblage"] = option + def YAMLSetUnitsSolution(self, option): + self.yaml_doc["SetUnitsSolution"] = option + def YAMLSetUnitsSSassemblage(self, option): + self.yaml_doc["SetUnitsSSassemblage"] = option + def YAMLSetUnitsSurface(self, option): + self.yaml_doc["SetUnitsSurface"] = option + def YAMLSpeciesConcentrations2Module(self, species_conc): + self.yaml_doc["SpeciesConcentrations2Module"] = species_conc + def YAMLStateSave(self, istate): + self.yaml_doc["StateSave"] = istate + def YAMLStateApply(self, istate): + self.yaml_doc["StateApply"] = istate + def YAMLStateDelete(self, istate): + self.yaml_doc["StateDelete"] = istate + def YAMLUseSolutionDensityVolume(self, tf): + self.yaml_doc["UseSolutionDensityVolume"] = tf + def YAMLWarningMessage(self, warnstr): + self.yaml_doc["WarningMessage"] = warnstr + + +#nxyz = 40 +#yrm = YAMLPhreeqcRM() +#grid2cell = [i for i in range(nxyz)] +#yrm.YAMLCreateMapping(grid2cell) +#yrm.YAMLRunFile(True, True, True, "myrunfile") +#yrm.YAMLSetFilePrefix("myfile") +#print(yrm.yaml_doc) +#yaml.dump(yrm.yaml_doc, sys.stdout, sort_keys=False) +#yrm.WriteYAMLDoc("dumpfile") \ No newline at end of file