mirror of
https://git.gfz-potsdam.de/naaice/poet.git
synced 2025-12-15 20:38:23 +01:00
Merge branch 'add-phreeqcrm' into 'main'
Refactor ChemistryModule and implement PhreeqcRM parallelization See merge request sec34/port!22
This commit is contained in:
commit
881ed1fea9
@ -14,6 +14,8 @@ set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
|
|||||||
include("CMake/POET_Scripts.cmake")
|
include("CMake/POET_Scripts.cmake")
|
||||||
list(APPEND CMAKE_MODULE_PATH "${POET_SOURCE_DIR}/CMake")
|
list(APPEND CMAKE_MODULE_PATH "${POET_SOURCE_DIR}/CMake")
|
||||||
|
|
||||||
|
get_poet_version()
|
||||||
|
|
||||||
# set(GCC_CXX_FLAGS "-D STRICT_R_HEADERS") add_definitions(${GCC_CXX_FLAGS})
|
# set(GCC_CXX_FLAGS "-D STRICT_R_HEADERS") add_definitions(${GCC_CXX_FLAGS})
|
||||||
|
|
||||||
find_package(MPI REQUIRED)
|
find_package(MPI REQUIRED)
|
||||||
|
|||||||
146
README.md
146
README.md
@ -1,10 +1,6 @@
|
|||||||
<!--
|
<!--
|
||||||
Time-stamp: "Last modified 2023-01-19 12:06:10 delucia"
|
Time-stamp: "Last modified 2023-01-19 12:06:10 delucia"
|
||||||
-->
|
-->
|
||||||
|
|
||||||
**Po**tsdamer **R**eactive **T**ransport
|
|
||||||
|
|
||||||
|
|
||||||
# Forked Project
|
# Forked Project
|
||||||
|
|
||||||
*PORT* is a fork of [POET](https://doi.org/10.5281/zenodo.4757913)
|
*PORT* is a fork of [POET](https://doi.org/10.5281/zenodo.4757913)
|
||||||
@ -19,11 +15,20 @@ also applicable for this project.
|
|||||||
POET is a coupled reactive transport simulator implementing a parallel
|
POET is a coupled reactive transport simulator implementing a parallel
|
||||||
architecture and a fast, original MPI-based Distributed Hash Table.
|
architecture and a fast, original MPI-based Distributed Hash Table.
|
||||||
|
|
||||||
|
## Parsed code documentiation
|
||||||
|
|
||||||
|
A parsed version of POET's documentiation can be found at [Gitlab
|
||||||
|
pages](https://sec34.git-pages.gfz-potsdam.de/port).
|
||||||
|
|
||||||
## External Libraries
|
## External Libraries
|
||||||
|
|
||||||
The following external header library is shipped with POET:
|
The following external header library is shipped with POET:
|
||||||
|
|
||||||
- **argh** - https://github.com/adishavit/argh (BSD license)
|
- **argh** - https://github.com/adishavit/argh (BSD license)
|
||||||
|
- **PhreeqcRM** with patches from GFZ -
|
||||||
|
https://www.usgs.gov/software/phreeqc-version-3 -
|
||||||
|
https://git.gfz-potsdam.de/mluebke/phreeqcrm-gfz
|
||||||
|
- **tug** - https://git.gfz-potsdam.de/sec34/tug
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
@ -35,23 +40,18 @@ To compile POET you need several software to be installed:
|
|||||||
- MPI-Implementation (tested with OpenMPI and MVAPICH)
|
- MPI-Implementation (tested with OpenMPI and MVAPICH)
|
||||||
- R language and environment
|
- R language and environment
|
||||||
- CMake 3.9+
|
- CMake 3.9+
|
||||||
|
- *optional*: `doxygen` with `dot` bindings for documentiation
|
||||||
If you want to build documentation during compilation, `doxygen`and
|
|
||||||
`graphviz` must be provided too.
|
|
||||||
|
|
||||||
The following R libraries must then be installed, which will get the
|
The following R libraries must then be installed, which will get the
|
||||||
needed dependencies automatically:
|
needed dependencies automatically:
|
||||||
|
|
||||||
- [devtools](https://www.r-project.org/nosvn/pandoc/devtools.html)
|
|
||||||
- [Rcpp](https://cran.r-project.org/web/packages/Rcpp/index.html)
|
- [Rcpp](https://cran.r-project.org/web/packages/Rcpp/index.html)
|
||||||
- [RInside](https://cran.r-project.org/web/packages/RInside/index.html)
|
- [RInside](https://cran.r-project.org/web/packages/RInside/index.html)
|
||||||
- [RedModRphree](https://git.gfz-potsdam.de/delucia/RedModRphree)
|
|
||||||
- [Rmufits](https://git.gfz-potsdam.de/delucia/Rmufits)
|
|
||||||
|
|
||||||
### Compiling source code
|
### Compiling source code
|
||||||
|
|
||||||
The generation of makefiles is done with CMake. If you obtained POET
|
The generation of makefiles is done with CMake. You should be able to generate
|
||||||
from git, you should be able to generate Makefiles by running
|
Makefiles by running:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
mkdir build && cd build
|
mkdir build && cd build
|
||||||
@ -62,34 +62,21 @@ This will create the directory `build` and processes the CMake files
|
|||||||
and generate Makefiles from it. You're now able to run `make` to start
|
and generate Makefiles from it. You're now able to run `make` to start
|
||||||
build process.
|
build process.
|
||||||
|
|
||||||
If POET was obtained from the official SVN repository or the redmine
|
|
||||||
at <https://redmine.cs.uni-potsdam.de/projects/poet> the branch or tag
|
|
||||||
to be used have to be set via
|
|
||||||
|
|
||||||
```sh
|
|
||||||
mkdir build && cd build
|
|
||||||
cmake -D POET_SET_BRANCH="<BRANCH>" ..
|
|
||||||
```
|
|
||||||
|
|
||||||
where currently available branches/tags are:
|
|
||||||
|
|
||||||
- dev
|
|
||||||
|
|
||||||
If everything went well you'll find the executable at
|
If everything went well you'll find the executable at
|
||||||
`build/src/poet`, but it is recommended to install the POET project
|
`build/app/poet`, but it is recommended to install the POET project
|
||||||
structure to a desired `CMAKE_INSTALL_PREFIX` with `make install`.
|
structure to a desired `CMAKE_INSTALL_PREFIX` with `make install`.
|
||||||
|
|
||||||
During the generation of Makefiles, various options can be specified
|
During the generation of Makefiles, various options can be specified
|
||||||
via `cmake -D <option>=<value> [...]`. Currently there are the
|
via `cmake -D <option>=<value> [...]`. Currently, there are the
|
||||||
following available options:
|
following available options:
|
||||||
|
|
||||||
- **DHT_Debug**=_boolean_ - toggles the output of detailed statistics
|
- **POET_DHT_Debug**=_boolean_ - toggles the output of detailed statistics about
|
||||||
about DHT usage (`cmake -D DHT_Debug=ON`). Defaults to _OFF_.
|
DHT usage. Defaults to _OFF_.
|
||||||
- **BUILD_DOC**=_boolean_ - toggles the generation of documantiation
|
- **POET_ENABLE_TESTING**=_boolean_ - enables small set of unit tests (more to
|
||||||
during compilation process. Defaults to _ON_.
|
come). Defaults to _OFF_.
|
||||||
- _only from svn version:_ **POET_SET_BRANCH**=_string_ - set branch
|
- **POET_USE_PRM_BACKEND**=_bollean_ - use the PhreeqcRM parallelization instead
|
||||||
or tag whose code is used
|
of POET's one. Intended for debugging purposes for modellers.
|
||||||
|
|
||||||
### Example: Build from scratch
|
### Example: Build from scratch
|
||||||
|
|
||||||
Assuming that only the C/C++ compiler, MPI libraries, R runtime
|
Assuming that only the C/C++ compiler, MPI libraries, R runtime
|
||||||
@ -101,9 +88,7 @@ follows:
|
|||||||
$ R
|
$ R
|
||||||
|
|
||||||
# install R dependencies
|
# install R dependencies
|
||||||
> install.packages(c("devtools", "Rcpp", "RInside"))
|
> install.packages(c("Rcpp", "RInside"))
|
||||||
> devtools::install_gitlab("delucia/RedModRphree", host="https://git.gfz-potsdam.de")
|
|
||||||
> devtools::install_gitlab("delucia/Rmufits", host="https://git.gfz-potsdam.de")
|
|
||||||
> q(save="no")
|
> q(save="no")
|
||||||
|
|
||||||
# cd into POET project root
|
# cd into POET project root
|
||||||
@ -124,60 +109,53 @@ POET we **do not recommend** to install to hierarchies like
|
|||||||
The correspondending directory tree would look like this:
|
The correspondending directory tree would look like this:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
.
|
poet
|
||||||
└── poet/
|
├── bin
|
||||||
├── bin/
|
│ └── poet
|
||||||
│ └── poet
|
├── R_lib
|
||||||
├── data/
|
│ └── kin_r_library.R
|
||||||
│ └── SimDol2D.R
|
└── share
|
||||||
├── docs/
|
└── poet
|
||||||
│ └── html/
|
├── bench
|
||||||
│ ├── index.html
|
│ ├── dolo_diffu_inner_large.R
|
||||||
│ └── ...
|
│ ├── dolo_diffu_inner.R
|
||||||
└── R_lib/
|
│ └── dolo_inner.pqi
|
||||||
├── kin_r_library.R
|
└── examples
|
||||||
└── parallel_r_library.R
|
├── dol.pqi
|
||||||
|
├── phreeqc_kin.dat
|
||||||
|
├── SimDol1D_diffu.R
|
||||||
|
└── SimDol2D_diffu.R
|
||||||
```
|
```
|
||||||
|
|
||||||
The R libraries will be loaded at runtime and the paths are hardcoded
|
The R libraries will be loaded at runtime and the paths are hardcoded
|
||||||
absolute paths inside `poet.cpp`. So, if you consider to move
|
absolute paths inside `poet.cpp`. So, if you consider to move
|
||||||
`bin/poet` either change paths of the R source files and recompile
|
`bin/poet` either change paths of the R source files and recompile
|
||||||
POET or also move `R_lib/*` according to the binary.
|
POET or also move `R_lib/*` relative to the binary.
|
||||||
|
|
||||||
To display the generated html documentation just open
|
|
||||||
`docs/html/index.html` with the browser of your choice.
|
|
||||||
|
|
||||||
## Running
|
## Running
|
||||||
|
|
||||||
Before POET is ready to run, a working directory must be created. In
|
|
||||||
this directory you should find the executable file, the R scripts
|
|
||||||
`<POET_ROOT>/R_lib/kin_r_library.R` and
|
|
||||||
`<POET_ROOT>/R_lib/parallel_r_library.R` and the simulation
|
|
||||||
description e.g. `<POET_ROOT>/data/chem_problems/SimDol2D.R`.
|
|
||||||
|
|
||||||
Run POET by `mpirun ./poet <OPTIONS> <SIMFILE> <OUTPUT_DIRECTORY>`
|
Run POET by `mpirun ./poet <OPTIONS> <SIMFILE> <OUTPUT_DIRECTORY>`
|
||||||
where:
|
where:
|
||||||
|
|
||||||
- **OPTIONS** - runtime parameters (explained below)
|
- **OPTIONS** - runtime parameters (explained below)
|
||||||
- **SIMFILE** - simulation described as R script (currently supported:
|
- **SIMFILE** - simulation described as R script (e.g.
|
||||||
`<POET_INSTALL_DIR>/data/SimDol2D.R`)
|
`<POET_INSTALL_DIR>/share/examples/SimDol2D_diffu.R`)
|
||||||
- **OUTPUT_DIRECTORY** - path, where all output of POET should be stored
|
- **OUTPUT_DIRECTORY** - path, where all output of POET should be stored
|
||||||
|
|
||||||
### Runtime options
|
### Runtime options
|
||||||
|
|
||||||
The following parameters can be set:
|
The following parameters can be set:
|
||||||
|
|
||||||
| Option | Value | Description |
|
| Option | Value | Description |
|
||||||
| ------------------------ | ------------ | -------------------------------------------------------------- |
|
|--------------------------|--------------|--------------------------------------------------------------------------------------------------------------------------|
|
||||||
| **--work-package-size=** | _1..n_ | size of work packages (defaults to _5_) |
|
| **--work-package-size=** | _1..n_ | size of work packages (defaults to _5_) |
|
||||||
| **--ignore-result** | | disables store of simulation resuls |
|
| **--ignore-result** | | disables store of simulation resuls |
|
||||||
| **--dht** | | enabling DHT usage (defaults to _OFF_) |
|
| **--dht** | | enabling DHT usage (defaults to _OFF_) |
|
||||||
| **--dht-nolog** | | disabling applying of logarithm before rounding |
|
| **--dht-signif=** | _1..n_ | set rounding to number of significant digits (defaults to _5_) (it is recommended to use `signif_vec` in R input script) |
|
||||||
| **--dht-signif=** | _1..n_ | set rounding to number of significant digits (defaults to _5_) |
|
| **--dht-strategy=** | _0-1_ | change DHT strategy. **NOT IMPLEMENTED YET** (Defaults to _0_) |
|
||||||
| **--dht-strategy=** | _0-1_ | change DHT strategy. **NOT IMPLEMENTED YET** (Defaults to _0_) |
|
| **--dht-size=** | _1-n_ | size of DHT per process involved in megabyte (defaults to _1000 MByte_) |
|
||||||
| **--dht-size=** | _1-n_ | size of DHT per process involved in byte (defaults to _1 GiB_) |
|
| **--dht-snaps=** | _0-2_ | disable or enable storage of DHT snapshots |
|
||||||
| **--dht-snaps=** | _0-2_ | disable or enable storage of DHT snapshots |
|
| **--dht-file=** | `<SNAPSHOT>` | initializes DHT with the given snapshot file |
|
||||||
| **--dht-file=** | `<SNAPSHOT>` | initializes DHT with the given snapshot file |
|
|
||||||
|
|
||||||
#### Additions to `dht-signif`
|
#### Additions to `dht-signif`
|
||||||
|
|
||||||
@ -197,26 +175,26 @@ Following values can be set:
|
|||||||
### Example: Running from scratch
|
### Example: Running from scratch
|
||||||
|
|
||||||
We will continue the above example and start a simulation with
|
We will continue the above example and start a simulation with
|
||||||
`SimDol2D.R`, which is the only simulation supported at this moment.
|
`SimDol2D_diffu.R`. As transport a simple fixed-coefficient diffusion is used.
|
||||||
The required flow velocities snapshots are included in the R package
|
It's a 2D, 100x100 grid, simulating 10 time steps. To start the simulation with
|
||||||
Rmufits. It's a 2D, 50x50 grid, with 20 time steps. To start the
|
4 processes `cd` into your previously installed POET-dir
|
||||||
simulation with 4 processes `cd` into your previously installed
|
`<POET_INSTALL_DIR>/bin` and run:
|
||||||
POET-dir `<POET_INSTALL_DIR>/bin` and run:
|
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
mpirun -n 4 ./poet ../data/SimDol2D.R output
|
mpirun -n 4 ./poet ../share/poet/examples/SimDol2D_diffu.R output
|
||||||
```
|
```
|
||||||
|
|
||||||
After a finished simulation all data generated by POET will be found
|
After a finished simulation all data generated by POET will be found
|
||||||
in the directory `output`.
|
in the directory `output`.
|
||||||
|
|
||||||
You might want to use the DHT to cache previously simulated data and
|
You might want to use the DHT to cache previously simulated data and reuse them
|
||||||
reuse them in further time-steps. Just append `--dht` to the options
|
in further time-steps. Just append `--dht` to the options of POET to activate
|
||||||
of POET to activate the usage of the DHT. The resulting call would
|
the usage of the DHT. Also, after each iteration a DHT snapshot shall be
|
||||||
look like this:
|
produced. This is done by appending the `--dht-snaps=<value>` option. The
|
||||||
|
resulting call would look like this:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
mpirun -n 4 ./poet --dht SimDol2D.R output
|
mpirun -n 4 ./poet --dht --dht-snaps=2 ../share/poet/examples/SimDol2D_diffu.R output
|
||||||
```
|
```
|
||||||
|
|
||||||
## About the usage of MPI_Wtime()
|
## About the usage of MPI_Wtime()
|
||||||
|
|||||||
@ -1,10 +1,14 @@
|
|||||||
get_poet_version()
|
|
||||||
|
|
||||||
configure_file(poet.h.in poet.h)
|
configure_file(poet.h.in poet.h)
|
||||||
|
|
||||||
add_executable(poet poet.cpp)
|
if(POET_USE_PRM_BACKEND)
|
||||||
|
set(poet_SRC poet_prm.cpp)
|
||||||
|
else()
|
||||||
|
set(poet_SRC poet.cpp)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_executable(poet ${poet_SRC})
|
||||||
target_include_directories(poet PUBLIC "${CMAKE_CURRENT_BINARY_DIR}")
|
target_include_directories(poet PUBLIC "${CMAKE_CURRENT_BINARY_DIR}")
|
||||||
target_link_libraries(poet PUBLIC poet_lib MPI::MPI_C)
|
target_link_libraries(poet PUBLIC poet_lib MPI::MPI_CXX)
|
||||||
#target_compile_definitions(poet PRIVATE OMPI_SKIP_MPICXX)
|
#target_compile_definitions(poet PRIVATE OMPI_SKIP_MPICXX)
|
||||||
|
|
||||||
install(TARGETS poet DESTINATION bin)
|
install(TARGETS poet DESTINATION bin)
|
||||||
|
|||||||
262
app/poet.cpp
262
app/poet.cpp
@ -18,11 +18,12 @@
|
|||||||
** Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
** Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "poet/ChemistryModule.hpp"
|
||||||
#include <RInside.h>
|
#include <RInside.h>
|
||||||
#include <Rcpp.h>
|
#include <Rcpp.h>
|
||||||
|
#include <Rcpp/internal/wrap.h>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <poet/ChemSimPar.hpp>
|
#include <cstdlib>
|
||||||
#include <poet/ChemSimSeq.hpp>
|
|
||||||
#include <poet/DiffusionModule.hpp>
|
#include <poet/DiffusionModule.hpp>
|
||||||
#include <poet/Grid.hpp>
|
#include <poet/Grid.hpp>
|
||||||
#include <poet/SimParams.hpp>
|
#include <poet/SimParams.hpp>
|
||||||
@ -39,9 +40,65 @@ using namespace std;
|
|||||||
using namespace poet;
|
using namespace poet;
|
||||||
using namespace Rcpp;
|
using namespace Rcpp;
|
||||||
|
|
||||||
template <class ChemistryInstance>
|
poet::ChemistryModule::SingleCMap DFToHashMap(const Rcpp::DataFrame &df) {
|
||||||
|
std::unordered_map<std::string, double> out_map;
|
||||||
|
vector<string> col_names = Rcpp::as<vector<string>>(df.names());
|
||||||
|
|
||||||
|
for (const auto &name : col_names) {
|
||||||
|
double val = df[name.c_str()];
|
||||||
|
out_map.insert({name, val});
|
||||||
|
}
|
||||||
|
|
||||||
|
return out_map;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_chem_parameters(poet::ChemistryModule &chem, uint32_t wp_size,
|
||||||
|
const std::string &database_path) {
|
||||||
|
chem.SetErrorHandlerMode(1);
|
||||||
|
chem.SetComponentH2O(false);
|
||||||
|
chem.SetRebalanceFraction(0.5);
|
||||||
|
chem.SetRebalanceByCell(true);
|
||||||
|
chem.UseSolutionDensityVolume(false);
|
||||||
|
chem.SetPartitionUZSolids(false);
|
||||||
|
|
||||||
|
// Set concentration units
|
||||||
|
// 1, mg/L; 2, mol/L; 3, kg/kgs
|
||||||
|
chem.SetUnitsSolution(2);
|
||||||
|
// 0, mol/L cell; 1, mol/L water; 2 mol/L rock
|
||||||
|
chem.SetUnitsPPassemblage(1);
|
||||||
|
// 0, mol/L cell; 1, mol/L water; 2 mol/L rock
|
||||||
|
chem.SetUnitsExchange(1);
|
||||||
|
// 0, mol/L cell; 1, mol/L water; 2 mol/L rock
|
||||||
|
chem.SetUnitsSurface(1);
|
||||||
|
// 0, mol/L cell; 1, mol/L water; 2 mol/L rock
|
||||||
|
chem.SetUnitsGasPhase(1);
|
||||||
|
// 0, mol/L cell; 1, mol/L water; 2 mol/L rock
|
||||||
|
chem.SetUnitsSSassemblage(1);
|
||||||
|
// 0, mol/L cell; 1, mol/L water; 2 mol/L rock
|
||||||
|
chem.SetUnitsKinetics(1);
|
||||||
|
|
||||||
|
// Set representative volume
|
||||||
|
std::vector<double> rv;
|
||||||
|
rv.resize(wp_size, 1.0);
|
||||||
|
chem.SetRepresentativeVolume(rv);
|
||||||
|
|
||||||
|
// Set initial porosity
|
||||||
|
std::vector<double> por;
|
||||||
|
por.resize(wp_size, 1);
|
||||||
|
chem.SetPorosity(por);
|
||||||
|
|
||||||
|
// Set initial saturation
|
||||||
|
std::vector<double> sat;
|
||||||
|
sat.resize(wp_size, 1.0);
|
||||||
|
chem.SetSaturation(sat);
|
||||||
|
|
||||||
|
// Load database
|
||||||
|
chem.LoadDatabase(database_path);
|
||||||
|
}
|
||||||
|
|
||||||
inline double RunMasterLoop(SimParams ¶ms, RInside &R, Grid &grid,
|
inline double RunMasterLoop(SimParams ¶ms, RInside &R, Grid &grid,
|
||||||
ChemistryParams &chem_params) {
|
ChemistryParams &chem_params,
|
||||||
|
const GridParams &g_params, uint32_t nxyz_master) {
|
||||||
|
|
||||||
DiffusionModule diffusion(poet::DiffusionParams(R), grid);
|
DiffusionModule diffusion(poet::DiffusionParams(R), grid);
|
||||||
/* Iteration Count is dynamic, retrieving value from R (is only needed by
|
/* Iteration Count is dynamic, retrieving value from R (is only needed by
|
||||||
@ -50,8 +107,31 @@ inline double RunMasterLoop(SimParams ¶ms, RInside &R, Grid &grid,
|
|||||||
|
|
||||||
double sim_time = .0;
|
double sim_time = .0;
|
||||||
|
|
||||||
ChemistryInstance C(params, R, grid);
|
ChemistryModule chem(nxyz_master, params.getNumParams().wp_size,
|
||||||
C.InitModule(chem_params);
|
MPI_COMM_WORLD);
|
||||||
|
set_chem_parameters(chem, nxyz_master, chem_params.database_path);
|
||||||
|
chem.RunInitFile(chem_params.input_script);
|
||||||
|
|
||||||
|
chem.InitializeField(grid.GetTotalCellCount(), DFToHashMap(g_params.init_df));
|
||||||
|
|
||||||
|
if (params.getNumParams().dht_enabled) {
|
||||||
|
chem.SetDHTEnabled(true, params.getNumParams().dht_size_per_process);
|
||||||
|
if (!params.getDHTSignifVector().empty()) {
|
||||||
|
chem.SetDHTSignifVector(params.getDHTSignifVector());
|
||||||
|
}
|
||||||
|
if (!params.getDHTPropTypeVector().empty()) {
|
||||||
|
chem.SetDHTPropTypeVector(params.getDHTPropTypeVector());
|
||||||
|
}
|
||||||
|
if (!params.getDHTFile().empty()) {
|
||||||
|
chem.ReadDHTFile(params.getDHTFile());
|
||||||
|
}
|
||||||
|
if (params.getNumParams().dht_snaps > 0) {
|
||||||
|
chem.SetDHTSnaps(params.getNumParams().dht_snaps, params.getOutDir());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StateMemory *chem_state = grid.RegisterState("state_C", chem.GetPropNames());
|
||||||
|
chem_state->mem = chem.GetField();
|
||||||
/* SIMULATION LOOP */
|
/* SIMULATION LOOP */
|
||||||
|
|
||||||
double dStartTime = MPI_Wtime();
|
double dStartTime = MPI_Wtime();
|
||||||
@ -77,7 +157,14 @@ inline double RunMasterLoop(SimParams ¶ms, RInside &R, Grid &grid,
|
|||||||
|
|
||||||
cout << "CPP: Chemistry" << endl;
|
cout << "CPP: Chemistry" << endl;
|
||||||
|
|
||||||
C.Simulate(dt);
|
chem.SetTimeStep(dt);
|
||||||
|
|
||||||
|
chem.SetField(chem_state->mem);
|
||||||
|
chem.SetTimeStep(dt);
|
||||||
|
chem.RunCells();
|
||||||
|
chem_state->mem = chem.GetField();
|
||||||
|
|
||||||
|
grid.WriteFieldsToR(R);
|
||||||
grid.PreModuleFieldCopy(tick++);
|
grid.PreModuleFieldCopy(tick++);
|
||||||
|
|
||||||
R["req_dt"] = dt;
|
R["req_dt"] = dt;
|
||||||
@ -97,12 +184,50 @@ inline double RunMasterLoop(SimParams ¶ms, RInside &R, Grid &grid,
|
|||||||
<< endl
|
<< endl
|
||||||
<< endl;
|
<< endl;
|
||||||
|
|
||||||
MPI_Barrier(MPI_COMM_WORLD);
|
// MPI_Barrier(MPI_COMM_WORLD);
|
||||||
|
|
||||||
} // END SIMULATION LOOP
|
} // END SIMULATION LOOP
|
||||||
|
|
||||||
R.parseEvalQ("profiling <- list()");
|
R.parseEvalQ("profiling <- list()");
|
||||||
C.End();
|
|
||||||
|
R["simtime_chemistry"] = chem.GetChemistryTime();
|
||||||
|
R.parseEvalQ("profiling$simtime_chemistry <- simtime_chemistry");
|
||||||
|
|
||||||
|
R["chemistry_loop"] = chem.GetMasterLoopTime();
|
||||||
|
R.parseEvalQ("profiling$chemistry_loop <- chemistry_loop");
|
||||||
|
|
||||||
|
R["chemistry_sequential"] = chem.GetMasterSequentialTime();
|
||||||
|
R.parseEvalQ("profiling$simtime_sequential <- chemistry_sequential");
|
||||||
|
|
||||||
|
R["idle_master"] = chem.GetMasterIdleTime();
|
||||||
|
R.parseEvalQ("profiling$idle_master <- idle_master");
|
||||||
|
|
||||||
|
R["idle_worker"] = Rcpp::wrap(chem.GetWorkerIdleTimings());
|
||||||
|
R.parseEvalQ("profiling$idle_worker <- idle_worker");
|
||||||
|
|
||||||
|
R["phreeqc_time"] = Rcpp::wrap(chem.GetWorkerPhreeqcTimings());
|
||||||
|
R.parseEvalQ("profiling$phreeqc <- phreeqc_time");
|
||||||
|
|
||||||
|
R["simtime_transport"] = diffusion.getTransportTime();
|
||||||
|
R.parseEvalQ("profiling$simtime_transport <- simtime_transport");
|
||||||
|
|
||||||
|
// R["phreeqc_count"] = phreeqc_counts;
|
||||||
|
// R.parseEvalQ("profiling$phreeqc_count <- phreeqc_count");
|
||||||
|
|
||||||
|
if (params.getNumParams().dht_enabled) {
|
||||||
|
R["dht_hits"] = Rcpp::wrap(chem.GetWorkerDHTHits());
|
||||||
|
R.parseEvalQ("profiling$dht_hits <- dht_hits");
|
||||||
|
R["dht_miss"] = Rcpp::wrap(chem.GetWorkerDHTMiss());
|
||||||
|
R.parseEvalQ("profiling$dht_miss <- dht_miss");
|
||||||
|
R["dht_evictions"] = Rcpp::wrap(chem.GetWorkerDHTEvictions());
|
||||||
|
R.parseEvalQ("profiling$dht_evictions <- dht_evictions");
|
||||||
|
R["dht_get_time"] = Rcpp::wrap(chem.GetWorkerDHTGetTimings());
|
||||||
|
R.parseEvalQ("profiling$dht_get_time <- dht_get_time");
|
||||||
|
R["dht_fill_time"] = Rcpp::wrap(chem.GetWorkerDHTFillTimings());
|
||||||
|
R.parseEvalQ("profiling$dht_fill_time <- dht_fill_time");
|
||||||
|
}
|
||||||
|
|
||||||
|
chem.MasterLoopBreak();
|
||||||
diffusion.end();
|
diffusion.end();
|
||||||
|
|
||||||
return MPI_Wtime() - dStartTime;
|
return MPI_Wtime() - dStartTime;
|
||||||
@ -119,20 +244,36 @@ int main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
|
MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
|
||||||
|
|
||||||
/*Create custom Communicator with all processes except 0 (the master) for DHT
|
|
||||||
* storage */
|
|
||||||
MPI_Comm dht_comm;
|
|
||||||
|
|
||||||
if (world_rank == 0) {
|
|
||||||
MPI_Comm_split(MPI_COMM_WORLD, MPI_UNDEFINED, world_rank, &dht_comm);
|
|
||||||
} else {
|
|
||||||
MPI_Comm_split(MPI_COMM_WORLD, 1, world_rank, &dht_comm);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (world_rank == 0) {
|
if (world_rank == 0) {
|
||||||
cout << "Running POET in version " << poet_version << endl << endl;
|
cout << "Running POET in version " << poet_version << endl << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (world_rank > 0) {
|
||||||
|
{
|
||||||
|
uint32_t c_size;
|
||||||
|
MPI_Bcast(&c_size, 1, MPI_UINT32_T, 0, MPI_COMM_WORLD);
|
||||||
|
|
||||||
|
char *buffer = new char[c_size + 1];
|
||||||
|
MPI_Bcast(buffer, c_size, MPI_CHAR, 0, MPI_COMM_WORLD);
|
||||||
|
buffer[c_size] = '\0';
|
||||||
|
|
||||||
|
// ChemistryModule worker(nxyz, nxyz, MPI_COMM_WORLD);
|
||||||
|
ChemistryModule worker =
|
||||||
|
poet::ChemistryModule::createWorker(MPI_COMM_WORLD);
|
||||||
|
set_chem_parameters(worker, worker.GetWPSize(), std::string(buffer));
|
||||||
|
|
||||||
|
delete[] buffer;
|
||||||
|
|
||||||
|
worker.WorkerLoop();
|
||||||
|
}
|
||||||
|
|
||||||
|
MPI_Barrier(MPI_COMM_WORLD);
|
||||||
|
cout << "CPP: finished, cleanup of process " << world_rank << endl;
|
||||||
|
MPI_Finalize();
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
/* initialize R runtime */
|
/* initialize R runtime */
|
||||||
RInside R(argc, argv);
|
RInside R(argc, argv);
|
||||||
|
|
||||||
@ -154,42 +295,18 @@ int main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
cout << "CPP: R Init (RInside) on process " << world_rank << endl;
|
cout << "CPP: R Init (RInside) on process " << world_rank << endl;
|
||||||
|
|
||||||
// HACK: we disable master_init and dt_differ propagation here for testing
|
|
||||||
// purposes
|
|
||||||
//
|
|
||||||
bool dt_differ = false;
|
|
||||||
R.parseEvalQ("mysetup <- setup");
|
R.parseEvalQ("mysetup <- setup");
|
||||||
if (world_rank == 0) { // get timestep vector from
|
// if (world_rank == 0) { // get timestep vector from
|
||||||
// grid_init function ... //
|
// grid_init function ... //
|
||||||
std::string master_init_code = "mysetup <- master_init(setup=setup)";
|
std::string master_init_code = "mysetup <- master_init(setup=setup)";
|
||||||
R.parseEval(master_init_code);
|
R.parseEval(master_init_code);
|
||||||
|
|
||||||
// dt_differ = R.parseEval("mysetup$dt_differ");
|
|
||||||
// // ... and broadcast it to every other rank unequal to 0
|
|
||||||
MPI_Bcast(&dt_differ, 1, MPI_C_BOOL, 0, MPI_COMM_WORLD);
|
|
||||||
}
|
|
||||||
/* workers will only read the setup DataFrame defined by input file */
|
|
||||||
else {
|
|
||||||
// R.parseEval("mysetup <- setup");
|
|
||||||
MPI_Bcast(&dt_differ, 1, MPI_C_BOOL, 0, MPI_COMM_WORLD);
|
|
||||||
}
|
|
||||||
|
|
||||||
params.setDtDiffer(dt_differ);
|
|
||||||
|
|
||||||
// initialize chemistry on all processes
|
|
||||||
// TODO: einlesen einer initial matrix (DataFrame)
|
|
||||||
// std::string init_chemistry_code = "mysetup <-
|
|
||||||
// init_chemistry(setup=mysetup)"; R.parseEval(init_chemistry_code);
|
|
||||||
|
|
||||||
// TODO: Grid anpassen
|
|
||||||
|
|
||||||
Grid grid;
|
Grid grid;
|
||||||
|
GridParams g_params(R);
|
||||||
|
|
||||||
grid.InitModuleFromParams(GridParams(R));
|
grid.InitModuleFromParams(g_params);
|
||||||
grid.PushbackModuleFlow(poet::DIFFUSION_MODULE_NAME,
|
grid.PushbackModuleFlow(poet::DIFFUSION_MODULE_NAME, CHEMISTRY_MODULE_NAME);
|
||||||
poet::BaseChemModule::CHEMISTRY_MODULE_NAME);
|
grid.PushbackModuleFlow(CHEMISTRY_MODULE_NAME, poet::DIFFUSION_MODULE_NAME);
|
||||||
grid.PushbackModuleFlow(poet::BaseChemModule::CHEMISTRY_MODULE_NAME,
|
|
||||||
poet::DIFFUSION_MODULE_NAME);
|
|
||||||
|
|
||||||
params.initVectorParams(R, grid.GetSpeciesCount());
|
params.initVectorParams(R, grid.GetSpeciesCount());
|
||||||
|
|
||||||
@ -203,38 +320,35 @@ int main(int argc, char *argv[]) {
|
|||||||
cout << "CPP: Init done on process with rank " << world_rank << endl;
|
cout << "CPP: Init done on process with rank " << world_rank << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
MPI_Barrier(MPI_COMM_WORLD);
|
// MPI_Barrier(MPI_COMM_WORLD);
|
||||||
|
|
||||||
poet::ChemistryParams chem_params(R);
|
poet::ChemistryParams chem_params(R);
|
||||||
|
|
||||||
/* THIS IS EXECUTED BY THE MASTER */
|
/* THIS IS EXECUTED BY THE MASTER */
|
||||||
if (world_rank == 0) {
|
std::string db_path = chem_params.database_path;
|
||||||
if (world_size == 1) {
|
uint32_t c_size = db_path.size();
|
||||||
dSimTime = RunMasterLoop<ChemSeq>(params, R, grid, chem_params);
|
MPI_Bcast(&c_size, 1, MPI_UINT32_T, 0, MPI_COMM_WORLD);
|
||||||
} else {
|
|
||||||
dSimTime = RunMasterLoop<ChemMaster>(params, R, grid, chem_params);
|
|
||||||
}
|
|
||||||
|
|
||||||
cout << "CPP: finished simulation loop" << endl;
|
MPI_Bcast(db_path.data(), c_size, MPI_CHAR, 0, MPI_COMM_WORLD);
|
||||||
|
uint32_t nxyz_master = (world_size == 1 ? grid.GetTotalCellCount() : 1);
|
||||||
|
|
||||||
cout << "CPP: start timing profiling" << endl;
|
dSimTime = RunMasterLoop(params, R, grid, chem_params, g_params, nxyz_master);
|
||||||
|
|
||||||
R["simtime"] = dSimTime;
|
cout << "CPP: finished simulation loop" << endl;
|
||||||
R.parseEvalQ("profiling$simtime <- simtime");
|
|
||||||
|
|
||||||
string r_vis_code;
|
cout << "CPP: start timing profiling" << endl;
|
||||||
r_vis_code = "saveRDS(profiling, file=paste0(fileout,'/timings.rds'));";
|
|
||||||
R.parseEval(r_vis_code);
|
|
||||||
|
|
||||||
cout << "CPP: Done! Results are stored as R objects into <"
|
R["simtime"] = dSimTime;
|
||||||
<< params.getOutDir() << "/timings.rds>" << endl;
|
R.parseEvalQ("profiling$simtime <- simtime");
|
||||||
}
|
|
||||||
/* THIS IS EXECUTED BY THE WORKERS */
|
string r_vis_code;
|
||||||
else {
|
r_vis_code = "saveRDS(profiling, file=paste0(fileout,'/timings.rds'));";
|
||||||
ChemWorker worker(params, R, grid, dht_comm);
|
R.parseEval(r_vis_code);
|
||||||
worker.InitModule(chem_params);
|
|
||||||
worker.loop();
|
cout << "CPP: Done! Results are stored as R objects into <"
|
||||||
}
|
<< params.getOutDir() << "/timings.rds>" << endl;
|
||||||
|
|
||||||
|
MPI_Barrier(MPI_COMM_WORLD);
|
||||||
|
|
||||||
cout << "CPP: finished, cleanup of process " << world_rank << endl;
|
cout << "CPP: finished, cleanup of process " << world_rank << endl;
|
||||||
MPI_Finalize();
|
MPI_Finalize();
|
||||||
|
|||||||
@ -1,6 +1,10 @@
|
|||||||
#ifndef POET_H
|
#ifndef POET_H
|
||||||
#define POET_H
|
#define POET_H
|
||||||
|
|
||||||
|
#include "poet/ChemistryModule.hpp"
|
||||||
|
#include <Rcpp.h>
|
||||||
const char *poet_version = "@POET_VERSION@";
|
const char *poet_version = "@POET_VERSION@";
|
||||||
|
|
||||||
|
const char *CHEMISTRY_MODULE_NAME = "state_C";
|
||||||
|
|
||||||
#endif // POET_H
|
#endif // POET_H
|
||||||
|
|||||||
287
app/poet_prm.cpp
Normal file
287
app/poet_prm.cpp
Normal file
@ -0,0 +1,287 @@
|
|||||||
|
/*
|
||||||
|
** Copyright (C) 2018-2021 Alexander Lindemann, Max Luebke (University of
|
||||||
|
** Potsdam)
|
||||||
|
**
|
||||||
|
** Copyright (C) 2018-2022 Marco De Lucia, Max Luebke (GFZ Potsdam)
|
||||||
|
**
|
||||||
|
** POET is free software; you can redistribute it and/or modify it under the
|
||||||
|
** terms of the GNU General Public License as published by the Free Software
|
||||||
|
** Foundation; either version 2 of the License, or (at your option) any later
|
||||||
|
** version.
|
||||||
|
**
|
||||||
|
** POET is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
** WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||||
|
** A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
**
|
||||||
|
** You should have received a copy of the GNU General Public License along with
|
||||||
|
** this program; if not, write to the Free Software Foundation, Inc., 51
|
||||||
|
** Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "poet/ChemistryModule.hpp"
|
||||||
|
#include <RInside.h>
|
||||||
|
#include <Rcpp.h>
|
||||||
|
#include <Rcpp/internal/wrap.h>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <poet/DiffusionModule.hpp>
|
||||||
|
#include <poet/Grid.hpp>
|
||||||
|
#include <poet/SimParams.hpp>
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <mpi.h>
|
||||||
|
#include <poet.h>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace poet;
|
||||||
|
using namespace Rcpp;
|
||||||
|
|
||||||
|
void set_chem_parameters(poet::ChemistryModule &chem, uint32_t wp_size,
|
||||||
|
const std::string &database_path) {
|
||||||
|
chem.SetErrorHandlerMode(1);
|
||||||
|
chem.SetComponentH2O(false);
|
||||||
|
chem.SetRebalanceFraction(0.5);
|
||||||
|
chem.SetRebalanceByCell(true);
|
||||||
|
chem.UseSolutionDensityVolume(false);
|
||||||
|
chem.SetPartitionUZSolids(false);
|
||||||
|
|
||||||
|
// Set concentration units
|
||||||
|
// 1, mg/L; 2, mol/L; 3, kg/kgs
|
||||||
|
chem.SetUnitsSolution(2);
|
||||||
|
// 0, mol/L cell; 1, mol/L water; 2 mol/L rock
|
||||||
|
chem.SetUnitsPPassemblage(1);
|
||||||
|
// 0, mol/L cell; 1, mol/L water; 2 mol/L rock
|
||||||
|
chem.SetUnitsExchange(1);
|
||||||
|
// 0, mol/L cell; 1, mol/L water; 2 mol/L rock
|
||||||
|
chem.SetUnitsSurface(1);
|
||||||
|
// 0, mol/L cell; 1, mol/L water; 2 mol/L rock
|
||||||
|
chem.SetUnitsGasPhase(1);
|
||||||
|
// 0, mol/L cell; 1, mol/L water; 2 mol/L rock
|
||||||
|
chem.SetUnitsSSassemblage(1);
|
||||||
|
// 0, mol/L cell; 1, mol/L water; 2 mol/L rock
|
||||||
|
chem.SetUnitsKinetics(1);
|
||||||
|
|
||||||
|
// Set representative volume
|
||||||
|
std::vector<double> rv;
|
||||||
|
rv.resize(wp_size, 1.0);
|
||||||
|
chem.SetRepresentativeVolume(rv);
|
||||||
|
|
||||||
|
// Set initial porosity
|
||||||
|
std::vector<double> por;
|
||||||
|
por.resize(wp_size, 1);
|
||||||
|
chem.SetPorosity(por);
|
||||||
|
|
||||||
|
// Set initial saturation
|
||||||
|
std::vector<double> sat;
|
||||||
|
sat.resize(wp_size, 1.0);
|
||||||
|
chem.SetSaturation(sat);
|
||||||
|
|
||||||
|
// Load database
|
||||||
|
chem.LoadDatabase(database_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline double RunMasterLoop(SimParams ¶ms, RInside &R, Grid &grid,
|
||||||
|
ChemistryParams &chem_params,
|
||||||
|
const GridParams &g_params, uint32_t nxyz_master) {
|
||||||
|
|
||||||
|
DiffusionModule diffusion(poet::DiffusionParams(R), grid);
|
||||||
|
/* Iteration Count is dynamic, retrieving value from R (is only needed by
|
||||||
|
* master for the following loop) */
|
||||||
|
uint32_t maxiter = R.parseEval("mysetup$iterations");
|
||||||
|
|
||||||
|
double sim_time = .0;
|
||||||
|
|
||||||
|
ChemistryModule chem(grid.GetTotalCellCount(), MPI_COMM_WORLD);
|
||||||
|
set_chem_parameters(chem, nxyz_master, chem_params.database_path);
|
||||||
|
chem.RunInitFile(chem_params.input_script);
|
||||||
|
|
||||||
|
chem.SetSelectedOutputOn(true);
|
||||||
|
chem.SetTimeStep(0);
|
||||||
|
chem.RunCells();
|
||||||
|
|
||||||
|
StateMemory *chem_state = grid.RegisterState("state_C", chem.GetPropNames());
|
||||||
|
auto &chem_field = chem_state->mem;
|
||||||
|
chem_field = chem.GetField();
|
||||||
|
/* SIMULATION LOOP */
|
||||||
|
|
||||||
|
double dStartTime = MPI_Wtime();
|
||||||
|
for (uint32_t iter = 1; iter < maxiter + 1; iter++) {
|
||||||
|
uint32_t tick = 0;
|
||||||
|
// cout << "CPP: Evaluating next time step" << endl;
|
||||||
|
// R.parseEvalQ("mysetup <- master_iteration_setup(mysetup)");
|
||||||
|
|
||||||
|
double dt = Rcpp::as<double>(
|
||||||
|
R.parseEval("mysetup$timesteps[" + std::to_string(iter) + "]"));
|
||||||
|
cout << "CPP: Next time step is " << dt << "[s]" << endl;
|
||||||
|
|
||||||
|
/* displaying iteration number, with C++ and R iterator */
|
||||||
|
cout << "CPP: Going through iteration " << iter << endl;
|
||||||
|
cout << "CPP: R's $iter: " << ((uint32_t)(R.parseEval("mysetup$iter")))
|
||||||
|
<< ". Iteration" << endl;
|
||||||
|
|
||||||
|
/* run transport */
|
||||||
|
// TODO: transport to diffusion
|
||||||
|
diffusion.simulate(dt);
|
||||||
|
|
||||||
|
grid.PreModuleFieldCopy(tick++);
|
||||||
|
|
||||||
|
cout << "CPP: Chemistry" << endl;
|
||||||
|
|
||||||
|
chem.SetTimeStep(dt);
|
||||||
|
|
||||||
|
chem.SetConcentrations(chem_field);
|
||||||
|
chem.SetTimeStep(dt);
|
||||||
|
chem.RunCells();
|
||||||
|
chem_field = chem.GetField();
|
||||||
|
|
||||||
|
grid.WriteFieldsToR(R);
|
||||||
|
grid.PreModuleFieldCopy(tick++);
|
||||||
|
|
||||||
|
R["req_dt"] = dt;
|
||||||
|
R["simtime"] = (sim_time += dt);
|
||||||
|
|
||||||
|
R.parseEval("mysetup$req_dt <- req_dt");
|
||||||
|
R.parseEval("mysetup$simtime <- simtime");
|
||||||
|
|
||||||
|
// MDL master_iteration_end just writes on disk state_T and
|
||||||
|
// state_C after every iteration if the cmdline option
|
||||||
|
// --ignore-results is not given (and thus the R variable
|
||||||
|
// store_result is TRUE)
|
||||||
|
R.parseEvalQ("mysetup <- master_iteration_end(setup=mysetup)");
|
||||||
|
|
||||||
|
cout << endl
|
||||||
|
<< "CPP: End of *coupling* iteration " << iter << "/" << maxiter
|
||||||
|
<< endl
|
||||||
|
<< endl;
|
||||||
|
|
||||||
|
// MPI_Barrier(MPI_COMM_WORLD);
|
||||||
|
|
||||||
|
} // END SIMULATION LOOP
|
||||||
|
|
||||||
|
R.parseEvalQ("profiling <- list()");
|
||||||
|
|
||||||
|
R["simtime_chemistry"] = chem.GetChemistryTime();
|
||||||
|
R.parseEvalQ("profiling$simtime_chemistry <- simtime_chemistry");
|
||||||
|
|
||||||
|
chem.MpiWorkerBreak();
|
||||||
|
diffusion.end();
|
||||||
|
|
||||||
|
return MPI_Wtime() - dStartTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
double dSimTime, sim_end;
|
||||||
|
|
||||||
|
int world_size, world_rank;
|
||||||
|
|
||||||
|
MPI_Init(&argc, &argv);
|
||||||
|
|
||||||
|
MPI_Comm_size(MPI_COMM_WORLD, &world_size);
|
||||||
|
|
||||||
|
MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
|
||||||
|
|
||||||
|
if (world_rank == 0) {
|
||||||
|
cout << "Running POET in version " << poet_version << endl << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (world_rank > 0) {
|
||||||
|
{
|
||||||
|
uint32_t nxyz;
|
||||||
|
MPI_Bcast(&nxyz, 1, MPI_UINT32_T, 0, MPI_COMM_WORLD);
|
||||||
|
ChemistryModule worker(nxyz, MPI_COMM_WORLD);
|
||||||
|
worker.MpiWorker();
|
||||||
|
}
|
||||||
|
|
||||||
|
MPI_Barrier(MPI_COMM_WORLD);
|
||||||
|
cout << "CPP: finished, cleanup of process " << world_rank << endl;
|
||||||
|
MPI_Finalize();
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* initialize R runtime */
|
||||||
|
RInside R(argc, argv);
|
||||||
|
|
||||||
|
/*Loading Dependencies*/
|
||||||
|
// TODO: kann raus
|
||||||
|
std::string r_load_dependencies = "source('../R_lib/kin_r_library.R');";
|
||||||
|
R.parseEvalQ(r_load_dependencies);
|
||||||
|
|
||||||
|
SimParams params(world_rank, world_size);
|
||||||
|
int pret = params.parseFromCmdl(argv, R);
|
||||||
|
|
||||||
|
if (pret == poet::PARSER_ERROR) {
|
||||||
|
MPI_Finalize();
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
} else if (pret == poet::PARSER_HELP) {
|
||||||
|
MPI_Finalize();
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
cout << "CPP: R Init (RInside) on process " << world_rank << endl;
|
||||||
|
|
||||||
|
R.parseEvalQ("mysetup <- setup");
|
||||||
|
// if (world_rank == 0) { // get timestep vector from
|
||||||
|
// grid_init function ... //
|
||||||
|
std::string master_init_code = "mysetup <- master_init(setup=setup)";
|
||||||
|
R.parseEval(master_init_code);
|
||||||
|
|
||||||
|
Grid grid;
|
||||||
|
GridParams g_params(R);
|
||||||
|
|
||||||
|
grid.InitModuleFromParams(g_params);
|
||||||
|
grid.PushbackModuleFlow(poet::DIFFUSION_MODULE_NAME, CHEMISTRY_MODULE_NAME);
|
||||||
|
grid.PushbackModuleFlow(CHEMISTRY_MODULE_NAME, poet::DIFFUSION_MODULE_NAME);
|
||||||
|
|
||||||
|
params.initVectorParams(R, grid.GetSpeciesCount());
|
||||||
|
|
||||||
|
// MDL: store all parameters
|
||||||
|
if (world_rank == 0) {
|
||||||
|
cout << "CPP: Calling R Function to store calling parameters" << endl;
|
||||||
|
R.parseEvalQ("StoreSetup(setup=mysetup)");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (world_rank == 0) {
|
||||||
|
cout << "CPP: Init done on process with rank " << world_rank << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// MPI_Barrier(MPI_COMM_WORLD);
|
||||||
|
|
||||||
|
poet::ChemistryParams chem_params(R);
|
||||||
|
|
||||||
|
/* THIS IS EXECUTED BY THE MASTER */
|
||||||
|
uint32_t nxyz = grid.GetTotalCellCount();
|
||||||
|
MPI_Bcast(&nxyz, 1, MPI_UINT32_T, 0, MPI_COMM_WORLD);
|
||||||
|
uint32_t nxyz_master = grid.GetTotalCellCount();
|
||||||
|
|
||||||
|
dSimTime = RunMasterLoop(params, R, grid, chem_params, g_params, nxyz_master);
|
||||||
|
|
||||||
|
cout << "CPP: finished simulation loop" << endl;
|
||||||
|
|
||||||
|
cout << "CPP: start timing profiling" << endl;
|
||||||
|
|
||||||
|
R["simtime"] = dSimTime;
|
||||||
|
R.parseEvalQ("profiling$simtime <- simtime");
|
||||||
|
|
||||||
|
string r_vis_code;
|
||||||
|
r_vis_code = "saveRDS(profiling, file=paste0(fileout,'/timings.rds'));";
|
||||||
|
R.parseEval(r_vis_code);
|
||||||
|
|
||||||
|
cout << "CPP: Done! Results are stored as R objects into <"
|
||||||
|
<< params.getOutDir() << "/timings.rds>" << endl;
|
||||||
|
|
||||||
|
MPI_Barrier(MPI_COMM_WORLD);
|
||||||
|
|
||||||
|
cout << "CPP: finished, cleanup of process " << world_rank << endl;
|
||||||
|
MPI_Finalize();
|
||||||
|
|
||||||
|
if (world_rank == 0) {
|
||||||
|
cout << "CPP: done, bye!" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
@ -1,13 +1,6 @@
|
|||||||
SELECTED_OUTPUT
|
SELECTED_OUTPUT
|
||||||
-high_precision true
|
-high_precision true
|
||||||
-reset false
|
-reset false
|
||||||
-time
|
|
||||||
-soln
|
|
||||||
-temperature true
|
|
||||||
-water true
|
|
||||||
-pH
|
|
||||||
-pe
|
|
||||||
-totals C Ca Cl Mg
|
|
||||||
-kinetic_reactants Calcite Dolomite
|
-kinetic_reactants Calcite Dolomite
|
||||||
-equilibrium O2g
|
-equilibrium O2g
|
||||||
|
|
||||||
|
|||||||
3718
bench/surfex/SMILE_2021_11_01_TH.dat
Normal file
3718
bench/surfex/SMILE_2021_11_01_TH.dat
Normal file
File diff suppressed because it is too large
Load Diff
56
bench/surfex/SurfExBase.pqi
Normal file
56
bench/surfex/SurfExBase.pqi
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
## Time-stamp: "Last modified 2023-02-27 14:31:11 delucia"
|
||||||
|
KNOBS
|
||||||
|
-logfile false
|
||||||
|
-iterations 10000
|
||||||
|
-convergence_tolerance 1E-12
|
||||||
|
-step_size 2
|
||||||
|
-pe_step_size 2
|
||||||
|
SELECTED_OUTPUT
|
||||||
|
-reset false
|
||||||
|
-high_precision true
|
||||||
|
-solution true
|
||||||
|
-state true
|
||||||
|
-step true
|
||||||
|
-pH true
|
||||||
|
-pe true
|
||||||
|
-ionic_strength true
|
||||||
|
-water true
|
||||||
|
USER_PUNCH
|
||||||
|
-head total_o total_h cb C(-4) C(4) Ca Cl Fe(2) Fe(3) H(0) K Mg Na S(-2) S(2) S(4) S(6) Sr U(4) U(5) U(6) UO2(am,hyd) KdU
|
||||||
|
-start
|
||||||
|
5 w=TOT("water")
|
||||||
|
10 PUNCH TOTMOLE("O"), TOTMOLE("H"), CHARGE_BALANCE, w*TOT("C(-4)"), w*TOT("C(4)"), w*TOT("Ca"), w*TOT("Cl"), w*TOT("Fe(2)"), w*TOT("Fe(3)"), w*TOT("H(0)"), w*TOT("K"), w*TOT("Mg"), w*TOT("Na"), w*TOT("S(-2)"), w*TOT("S(2)"), w*TOT("S(4)"), w*TOT("S(6)"), w*TOT("Sr"), w*TOT("U(4)"), w*TOT("U(5)"), w*TOT("U(6)"), EQUI("UO2(am,hyd)")
|
||||||
|
20 PUNCH ((SURF("U, Ill")+SURF("U, Mll")+SURF("U, Kln")+EDL("U, Ill")+EDL("U, Mll")+EDL("U, Kln"))/((TOT("U")*1.01583)))/(0.002251896406*1000)
|
||||||
|
-end
|
||||||
|
SOLUTION 1
|
||||||
|
temp 13
|
||||||
|
units mol/kgw
|
||||||
|
pH 7.06355
|
||||||
|
pe -2.626517
|
||||||
|
C(4) 0.001990694
|
||||||
|
Ca 0.02172649
|
||||||
|
Cl 0.3227673 charge
|
||||||
|
Fe 0.0001434717
|
||||||
|
K 0.001902357
|
||||||
|
Mg 0.01739704
|
||||||
|
Na 0.2762882
|
||||||
|
S(6) 0.01652701
|
||||||
|
Sr 0.0004520361
|
||||||
|
U(4) 8.147792e-12
|
||||||
|
U(6) 2.237946e-09
|
||||||
|
-water 0.00133
|
||||||
|
SURFACE 1
|
||||||
|
-equil 1
|
||||||
|
-sites_units density
|
||||||
|
-donnan 4.9e-10
|
||||||
|
Kln_aOH 1.155 11. 5.0518
|
||||||
|
Kln_siOH 1.155
|
||||||
|
Ill_sOH 0.05 100. 5.5931
|
||||||
|
Ill_wOH 2.26
|
||||||
|
Mll_sOH 0.05 100. 1.0825
|
||||||
|
Mll_wOH 2.26
|
||||||
|
EXCHANGE 1
|
||||||
|
-equil 1
|
||||||
|
Z 0.0012585
|
||||||
|
Y 0.0009418
|
||||||
|
END
|
||||||
142
bench/surfex/surfex.R
Normal file
142
bench/surfex/surfex.R
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
## Time-stamp: "Last modified 2023-02-27 18:33:30 delucia"
|
||||||
|
|
||||||
|
database <- normalizePath("./SMILE_2021_11_01_TH.dat")
|
||||||
|
input_script <- normalizePath("./SurfExBase.pqi")
|
||||||
|
|
||||||
|
cat(paste(":: R This is a test 1\n"))
|
||||||
|
|
||||||
|
#################################################################
|
||||||
|
## Section 1 ##
|
||||||
|
## Grid initialization ##
|
||||||
|
#################################################################
|
||||||
|
|
||||||
|
n <- 10
|
||||||
|
m <- 10
|
||||||
|
|
||||||
|
types <- c("scratch", "phreeqc", "rds")
|
||||||
|
|
||||||
|
init_cell <- list(H = 1.476571028625e-01,
|
||||||
|
O = 7.392297218936e-02,
|
||||||
|
Charge = -1.765225732724e-18,
|
||||||
|
`C(-4)` = 2.477908970828e-21,
|
||||||
|
`C(4)` = 2.647623016916e-06,
|
||||||
|
Ca = 2.889623169138e-05,
|
||||||
|
Cl = 4.292806181039e-04,
|
||||||
|
`Fe(2)` =1.908142472666e-07,
|
||||||
|
`Fe(3)` =3.173306589931e-12,
|
||||||
|
`H(0)` =2.675642675119e-15,
|
||||||
|
K = 2.530134809667e-06,
|
||||||
|
Mg =2.313806319294e-05,
|
||||||
|
Na =3.674633059628e-04,
|
||||||
|
`S(-2)` = 8.589766637180e-15,
|
||||||
|
`S(2)` = 1.205284362720e-19,
|
||||||
|
`S(4)` = 9.108958772790e-18,
|
||||||
|
`S(6)` = 2.198092329098e-05,
|
||||||
|
Sr = 6.012080128154e-07,
|
||||||
|
`U(4)` = 1.039668623852e-14,
|
||||||
|
`U(5)` = 1.208394829796e-15,
|
||||||
|
`U(6)` = 2.976409147150e-12)
|
||||||
|
|
||||||
|
grid <- list(
|
||||||
|
n_cells = c(n, m),
|
||||||
|
s_cells = c(1, 1),
|
||||||
|
type = "scratch",
|
||||||
|
init_cell = as.data.frame(init_cell, check.names = FALSE),
|
||||||
|
props = names(init_cell),
|
||||||
|
database = database,
|
||||||
|
input_script = input_script
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
##################################################################
|
||||||
|
## Section 2 ##
|
||||||
|
## Diffusion parameters and boundary conditions ##
|
||||||
|
##################################################################
|
||||||
|
|
||||||
|
vecinj_diffu <- list(
|
||||||
|
list(H = 0.147659686316291,
|
||||||
|
O = 0.0739242798146046,
|
||||||
|
Charge = 7.46361643222701e-20,
|
||||||
|
`C(-4)` = 2.92438561098248e-21,
|
||||||
|
`C(4)` = 2.65160558871092e-06,
|
||||||
|
Ca = 2.89001071336443e-05,
|
||||||
|
Cl = 0.000429291158114428,
|
||||||
|
`Fe(2)` = 1.90823391198114e-07,
|
||||||
|
`Fe(3)` = 3.10832423034763e-12,
|
||||||
|
`H(0)` = 2.7888235127385e-15,
|
||||||
|
K = 2.5301787e-06,
|
||||||
|
Mg = 2.31391999937907e-05,
|
||||||
|
Na = 0.00036746969,
|
||||||
|
`S(-2)` = 1.01376078438546e-14,
|
||||||
|
`S(2)` = 1.42247026981542e-19,
|
||||||
|
`S(4)` = 9.49422092568557e-18,
|
||||||
|
`S(6)` = 2.19812504654191e-05,
|
||||||
|
Sr = 6.01218519999999e-07,
|
||||||
|
`U(4)` = 4.82255946569383e-12,
|
||||||
|
`U(5)` = 5.49050615347901e-13,
|
||||||
|
`U(6)` = 1.32462838991902e-09)
|
||||||
|
)
|
||||||
|
|
||||||
|
vecinj <- do.call(rbind.data.frame, vecinj_diffu)
|
||||||
|
names(vecinj) <- grid$props
|
||||||
|
|
||||||
|
## diffusion coefficients
|
||||||
|
alpha_diffu <- c(H = 1E-6, O = 1E-6, Charge = 1E-6, `C(-4)` = 1E-6,
|
||||||
|
`C(4)` = 1E-6, Ca = 1E-6, Cl = 1E-6, `Fe(2)` = 1E-6,
|
||||||
|
`Fe(3)` = 1E-6, `H(0)` = 1E-6, K = 1E-6, Mg = 1E-6,
|
||||||
|
Na = 1E-6, `S(-2)` = 1E-6, `S(2)` = 1E-6,
|
||||||
|
`S(4)` = 1E-6, `S(6)` = 1E-6, Sr = 1E-6,
|
||||||
|
`U(4)` = 1E-6, `U(5)` = 1E-6, `U(6)` = 1E-6)
|
||||||
|
|
||||||
|
## list of boundary conditions/inner nodes
|
||||||
|
|
||||||
|
## vecinj_inner <- list(
|
||||||
|
## list(1,1,1)
|
||||||
|
## )
|
||||||
|
|
||||||
|
boundary <- list(
|
||||||
|
"N" = rep(1, n),
|
||||||
|
"E" = rep(0, n),
|
||||||
|
"S" = rep(0, n),
|
||||||
|
"W" = rep(0, n)
|
||||||
|
)
|
||||||
|
|
||||||
|
diffu_list <- names(alpha_diffu)
|
||||||
|
|
||||||
|
diffusion <- list(
|
||||||
|
init = init_cell,
|
||||||
|
vecinj = vecinj,
|
||||||
|
# vecinj_inner = vecinj_inner,
|
||||||
|
vecinj_index = boundary,
|
||||||
|
alpha = alpha_diffu
|
||||||
|
)
|
||||||
|
|
||||||
|
#################################################################
|
||||||
|
## Section 3 ##
|
||||||
|
## Chemistry module (Phreeqc) ##
|
||||||
|
#################################################################
|
||||||
|
|
||||||
|
|
||||||
|
chemistry <- list(
|
||||||
|
database = database,
|
||||||
|
input_script = input_script
|
||||||
|
)
|
||||||
|
|
||||||
|
#################################################################
|
||||||
|
## Section 4 ##
|
||||||
|
## Putting all those things together ##
|
||||||
|
#################################################################
|
||||||
|
|
||||||
|
|
||||||
|
iterations <- 10
|
||||||
|
dt <- 200
|
||||||
|
|
||||||
|
setup <- list(
|
||||||
|
grid = grid,
|
||||||
|
diffusion = diffusion,
|
||||||
|
chemistry = chemistry,
|
||||||
|
iterations = iterations,
|
||||||
|
timesteps = rep(dt, iterations),
|
||||||
|
store_result = TRUE,
|
||||||
|
out_save = c(5, iterations)
|
||||||
|
)
|
||||||
128
data/SimComp2D.R
128
data/SimComp2D.R
@ -1,128 +0,0 @@
|
|||||||
## chemical database
|
|
||||||
db <- RPhreeFile("mdl_quint_kin.dat", is.db=TRUE)
|
|
||||||
phreeqc::phrLoadDatabaseString(db)
|
|
||||||
|
|
||||||
## only the directory
|
|
||||||
demodir <- system.file("extdata", "demo_rtwithmufits", package="Rmufits")
|
|
||||||
|
|
||||||
prop <- c("Al", "C","Ca","Cl","Fe", "K", "Mg","Na", "Si", "pH", ## "pe",
|
|
||||||
"Albite", "Calcite", "Chlorite", "Illite", "Kaolinite")
|
|
||||||
|
|
||||||
signif_vector <- c(7,7,7,7,7,7,7,7,7,6, 5,5,5,5,5)
|
|
||||||
prop_type <- rep("normal", length(signif_vector))
|
|
||||||
|
|
||||||
base <- c("SOLUTION 1",
|
|
||||||
"units mol/kgw",
|
|
||||||
"pH 6.77",
|
|
||||||
"temp 35",
|
|
||||||
"-water 1",
|
|
||||||
"Al 8.06386e-09",
|
|
||||||
"C 0.0006108294",
|
|
||||||
"Ca 0.09709463",
|
|
||||||
"Cl 4.340042",
|
|
||||||
"Fe 1.234357e-05",
|
|
||||||
"K 0.01117434",
|
|
||||||
"Mg 0.0406959",
|
|
||||||
"Na 4.189209",
|
|
||||||
"Si 0.0001935754",
|
|
||||||
"INCREMENTAL_REACTIONS true",
|
|
||||||
"KINETICS 1 ",
|
|
||||||
"-steps 86400",
|
|
||||||
"-bad_step_max 10000",
|
|
||||||
"-cvode true",
|
|
||||||
"Albite",
|
|
||||||
"-m 8.432165", ## 1540.0",
|
|
||||||
"-parms 01.54 100",
|
|
||||||
"Calcite",
|
|
||||||
"-m 0.0",
|
|
||||||
"-parms 10 100",
|
|
||||||
"Chlorite",
|
|
||||||
"-m 1.106585", ## 202.100",
|
|
||||||
"-parms 64.84 100",
|
|
||||||
"Illite",
|
|
||||||
"-m 0.9549153", ## 174.400",
|
|
||||||
"-parms 43.38 100",
|
|
||||||
"Kaolinite",
|
|
||||||
"-m 0.0",
|
|
||||||
"-parms 29.17 100",
|
|
||||||
"END")
|
|
||||||
|
|
||||||
selout <- c("KNOBS",
|
|
||||||
"-convergence_tolerance 1E-6",
|
|
||||||
"SELECTED_OUTPUT",
|
|
||||||
"-reset false",
|
|
||||||
"USER_PUNCH",
|
|
||||||
"-head Al C Ca Cl Fe K Mg Na Si pH Albite Calcite Chlorite Illite Kaolinite", ## pe
|
|
||||||
"10 PUNCH TOT(\"Al\"), TOT(\"C\"), TOT(\"Ca\"), TOT(\"Cl\"), TOT(\"Fe\"), TOT(\"K\"), TOT(\"Mg\"), TOT(\"Na\"), TOT(\"Si\"), -LA(\"H+\"), KIN(\"Albite\"), KIN(\"Calcite\"), KIN(\"Chlorite\"), KIN(\"Illite\"), KIN(\"Kaolinite\")" )
|
|
||||||
|
|
||||||
## Define initial conditions as equilibrium with primary minerals
|
|
||||||
ipr <- c(Al = 8.689e-10,
|
|
||||||
C = 0.0006108,
|
|
||||||
Ca = 0.09709,
|
|
||||||
Cl = 4.34,
|
|
||||||
Fe = 1.802e-06,
|
|
||||||
K = 0.01131,
|
|
||||||
Mg = 0.04074,
|
|
||||||
Na = 4.189,
|
|
||||||
Si = 7.653e-05,
|
|
||||||
pH = 6.889,
|
|
||||||
Albite = 5.0,
|
|
||||||
Calcite = 0.0,
|
|
||||||
Chlorite = 10.0,
|
|
||||||
Illite = 2.0,
|
|
||||||
Kaolinite = 0.0
|
|
||||||
)
|
|
||||||
|
|
||||||
initstate <- matrix(rep(ipr, 2500), byrow=TRUE, ncol=length(ipr))
|
|
||||||
colnames(initstate) <- names(ipr)
|
|
||||||
|
|
||||||
vecinj <- c(Al= 8.694e-10,
|
|
||||||
C = 8.182e-01,
|
|
||||||
Ca= 9.710e-02,
|
|
||||||
Cl= 4.340e+00,
|
|
||||||
Fe= 1.778e-06,
|
|
||||||
K = 1.131e-02,
|
|
||||||
Mg= 4.074e-02,
|
|
||||||
Na= 4.189e+00,
|
|
||||||
Si= 7.652e-05,
|
|
||||||
pH= 2.556228)
|
|
||||||
|
|
||||||
|
|
||||||
## setup boundary conditions for transport - we have already read the
|
|
||||||
## GRID with the following code:
|
|
||||||
## grid <- Rmufits::ReadGrid(paste0(demodir,"/d2ascii.run.GRID.SUM"))
|
|
||||||
## cbound <- which(grid$cell$ACTNUM == 2)
|
|
||||||
## dput(cbound)
|
|
||||||
cbound <- c(1L, 50L, 100L, 150L, 200L, 250L, 300L, 350L, 400L, 450L, 500L,
|
|
||||||
550L, 600L, 650L, 700L, 750L, 800L, 850L, 900L, 950L, 1000L,
|
|
||||||
1050L, 1100L, 1150L, 1200L, 1250L, 1300L, 1350L, 1400L, 1450L,
|
|
||||||
1500L, 1550L, 1600L, 1650L, 1700L, 1750L, 1800L, 1850L, 1900L,
|
|
||||||
1950L, 2000L, 2050L, 2100L, 2150L, 2200L, 2250L, 2300L, 2350L,
|
|
||||||
2400L, 2450L, 2451L, 2452L, 2453L, 2454L, 2455L, 2456L, 2457L,
|
|
||||||
2458L, 2459L, 2460L, 2461L, 2462L, 2463L, 2464L, 2465L, 2466L,
|
|
||||||
2467L, 2468L, 2469L, 2470L, 2471L, 2472L, 2473L, 2474L, 2475L,
|
|
||||||
2476L, 2477L, 2478L, 2479L, 2480L, 2481L, 2482L, 2483L, 2484L,
|
|
||||||
2485L, 2486L, 2487L, 2488L, 2489L, 2490L, 2491L, 2492L, 2493L,
|
|
||||||
2494L, 2495L, 2496L, 2497L, 2498L, 2499L, 2500L)
|
|
||||||
|
|
||||||
boundary_matrix <- matrix(rep(ipr[1:10], length(cbound)), byrow=TRUE, nrow=length(cbound))
|
|
||||||
colnames(boundary_matrix) <- names(ipr[1:10])
|
|
||||||
boundary_matrix[1, ] <- vecinj
|
|
||||||
|
|
||||||
boundary_matrix <- cbind(cbound,boundary_matrix)
|
|
||||||
|
|
||||||
setup <- list(n = 2500,
|
|
||||||
bound = boundary_matrix,
|
|
||||||
base = base,
|
|
||||||
first = selout,
|
|
||||||
initsim = initstate,
|
|
||||||
Cf = 1,
|
|
||||||
prop = prop,
|
|
||||||
immobile = seq(11,15),
|
|
||||||
kin = seq(11,15),
|
|
||||||
phase = "FLUX1",
|
|
||||||
density = "DEN1",
|
|
||||||
reduce = FALSE,
|
|
||||||
snapshots = demodir, ## directory where we will read MUFITS SUM files
|
|
||||||
gridfile = paste0(demodir,"/d2ascii.run.GRID.SUM")
|
|
||||||
)
|
|
||||||
@ -1,131 +0,0 @@
|
|||||||
db <- RPhreeFile("mdl_quint_kin.dat", is.db=TRUE)
|
|
||||||
phreeqc::phrLoadDatabaseString(db)
|
|
||||||
|
|
||||||
## only the directory
|
|
||||||
demodir <- "./snaps/"
|
|
||||||
|
|
||||||
base <- c("SOLUTION 1",
|
|
||||||
"units mol/kgw",
|
|
||||||
"pH 6.77",
|
|
||||||
"temp 35",
|
|
||||||
"-water 1",
|
|
||||||
"Al 8.06386e-09",
|
|
||||||
"C 0.0006108294",
|
|
||||||
"Ca 0.09709463",
|
|
||||||
"Cl 4.340042",
|
|
||||||
"Fe 1.234357e-05",
|
|
||||||
"K 0.01117434",
|
|
||||||
"Mg 0.0406959",
|
|
||||||
"Na 4.189209",
|
|
||||||
"Si 0.0001935754",
|
|
||||||
"INCREMENTAL_REACTIONS true",
|
|
||||||
"KINETICS 1 ",
|
|
||||||
"-steps 86400",
|
|
||||||
"-bad_step_max 10000",
|
|
||||||
"-cvode true",
|
|
||||||
"Albite",
|
|
||||||
"-m 8.432165", ## 1540.0",
|
|
||||||
"-parms 01.54 100",
|
|
||||||
"Calcite",
|
|
||||||
"-m 0.0",
|
|
||||||
"-parms 10 100",
|
|
||||||
"Chlorite",
|
|
||||||
"-m 1.106585", ## 202.100",
|
|
||||||
"-parms 64.84 100",
|
|
||||||
"Illite",
|
|
||||||
"-m 0.9549153", ## 174.400",
|
|
||||||
"-parms 43.38 100",
|
|
||||||
"Kaolinite",
|
|
||||||
"-m 0.0",
|
|
||||||
"-parms 29.17 100",
|
|
||||||
"END")
|
|
||||||
|
|
||||||
selout <- c("KNOBS",
|
|
||||||
"-convergence_tolerance 1E-6",
|
|
||||||
"SELECTED_OUTPUT",
|
|
||||||
"-reset false",
|
|
||||||
"USER_PUNCH",
|
|
||||||
"-head Al C Ca Cl Fe K Mg Na Si pH Albite Calcite Chlorite Illite Kaolinite", ## pe
|
|
||||||
"10 PUNCH TOT(\"Al\"), TOT(\"C\"), TOT(\"Ca\"), TOT(\"Cl\"), TOT(\"Fe\"), TOT(\"K\"), TOT(\"Mg\"), TOT(\"Na\"), TOT(\"Si\"), -LA(\"H+\"), KIN(\"Albite\"), KIN(\"Calcite\"), KIN(\"Chlorite\"), KIN(\"Illite\"), KIN(\"Kaolinite\")" )
|
|
||||||
|
|
||||||
## Define initial conditions as equilibrium with primary minerals
|
|
||||||
ipr <- c(Al = 8.689e-10,
|
|
||||||
C = 0.0006108,
|
|
||||||
Ca = 0.09709,
|
|
||||||
Cl = 4.34,
|
|
||||||
Fe = 1.802e-06,
|
|
||||||
K = 0.01131,
|
|
||||||
Mg = 0.04074,
|
|
||||||
Na = 4.189,
|
|
||||||
Si = 7.653e-05,
|
|
||||||
pH = 6.889,
|
|
||||||
Albite = 5.0,
|
|
||||||
Calcite = 0.0,
|
|
||||||
Chlorite = 10.0,
|
|
||||||
Illite = 2.0,
|
|
||||||
Kaolinite = 0.0
|
|
||||||
)
|
|
||||||
|
|
||||||
initstate <- matrix(rep(ipr, 648420), byrow=TRUE, ncol=length(ipr))
|
|
||||||
colnames(initstate) <- names(ipr)
|
|
||||||
|
|
||||||
vecinj <- c(Al= 8.694e-10,
|
|
||||||
C = 8.182e-01,
|
|
||||||
Ca= 9.710e-02,
|
|
||||||
Cl= 4.340e+00,
|
|
||||||
Fe= 1.778e-06,
|
|
||||||
K = 1.131e-02,
|
|
||||||
Mg= 4.074e-02,
|
|
||||||
Na= 4.189e+00,
|
|
||||||
Si= 7.652e-05,
|
|
||||||
pH= 2.556228)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
prop <- c("Al", "C","Ca","Cl","Fe", "K", "Mg","Na", "Si", "pH", ## "pe",
|
|
||||||
"Albite", "Calcite", "Chlorite", "Illite", "Kaolinite")
|
|
||||||
|
|
||||||
bound_elm <- c(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 12L, 13L, 14L,
|
|
||||||
15L, 16L, 17L, 18L, 19L, 20L, 21L, 22L, 23L, 24L, 25L, 26L, 27L,
|
|
||||||
28L, 29L, 30L, 31L, 32L, 33L, 34L, 35L, 36L, 37L, 38L, 39L, 40L,
|
|
||||||
41L, 42L, 43L, 44L, 45L, 46L, 47L, 48L, 49L, 50L, 51L, 52L, 53L,
|
|
||||||
54L, 55L, 56L, 57L, 58L, 59L, 60L, 61L, 62L, 63L, 64L, 65L, 66L,
|
|
||||||
67L, 68L, 69L, 70L, 71L, 72L, 73L, 74L, 75L, 76L, 77L, 78L, 79L,
|
|
||||||
80L, 81L, 82L, 83L, 84L, 85L, 86L, 87L, 88L, 89L, 90L, 91L, 92L,
|
|
||||||
93L, 94L, 95L, 96L, 97L, 98L, 99L, 100L, 101L, 102L, 103L, 104L,
|
|
||||||
105L, 106L, 107L, 108L, 214L, 215L)
|
|
||||||
|
|
||||||
inj_elm <- c(7426L, 18233L, 29040L, 39847L,
|
|
||||||
50654L, 61461L, 72268L, 83075L, 93882L, 104689L, 115496L, 126303L,
|
|
||||||
137110L, 147917L, 158724L, 169531L, 180338L, 191145L, 201952L,
|
|
||||||
212759L, 223566L, 234373L, 245180L, 255987L, 266794L, 277601L,
|
|
||||||
288408L, 299215L, 310022L, 320829L, 331636L, 342443L, 353250L,
|
|
||||||
364057L, 374864L, 385671L, 396478L, 407285L, 418092L, 428899L,
|
|
||||||
439706L, 450513L, 461320L, 472127L, 482934L, 493741L, 504548L,
|
|
||||||
515355L)
|
|
||||||
|
|
||||||
cbound <- inj_elm
|
|
||||||
|
|
||||||
boundinit <- matrix(rep(vecinj, length(cbound)), ncol=length(vecinj), byrow=TRUE)
|
|
||||||
myboundmat <- cbind(cbound,boundinit)
|
|
||||||
|
|
||||||
## distinguish between injection and real boundaries
|
|
||||||
colnames(myboundmat) <- c("cbound", names(vecinj))
|
|
||||||
|
|
||||||
setup <- list(n=648420,
|
|
||||||
base=base,
|
|
||||||
bound=myboundmat,
|
|
||||||
first=selout,
|
|
||||||
initsim=initstate,
|
|
||||||
Cf=1,
|
|
||||||
prop=prop,
|
|
||||||
immobile=seq(11,15),
|
|
||||||
kin= seq(11,15),
|
|
||||||
phase="FLUX1",
|
|
||||||
density="DENS",
|
|
||||||
reduce=TRUE,
|
|
||||||
snapshots="snaps/AllSnaps_cmp_v3.rds",
|
|
||||||
gridfile ="snaps/GridKtz_cmp_v3.rds")
|
|
||||||
|
|
||||||
|
|
||||||
120
data/SimDol2D.R
120
data/SimDol2D.R
@ -1,120 +0,0 @@
|
|||||||
## chemical database
|
|
||||||
db <- RPhreeFile(system.file("extdata", "phreeqc_kin.dat",
|
|
||||||
package="RedModRphree"), is.db=TRUE)
|
|
||||||
|
|
||||||
phreeqc::phrLoadDatabaseString(db)
|
|
||||||
|
|
||||||
## only the directory
|
|
||||||
demodir <- system.file("extdata", "demo_rtwithmufits", package="Rmufits")
|
|
||||||
|
|
||||||
prop <- c("C","Ca","Cl","Mg","pH","pe","O2g", "Calcite","Dolomite")
|
|
||||||
|
|
||||||
signif_vector <- c(7,7,7,7,7,7,7,5,5)
|
|
||||||
prop_type <- c("act","act","act","act","logact","logact","ignore","act","act")
|
|
||||||
|
|
||||||
|
|
||||||
base <- c("SOLUTION 1",
|
|
||||||
"units mol/kgw",
|
|
||||||
"temp 25.0",
|
|
||||||
"water 1",
|
|
||||||
"pH 9.91 charge",
|
|
||||||
"pe 4.0",
|
|
||||||
"C 1.2279E-04",
|
|
||||||
"Ca 1.2279E-04",
|
|
||||||
"Mg 0.001",
|
|
||||||
"Cl 0.002",
|
|
||||||
"PURE 1",
|
|
||||||
"O2g -0.1675 10",
|
|
||||||
"KINETICS 1",
|
|
||||||
"-steps 100",
|
|
||||||
"-step_divide 100",
|
|
||||||
"-bad_step_max 2000",
|
|
||||||
"Calcite", "-m 0.000207",
|
|
||||||
"-parms 0.0032",
|
|
||||||
"Dolomite",
|
|
||||||
"-m 0.0",
|
|
||||||
"-parms 0.00032",
|
|
||||||
"END")
|
|
||||||
|
|
||||||
selout <- c("SELECTED_OUTPUT", "-high_precision true", "-reset false",
|
|
||||||
"-time", "-soln", "-temperature true", "-water true",
|
|
||||||
"-pH", "-pe", "-totals C Ca Cl Mg",
|
|
||||||
"-kinetic_reactants Calcite Dolomite", "-equilibrium O2g")
|
|
||||||
|
|
||||||
initsim <- c("SELECTED_OUTPUT", "-high_precision true",
|
|
||||||
"-reset false",
|
|
||||||
"USER_PUNCH",
|
|
||||||
"-head C Ca Cl Mg pH pe O2g Calcite Dolomite",
|
|
||||||
"10 PUNCH TOT(\"C\"), TOT(\"Ca\"), TOT(\"Cl\"), TOT(\"Mg\"), -LA(\"H+\"), -LA(\"e-\"), EQUI(\"O2g\"), EQUI(\"Calcite\"), EQUI(\"Dolomite\")",
|
|
||||||
"SOLUTION 1",
|
|
||||||
"units mol/kgw",
|
|
||||||
"temp 25.0", "water 1",
|
|
||||||
"pH 9.91 charge",
|
|
||||||
"pe 4.0",
|
|
||||||
"C 1.2279E-04",
|
|
||||||
"Ca 1.2279E-04",
|
|
||||||
"Cl 1E-12",
|
|
||||||
"Mg 1E-12",
|
|
||||||
"PURE 1",
|
|
||||||
"O2g -0.6788 10.0",
|
|
||||||
"Calcite 0.0 2.07E-3",
|
|
||||||
"Dolomite 0.0 0.0",
|
|
||||||
"END")
|
|
||||||
|
|
||||||
vecinj <- c("C"= 0,
|
|
||||||
"Ca" = 0,
|
|
||||||
"Cl" = 0.002,
|
|
||||||
"Mg" = 0.001,
|
|
||||||
"pe" = 4,
|
|
||||||
"pH" = 7)
|
|
||||||
|
|
||||||
init <- c("C(4)"= 1.2279E-4,
|
|
||||||
"Ca" =1.2279E-4,
|
|
||||||
"Cl" =0,
|
|
||||||
"Mg" =0,
|
|
||||||
"pe" =4,
|
|
||||||
"pH" =7,
|
|
||||||
"Calcite"= 2.07e-4,
|
|
||||||
"Dolomite"= 0)
|
|
||||||
|
|
||||||
|
|
||||||
## setup boundary conditions for transport - we have already read the
|
|
||||||
## GRID with the following code:
|
|
||||||
## grid <- Rmufits::ReadGrid(paste0(demodir,"/d2ascii.run.GRID.SUM"))
|
|
||||||
## cbound <- which(grid$cell$ACTNUM == 2)
|
|
||||||
## dput(cbound)
|
|
||||||
cbound <- c(1L, 50L, 100L, 150L, 200L, 250L, 300L, 350L, 400L, 450L, 500L,
|
|
||||||
550L, 600L, 650L, 700L, 750L, 800L, 850L, 900L, 950L, 1000L,
|
|
||||||
1050L, 1100L, 1150L, 1200L, 1250L, 1300L, 1350L, 1400L, 1450L,
|
|
||||||
1500L, 1550L, 1600L, 1650L, 1700L, 1750L, 1800L, 1850L, 1900L,
|
|
||||||
1950L, 2000L, 2050L, 2100L, 2150L, 2200L, 2250L, 2300L, 2350L,
|
|
||||||
2400L, 2450L, 2451L, 2452L, 2453L, 2454L, 2455L, 2456L, 2457L,
|
|
||||||
2458L, 2459L, 2460L, 2461L, 2462L, 2463L, 2464L, 2465L, 2466L,
|
|
||||||
2467L, 2468L, 2469L, 2470L, 2471L, 2472L, 2473L, 2474L, 2475L,
|
|
||||||
2476L, 2477L, 2478L, 2479L, 2480L, 2481L, 2482L, 2483L, 2484L,
|
|
||||||
2485L, 2486L, 2487L, 2488L, 2489L, 2490L, 2491L, 2492L, 2493L,
|
|
||||||
2494L, 2495L, 2496L, 2497L, 2498L, 2499L, 2500L)
|
|
||||||
|
|
||||||
boundinit <- matrix(rep(init[-c(7,8)], length(cbound)), byrow=TRUE, nrow=length(cbound))
|
|
||||||
myboundmat <- cbind(cbound,boundinit)
|
|
||||||
myboundmat[cbound==1, c(2:7)] <- vecinj
|
|
||||||
colnames(myboundmat) <- c("cbound", names(vecinj))
|
|
||||||
|
|
||||||
# TODO: dt and iterations
|
|
||||||
|
|
||||||
setup <- list(n=2500,
|
|
||||||
bound=myboundmat,
|
|
||||||
base=base,
|
|
||||||
first=selout,
|
|
||||||
initsim=initsim,
|
|
||||||
Cf=1,
|
|
||||||
prop=prop,
|
|
||||||
immobile=c(7,8,9),
|
|
||||||
kin= c(8,9),
|
|
||||||
ann=list(O2g=-0.1675),
|
|
||||||
phase="FLUX1",
|
|
||||||
density="DEN1",
|
|
||||||
reduce=FALSE,
|
|
||||||
snapshots=demodir, ## directory where we will read MUFITS SUM files
|
|
||||||
gridfile=paste0(demodir,"/d2ascii.run.GRID.SUM")
|
|
||||||
)
|
|
||||||
130
data/SimDolKtz.R
130
data/SimDolKtz.R
@ -1,130 +0,0 @@
|
|||||||
# library(RedModRphree)
|
|
||||||
# library(Rmufits)
|
|
||||||
# library(RcppVTK)
|
|
||||||
|
|
||||||
db <- RPhreeFile(system.file("extdata", "phreeqc_kin.dat",
|
|
||||||
package="RedModRphree"), is.db=TRUE)
|
|
||||||
|
|
||||||
phreeqc::phrLoadDatabaseString(db)
|
|
||||||
|
|
||||||
prop <- c("C","Ca","Cl","Mg","pH","pe","O2g", "Calcite","Dolomite")
|
|
||||||
signif_vector <- c(7,7,7,7,7,7,7,5,5)
|
|
||||||
prop_type <- c("act","act","act","act","logact","logact","ignore","act","act")
|
|
||||||
|
|
||||||
|
|
||||||
base <- c("SOLUTION 1",
|
|
||||||
"units mol/kgw",
|
|
||||||
"temp 25.0",
|
|
||||||
"water 1",
|
|
||||||
"pH 9.91 charge",
|
|
||||||
"pe 4.0",
|
|
||||||
"C 1.2279E-04",
|
|
||||||
"Ca 1.2279E-04",
|
|
||||||
"Mg 0.001",
|
|
||||||
"Cl 0.002",
|
|
||||||
"PURE 1",
|
|
||||||
"O2g -0.1675 10",
|
|
||||||
"KINETICS 1",
|
|
||||||
"-steps 100",
|
|
||||||
"-step_divide 100",
|
|
||||||
"-bad_step_max 2000",
|
|
||||||
"Calcite", "-m 0.000207",
|
|
||||||
"-parms 0.0032",
|
|
||||||
"Dolomite",
|
|
||||||
"-m 0.0",
|
|
||||||
"-parms 0.00032",
|
|
||||||
"END")
|
|
||||||
|
|
||||||
selout <- c("SELECTED_OUTPUT",
|
|
||||||
"-high_precision true",
|
|
||||||
"-reset false",
|
|
||||||
"-time",
|
|
||||||
"-soln",
|
|
||||||
"-temperature true",
|
|
||||||
"-water true",
|
|
||||||
"-pH",
|
|
||||||
"-pe",
|
|
||||||
"-totals C Ca Cl Mg",
|
|
||||||
"-kinetic_reactants Calcite Dolomite",
|
|
||||||
"-equilibrium O2g")
|
|
||||||
|
|
||||||
initsim <- c("SELECTED_OUTPUT",
|
|
||||||
"-high_precision true",
|
|
||||||
"-reset false",
|
|
||||||
"USER_PUNCH",
|
|
||||||
"-head C Ca Cl Mg pH pe O2g Calcite Dolomite",
|
|
||||||
"10 PUNCH TOT(\"C\"), TOT(\"Ca\"), TOT(\"Cl\"), TOT(\"Mg\"), -LA(\"H+\"), -LA(\"e-\"), EQUI(\"O2g\"), EQUI(\"Calcite\"), EQUI(\"Dolomite\")",
|
|
||||||
"SOLUTION 1",
|
|
||||||
"units mol/kgw",
|
|
||||||
"temp 25.0", "water 1",
|
|
||||||
"pH 9.91 charge",
|
|
||||||
"pe 4.0",
|
|
||||||
"C 1.2279E-04",
|
|
||||||
"Ca 1.2279E-04",
|
|
||||||
"Cl 1E-12",
|
|
||||||
"Mg 1E-12",
|
|
||||||
"PURE 1",
|
|
||||||
"O2g -0.6788 10.0",
|
|
||||||
"Calcite 0.0 2.07E-3",
|
|
||||||
"Dolomite 0.0 0.0",
|
|
||||||
"END")
|
|
||||||
|
|
||||||
vecinj <- c("C"= 0,
|
|
||||||
"Ca" = 0,
|
|
||||||
"Cl" = 0.002,
|
|
||||||
"Mg" = 0.001,
|
|
||||||
"pe" = 4,
|
|
||||||
"pH" = 7)
|
|
||||||
|
|
||||||
init <- c("C(4)"= 1.2279E-4,
|
|
||||||
"Ca" =1.2279E-4,
|
|
||||||
"Cl" =0,
|
|
||||||
"Mg" =0,
|
|
||||||
"pe" =4,
|
|
||||||
"pH" =7,
|
|
||||||
"Calcite"= 2.07e-4,
|
|
||||||
"Dolomite"= 0)
|
|
||||||
|
|
||||||
bound_elm <- c(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 11L, 12L, 13L, 14L,
|
|
||||||
15L, 16L, 17L, 18L, 19L, 20L, 21L, 22L, 23L, 24L, 25L, 26L, 27L,
|
|
||||||
28L, 29L, 30L, 31L, 32L, 33L, 34L, 35L, 36L, 37L, 38L, 39L, 40L,
|
|
||||||
41L, 42L, 43L, 44L, 45L, 46L, 47L, 48L, 49L, 50L, 51L, 52L, 53L,
|
|
||||||
54L, 55L, 56L, 57L, 58L, 59L, 60L, 61L, 62L, 63L, 64L, 65L, 66L,
|
|
||||||
67L, 68L, 69L, 70L, 71L, 72L, 73L, 74L, 75L, 76L, 77L, 78L, 79L,
|
|
||||||
80L, 81L, 82L, 83L, 84L, 85L, 86L, 87L, 88L, 89L, 90L, 91L, 92L,
|
|
||||||
93L, 94L, 95L, 96L, 97L, 98L, 99L, 100L, 101L, 102L, 103L, 104L,
|
|
||||||
105L, 106L, 107L, 108L, 214L, 215L)
|
|
||||||
|
|
||||||
inj_elm <- c(7426L, 18233L, 29040L, 39847L,
|
|
||||||
50654L, 61461L, 72268L, 83075L, 93882L, 104689L, 115496L, 126303L,
|
|
||||||
137110L, 147917L, 158724L, 169531L, 180338L, 191145L, 201952L,
|
|
||||||
212759L, 223566L, 234373L, 245180L, 255987L, 266794L, 277601L,
|
|
||||||
288408L, 299215L, 310022L, 320829L, 331636L, 342443L, 353250L,
|
|
||||||
364057L, 374864L, 385671L, 396478L, 407285L, 418092L, 428899L,
|
|
||||||
439706L, 450513L, 461320L, 472127L, 482934L, 493741L, 504548L,
|
|
||||||
515355L)
|
|
||||||
|
|
||||||
cbound <- inj_elm
|
|
||||||
|
|
||||||
boundinit <- matrix(rep(vecinj, length(cbound)), ncol=length(vecinj), byrow=TRUE)
|
|
||||||
myboundmat <- cbind(cbound,boundinit)
|
|
||||||
|
|
||||||
## distinguish between injection and real boundaries
|
|
||||||
colnames(myboundmat) <- c("cbound", names(vecinj))
|
|
||||||
|
|
||||||
setup <- list(n=648420,
|
|
||||||
bound=myboundmat,
|
|
||||||
base=base,
|
|
||||||
first=selout,
|
|
||||||
initsim=initsim,
|
|
||||||
Cf=1,
|
|
||||||
prop=prop,
|
|
||||||
immobile=c(7,8,9),
|
|
||||||
kin= c(8,9),
|
|
||||||
ann=list(O2g=-0.1675),
|
|
||||||
phase="FLUX1",
|
|
||||||
density="DENS",
|
|
||||||
reduce=FALSE,
|
|
||||||
snapshots="snaps/AllSnaps_cmp_v3.rds",
|
|
||||||
gridfile ="snaps/GridKtz_cmp_v3.rds"
|
|
||||||
)
|
|
||||||
File diff suppressed because it is too large
Load Diff
@ -9,10 +9,12 @@ if(DOXYGEN_FOUND)
|
|||||||
set(DOXYGEN_DISABLE_INDEX NO)
|
set(DOXYGEN_DISABLE_INDEX NO)
|
||||||
set(DOXYGEN_GENERATE_TREEVIEW YES)
|
set(DOXYGEN_GENERATE_TREEVIEW YES)
|
||||||
set(DOXYGEN_FULL_SIDEBAR YES)
|
set(DOXYGEN_FULL_SIDEBAR YES)
|
||||||
|
set(DOXYGEN_PROJECT_NUMBER ${POET_VERSION})
|
||||||
|
|
||||||
doxygen_add_docs(doxygen
|
doxygen_add_docs(doxygen
|
||||||
${PROJECT_SOURCE_DIR}/include
|
${PROJECT_SOURCE_DIR}/include
|
||||||
${PROJECT_SOURCE_DIR}/README.md
|
${PROJECT_SOURCE_DIR}/README.md
|
||||||
|
${PROJECT_SOURCE_DIR}/docs/Input_Scripts.md
|
||||||
${PROJECT_SOURCE_DIR}/docs/Output.md
|
${PROJECT_SOURCE_DIR}/docs/Output.md
|
||||||
COMMENT "Generate html pages")
|
COMMENT "Generate html pages")
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
2633
docs/Doxyfile.in
2633
docs/Doxyfile.in
File diff suppressed because it is too large
Load Diff
95
docs/Input_Scripts.md
Normal file
95
docs/Input_Scripts.md
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
# Input Scripts
|
||||||
|
|
||||||
|
In the following the expected schemes of the input scripts is described.
|
||||||
|
Therefore, each section of the input script gets its own chapter. All sections
|
||||||
|
should return a `list` as results, which are concatenated to one setup list at
|
||||||
|
the end of the file. All values must have the same name in order to get parsed
|
||||||
|
by POET.
|
||||||
|
|
||||||
|
## Grid initialization
|
||||||
|
|
||||||
|
| name | type | description |
|
||||||
|
|----------------|----------------|-----------------------------------------------------------------------|
|
||||||
|
| `n_cells` | Numeric Vector | Number of cells in each direction |
|
||||||
|
| `s_cells` | Numeric Vector | Spatial resolution of grid in each direction |
|
||||||
|
| `type` | String | Type of initialization, can be set to *scratch*, *phreeqc* or *rds* |
|
||||||
|
| `init_cell` | Data Frame | Containing all exactly one value per species to initialize the field. |
|
||||||
|
| `props` | String Vector | Names of all species |
|
||||||
|
| `database` | String | Path to Phreeqc database |
|
||||||
|
| `input_script` | String | Path to Phreeqc initial script |
|
||||||
|
|
||||||
|
## Diffusion parameters
|
||||||
|
|
||||||
|
| name | type | description |
|
||||||
|
|----------------|----------------------|-------------------------------------------|
|
||||||
|
| `init` | Named Numeric Vector | Initial state for each diffused species |
|
||||||
|
| `vecinj` | Data Frame | Defining all boundary conditions row wise |
|
||||||
|
| `vecinj_inner` | List of Triples | Inner boundaries |
|
||||||
|
| `vecinj_index` | List of 4 elements | Ghost nodes boundary conditions |
|
||||||
|
| `alpha` | Named Numeric Vector | Constant alpha for each species |
|
||||||
|
|
||||||
|
### Remark on boundary conditions
|
||||||
|
|
||||||
|
Each boundary condition should be defined in `vecinj` as a data frame, where one
|
||||||
|
row holds one boundary condition.
|
||||||
|
|
||||||
|
To define inner (constant) boundary conditions, use a list of triples in
|
||||||
|
`vecinj_inner`, where each triples is defined by $(i,x,y)$. $i$ is defining the
|
||||||
|
boundary condition, referencing to the row in `vecinj`. $x$ and $y$ coordinates
|
||||||
|
then defining the position inside the grid.
|
||||||
|
|
||||||
|
Ghost nodes are set by `vecinj_index` which is a list containing boundaries for
|
||||||
|
each celestial direction (**important**: named by `N, E, S, W`). Each direction
|
||||||
|
is a numeric vector, also representing a row index of the `vecinj` data frame
|
||||||
|
for each ghost node, starting at the left-most and upper cell respectively. By
|
||||||
|
setting the boundary condition to $0$, the ghost node is set as closed boundary.
|
||||||
|
|
||||||
|
#### Example
|
||||||
|
|
||||||
|
Suppose you have a `vecinj` data frame defining 2 boundary conditions and a grid
|
||||||
|
consisting of $10 \times 10$ grid cells. Grid cell $(1,1)$ should be set to the
|
||||||
|
first boundary condition and $(5,6)$ to the second. Also, all boundary
|
||||||
|
conditions for the ghost nodes should be closed. Except the southern boundary,
|
||||||
|
which should be set to the first boundary condition injection. The following
|
||||||
|
setup describes how to setup your initial script, where `n` and `m` are the
|
||||||
|
grids cell count for each direction ($n = m = 10$):
|
||||||
|
|
||||||
|
```R
|
||||||
|
vecinj_inner <- list (
|
||||||
|
l1 = c(1, 1, 1),
|
||||||
|
l2 = c(2, 5, 6)
|
||||||
|
)
|
||||||
|
|
||||||
|
vecinj_index <- list(
|
||||||
|
"N" = rep(0, n),
|
||||||
|
"E" = rep(0, m),
|
||||||
|
"S" = rep(1, n),
|
||||||
|
"W" = rep(0, m)
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Chemistry parameters
|
||||||
|
|
||||||
|
| name | type | description |
|
||||||
|
|----------------|--------|-----------------------------------|
|
||||||
|
| `database` | String | Path to the Phreeqc database |
|
||||||
|
| `input_script` | String | Path the the Phreeqc input script |
|
||||||
|
|
||||||
|
## Final setup
|
||||||
|
|
||||||
|
| name | type | description |
|
||||||
|
|----------------|----------------|------------------------------------------------------------|
|
||||||
|
| `grid` | List | Grid parameter list |
|
||||||
|
| `diffusion` | List | Diffusion parameter list |
|
||||||
|
| `chemistry` | List | Chemistry parameter list |
|
||||||
|
| `iterations` | Numeric Value | Count of iterations |
|
||||||
|
| `timesteps` | Numeric Vector | $\Delta t$ to use for specific iteration |
|
||||||
|
| `store_result` | Boolean | Indicates if results should be stored |
|
||||||
|
| `out_save` | Numeric Vector | *optional:* At which iteration the states should be stored |
|
||||||
|
|
||||||
|
### DHT setup
|
||||||
|
|
||||||
|
| name | type | description |
|
||||||
|
|-----------------|----------------|---------------------------------------------------------------------------------|
|
||||||
|
| `signif_vector` | Numeric Vector | Indicates significant digits to use for DHT rounding. Order of `props` vector. |
|
||||||
|
| `prop_type` | String Vector | Set type of species for rounding, can be left blank or set to *act* or *ignore* |
|
||||||
@ -46,11 +46,13 @@ and possible to read out within a R runtime with
|
|||||||
If running parallel there are also measured timings which are subsets of
|
If running parallel there are also measured timings which are subsets of
|
||||||
*simtime\_chemistry*.
|
*simtime\_chemistry*.
|
||||||
|
|
||||||
| Value | Description |
|
| Value | Description |
|
||||||
|----------------------------|----------------------------------------------------|
|
|-----------------------|-----------------------------------------------------------|
|
||||||
| simtime\_workers | time spent in send/recv loop of master |
|
| chemistry\_loop | time spent in send/recv loop of master |
|
||||||
| simtime\_chemistry\_master | sequential part of master chemistry |
|
| chemistry\_sequential | sequential part of master chemistry |
|
||||||
| phreeqc | measured time of each worker in PHREEQC subroutine |
|
| idle\_master | idling time (waiting for any free worker) of the master |
|
||||||
|
| idle\_worker | idling time (waiting for work from master) of the workers |
|
||||||
|
| phreeqc\_time | accumulated times for Phreeqc calls of every worker |
|
||||||
|
|
||||||
### DHT usage {#DHT-usage}
|
### DHT usage {#DHT-usage}
|
||||||
|
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
Subproject commit cc5ef0ff37233d24108a793a74abe649dcae54b7
|
Subproject commit f862889b693507458d450c6319abe5e1dce030f7
|
||||||
@ -1,273 +0,0 @@
|
|||||||
/*
|
|
||||||
** Copyright (C) 2018-2021 Alexander Lindemann, Max Luebke (University of
|
|
||||||
** Potsdam)
|
|
||||||
**
|
|
||||||
** Copyright (C) 2018-2022 Marco De Lucia, Max Luebke (GFZ Potsdam)
|
|
||||||
**
|
|
||||||
** POET is free software; you can redistribute it and/or modify it under the
|
|
||||||
** terms of the GNU General Public License as published by the Free Software
|
|
||||||
** Foundation; either version 2 of the License, or (at your option) any later
|
|
||||||
** version.
|
|
||||||
**
|
|
||||||
** POET is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
||||||
** WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
||||||
** A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
||||||
**
|
|
||||||
** You should have received a copy of the GNU General Public License along with
|
|
||||||
** this program; if not, write to the Free Software Foundation, Inc., 51
|
|
||||||
** Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef CHEMSIMPAR_H
|
|
||||||
#define CHEMSIMPAR_H
|
|
||||||
|
|
||||||
#include "ChemSimSeq.hpp"
|
|
||||||
#include "DHT_Wrapper.hpp"
|
|
||||||
#include "Grid.hpp"
|
|
||||||
#include "RInside.h"
|
|
||||||
#include "SimParams.hpp"
|
|
||||||
#include "poet/PhreeqcWrapper.hpp"
|
|
||||||
|
|
||||||
#include <array>
|
|
||||||
#include <cstdint>
|
|
||||||
#include <mpi.h>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
/** Number of data elements that are kept free at each work package */
|
|
||||||
#define BUFFER_OFFSET 5
|
|
||||||
|
|
||||||
/** Message tag indicating work */
|
|
||||||
#define TAG_WORK 42
|
|
||||||
/** Message tag indicating to finish loop */
|
|
||||||
#define TAG_FINISH 43
|
|
||||||
/** Message tag indicating timing profiling */
|
|
||||||
#define TAG_TIMING 44
|
|
||||||
/** Message tag indicating collecting DHT performance */
|
|
||||||
#define TAG_DHT_PERF 45
|
|
||||||
/** Message tag indicating simulation reached the end of an itertation */
|
|
||||||
#define TAG_DHT_ITER 47
|
|
||||||
|
|
||||||
namespace poet {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Class providing execution of master chemistry
|
|
||||||
*
|
|
||||||
* Providing member functions to run an iteration and to end a simulation. Also
|
|
||||||
* a loop to send and recv pkgs from workers is implemented.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class ChemMaster : public BaseChemModule {
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Construct a new ChemMaster object
|
|
||||||
*
|
|
||||||
* The following steps are executed to create a new object of ChemMaster:
|
|
||||||
* -# all needed simulation parameters are extracted
|
|
||||||
* -# memory is allocated
|
|
||||||
* -# distribution of work packages is calculated
|
|
||||||
*
|
|
||||||
* @param params Simulation parameters as SimParams object
|
|
||||||
* @param R_ R runtime
|
|
||||||
* @param grid_ Grid object
|
|
||||||
*/
|
|
||||||
ChemMaster(SimParams ¶ms, RInside &R_, Grid &grid_);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Destroy the ChemMaster object
|
|
||||||
*
|
|
||||||
* By freeing ChemMaster all buffers allocated in the Constructor are freed.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
~ChemMaster();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Run iteration of simulation in parallel mode
|
|
||||||
*
|
|
||||||
* To run the chemistry simulation parallel following steps are done:
|
|
||||||
*
|
|
||||||
* -# 'Shuffle' the grid by previously calculated distribution of work
|
|
||||||
* packages. Convert R grid to C memory area.
|
|
||||||
* -# Start the send/recv loop.
|
|
||||||
* Detailed description in sendPkgs respectively in recvPkgs.
|
|
||||||
* -# 'Unshuffle'
|
|
||||||
* the grid and convert C memory area to R grid.
|
|
||||||
* -# Run 'master_chemistry'
|
|
||||||
*
|
|
||||||
* The main tasks are instrumented with time measurements.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void Simulate(double dt);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief End chemistry simulation.
|
|
||||||
*
|
|
||||||
* Notify the worker to finish their 'work'-loop. This is done by sending
|
|
||||||
* every worker an empty message with the tag TAG_FINISH. Now the master will
|
|
||||||
* receive measured times and DHT metrics from all worker one after another.
|
|
||||||
* Finally he will write all data to the R runtime and return this function.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void End();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the send time
|
|
||||||
*
|
|
||||||
* Time spent in send loop.
|
|
||||||
*
|
|
||||||
* @return double sent time in seconds
|
|
||||||
*/
|
|
||||||
double getSendTime();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the recv time
|
|
||||||
*
|
|
||||||
* Time spent in recv loop.
|
|
||||||
*
|
|
||||||
* @return double recv time in seconds
|
|
||||||
*/
|
|
||||||
double getRecvTime();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the idle time
|
|
||||||
*
|
|
||||||
* Time master was idling in MPI_Probe of recv loop.
|
|
||||||
*
|
|
||||||
* @return double idle time in seconds
|
|
||||||
*/
|
|
||||||
double getIdleTime();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the Worker time
|
|
||||||
*
|
|
||||||
* Time spent in whole send/recv loop.
|
|
||||||
*
|
|
||||||
* @return double worker time in seconds
|
|
||||||
*/
|
|
||||||
double getWorkerTime();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the ChemMaster time
|
|
||||||
*
|
|
||||||
* Time spent in 'master_chemistry' R function.
|
|
||||||
*
|
|
||||||
* @return double ChemMaster time in seconds
|
|
||||||
*/
|
|
||||||
double getChemMasterTime();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the sequential time
|
|
||||||
*
|
|
||||||
* Time master executed code which must be run sequential.
|
|
||||||
*
|
|
||||||
* @return double seqntial time in seconds.
|
|
||||||
*/
|
|
||||||
double getSeqTime();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void printProgressbar(int count_pkgs, int n_wp, int barWidth = 70);
|
|
||||||
inline void sendPkgs(int &pkg_to_send, int &count_pkgs, int &free_workers,
|
|
||||||
double *&work_pointer, const double &dt,
|
|
||||||
const uint32_t iteration);
|
|
||||||
inline void recvPkgs(int &pkg_to_recv, bool to_send, int &free_workers);
|
|
||||||
void shuffleField(const std::vector<double> &in_field, uint32_t size_per_prop,
|
|
||||||
uint32_t prop_count, double *out_buffer);
|
|
||||||
void unshuffleField(const double *in_buffer, uint32_t size_per_prop,
|
|
||||||
uint32_t prop_count, std::vector<double> &out_field);
|
|
||||||
|
|
||||||
uint32_t wp_size;
|
|
||||||
bool dht_enabled;
|
|
||||||
|
|
||||||
double send_t = 0.f;
|
|
||||||
double recv_t = 0.f;
|
|
||||||
double master_idle = 0.f;
|
|
||||||
double worker_t = 0.f;
|
|
||||||
double chem_master = 0.f;
|
|
||||||
double seq_t = 0.f;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char has_work;
|
|
||||||
double *send_addr;
|
|
||||||
} worker_struct;
|
|
||||||
|
|
||||||
worker_struct *workerlist;
|
|
||||||
double *send_buffer;
|
|
||||||
double *mpi_buffer;
|
|
||||||
std::vector<uint32_t> wp_sizes_vector;
|
|
||||||
poet::StateMemory *state;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Class providing execution of worker chemistry
|
|
||||||
*
|
|
||||||
* Providing mainly a function to loop and wait for messages from the master.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class ChemWorker : public BaseChemModule {
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Construct a new ChemWorker object
|
|
||||||
*
|
|
||||||
* The following steps are executed to create a new object of ChemWorker:
|
|
||||||
* -# all needed simulation parameters are extracted
|
|
||||||
* -# memory is allocated
|
|
||||||
* -# Preparetion to create a DHT
|
|
||||||
* -# and finally create a new DHT_Wrapper
|
|
||||||
*
|
|
||||||
* @param params Simulation parameters as SimParams object
|
|
||||||
* @param R_ R runtime
|
|
||||||
* @param grid_ Grid object
|
|
||||||
* @param dht_comm Communicator addressing all processes marked as worker
|
|
||||||
*/
|
|
||||||
ChemWorker(SimParams ¶ms, RInside &R_, Grid &grid_, MPI_Comm dht_comm);
|
|
||||||
|
|
||||||
void InitModule(poet::ChemistryParams &chem_params);
|
|
||||||
/**
|
|
||||||
* @brief Destroy the ChemWorker object
|
|
||||||
*
|
|
||||||
* Therefore all buffers are freed and the DHT_Wrapper object is destroyed.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
~ChemWorker();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Start the 'work' loop
|
|
||||||
*
|
|
||||||
* Loop in an endless loop. At the beginning probe for a message from the
|
|
||||||
* master process. If there is a receivable message evaluate the message tag.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void loop();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void doWork(MPI_Status &probe_status);
|
|
||||||
void postIter();
|
|
||||||
void finishWork();
|
|
||||||
void writeFile();
|
|
||||||
void readFile();
|
|
||||||
|
|
||||||
uint32_t wp_size;
|
|
||||||
uint32_t dht_size_per_process;
|
|
||||||
uint32_t iteration = 0;
|
|
||||||
|
|
||||||
bool dht_enabled;
|
|
||||||
bool dt_differ;
|
|
||||||
int dht_snaps;
|
|
||||||
std::string dht_file;
|
|
||||||
std::vector<bool> dht_flags;
|
|
||||||
double *mpi_buffer_results;
|
|
||||||
DHT_Wrapper *dht;
|
|
||||||
|
|
||||||
std::array<double, 3> timing;
|
|
||||||
double idle_t = 0.f;
|
|
||||||
uint32_t phreeqc_count = 0;
|
|
||||||
|
|
||||||
double *mpi_buffer;
|
|
||||||
|
|
||||||
uint32_t ncomps;
|
|
||||||
std::string out_dir;
|
|
||||||
|
|
||||||
PhreeqcWrapper *phreeqc_rm = std::nullptr_t();
|
|
||||||
};
|
|
||||||
} // namespace poet
|
|
||||||
#endif // CHEMSIMPAR_H
|
|
||||||
@ -1,131 +0,0 @@
|
|||||||
/*
|
|
||||||
** Copyright (C) 2018-2021 Alexander Lindemann, Max Luebke (University of
|
|
||||||
** Potsdam)
|
|
||||||
**
|
|
||||||
** Copyright (C) 2018-2022 Marco De Lucia, Max Luebke (GFZ Potsdam)
|
|
||||||
**
|
|
||||||
** POET is free software; you can redistribute it and/or modify it under the
|
|
||||||
** terms of the GNU General Public License as published by the Free Software
|
|
||||||
** Foundation; either version 2 of the License, or (at your option) any later
|
|
||||||
** version.
|
|
||||||
**
|
|
||||||
** POET is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
||||||
** WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
||||||
** A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
||||||
**
|
|
||||||
** You should have received a copy of the GNU General Public License along with
|
|
||||||
** this program; if not, write to the Free Software Foundation, Inc., 51
|
|
||||||
** Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef CHEMSIMSEQ_H
|
|
||||||
#define CHEMSIMSEQ_H
|
|
||||||
|
|
||||||
#include "DHT_Wrapper.hpp"
|
|
||||||
#include "Grid.hpp"
|
|
||||||
#include "PhreeqcWrapper.hpp"
|
|
||||||
#include "RInside.h"
|
|
||||||
#include "SimParams.hpp"
|
|
||||||
#include <bits/stdint-uintn.h>
|
|
||||||
#include <cstddef>
|
|
||||||
#include <cstdint>
|
|
||||||
#include <mpi.h>
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
/** Number of data elements that are kept free at each work package */
|
|
||||||
#define BUFFER_OFFSET 5
|
|
||||||
|
|
||||||
/** Message tag indicating work */
|
|
||||||
#define TAG_WORK 42
|
|
||||||
/** Message tag indicating to finish loop */
|
|
||||||
#define TAG_FINISH 43
|
|
||||||
/** Message tag indicating timing profiling */
|
|
||||||
#define TAG_TIMING 44
|
|
||||||
/** Message tag indicating collecting DHT performance */
|
|
||||||
#define TAG_DHT_PERF 45
|
|
||||||
/** Message tag indicating simulation reached the end of an itertation */
|
|
||||||
#define TAG_DHT_ITER 47
|
|
||||||
|
|
||||||
namespace poet {
|
|
||||||
/**
|
|
||||||
* @brief Base class of the chemical simulation
|
|
||||||
*
|
|
||||||
* Providing member functions to run an iteration and to end a simulation. Also
|
|
||||||
* containing basic parameters for simulation.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
class BaseChemModule {
|
|
||||||
public:
|
|
||||||
BaseChemModule(SimParams ¶ms, RInside &R_, Grid &grid_);
|
|
||||||
|
|
||||||
virtual void InitModule(poet::ChemistryParams &chem_params){};
|
|
||||||
|
|
||||||
static constexpr const char *CHEMISTRY_MODULE_NAME = "state_c";
|
|
||||||
|
|
||||||
protected:
|
|
||||||
int world_rank;
|
|
||||||
int world_size;
|
|
||||||
RInside &R;
|
|
||||||
|
|
||||||
Grid &grid;
|
|
||||||
double chem_t = 0.f;
|
|
||||||
double current_sim_time = 0;
|
|
||||||
|
|
||||||
uint32_t n_cells_per_prop;
|
|
||||||
std::vector<std::string> prop_names;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ChemSeq : public BaseChemModule {
|
|
||||||
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief Construct a new ChemSim object
|
|
||||||
*
|
|
||||||
* Creating a new instance of class ChemSim will just extract simulation
|
|
||||||
* parameters from SimParams object.
|
|
||||||
*
|
|
||||||
* @param params SimParams object
|
|
||||||
* @param R_ R runtime
|
|
||||||
* @param grid_ Initialized grid
|
|
||||||
*/
|
|
||||||
ChemSeq(SimParams ¶ms, RInside &R_, Grid &grid_);
|
|
||||||
|
|
||||||
~ChemSeq();
|
|
||||||
|
|
||||||
void InitModule(poet::ChemistryParams &chem_params);
|
|
||||||
/**
|
|
||||||
* @brief Run iteration of simulation in sequential mode
|
|
||||||
*
|
|
||||||
* This will call the correspondending R function slave_chemistry, followed by
|
|
||||||
* the execution of master_chemistry.
|
|
||||||
*
|
|
||||||
* @todo change function name. Maybe 'slave' to 'seq'.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void Simulate(double dt);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief End simulation
|
|
||||||
*
|
|
||||||
* End the simulation by distribute the measured runtime of simulation to the
|
|
||||||
* R runtime.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void End();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Get the Chemistry Time
|
|
||||||
*
|
|
||||||
* @return double Runtime of sequential chemistry simulation in seconds
|
|
||||||
*/
|
|
||||||
double getChemistryTime();
|
|
||||||
|
|
||||||
private:
|
|
||||||
poet::StateMemory *state;
|
|
||||||
PhreeqcWrapper *phreeqc_rm = std::nullptr_t();
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace poet
|
|
||||||
#endif // CHEMSIMSEQ_H
|
|
||||||
413
include/poet/ChemistryModule.hpp
Normal file
413
include/poet/ChemistryModule.hpp
Normal file
@ -0,0 +1,413 @@
|
|||||||
|
#ifndef CHEMISTRYMODULE_H_
|
||||||
|
#define CHEMISTRYMODULE_H_
|
||||||
|
|
||||||
|
#include "IrmResult.h"
|
||||||
|
#include "PhreeqcRM.h"
|
||||||
|
#include "poet/DHT_Wrapper.hpp"
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <mpi.h>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace poet {
|
||||||
|
/**
|
||||||
|
* \brief Wrapper around PhreeqcRM to provide POET specific parallelization with
|
||||||
|
* easy access.
|
||||||
|
*/
|
||||||
|
class ChemistryModule : public PhreeqcRM {
|
||||||
|
public:
|
||||||
|
#ifdef POET_USE_PRM
|
||||||
|
/**
|
||||||
|
* Creates a new instance of Chemistry module with given grid cell count and
|
||||||
|
* using MPI communicator.
|
||||||
|
*
|
||||||
|
* Constructor is just a wrapper around PhreeqcRM's constructor, so just calls
|
||||||
|
* the base class constructor.
|
||||||
|
*
|
||||||
|
* \param nxyz Count of grid cells.
|
||||||
|
* \param communicator MPI communicator where work will be distributed.
|
||||||
|
*/
|
||||||
|
ChemistryModule(uint32_t nxyz, MPI_Comm communicator)
|
||||||
|
: PhreeqcRM(nxyz, communicator), n_cells(nxyz){};
|
||||||
|
#else
|
||||||
|
/**
|
||||||
|
* Creates a new instance of Chemistry module with given grid cell count, work
|
||||||
|
* package size and communicator.
|
||||||
|
*
|
||||||
|
* This constructor shall only be called by the master. To create workers, see
|
||||||
|
* ChemistryModule::createWorker .
|
||||||
|
*
|
||||||
|
* When the use of parallelization is intended, the nxyz value shall be set to
|
||||||
|
* 1 to save memory and only one node is needed for initialization.
|
||||||
|
*
|
||||||
|
* \param nxyz Count of grid cells to allocate and initialize for each
|
||||||
|
* process. For parellel use set to 1 at the master.
|
||||||
|
* \param wp_size Count of grid cells to fill each work package at maximum.
|
||||||
|
* \param communicator MPI communicator to distribute work in.
|
||||||
|
*/
|
||||||
|
ChemistryModule(uint32_t nxyz, uint32_t wp_size, MPI_Comm communicator);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deconstructor, which frees DHT data structure if used.
|
||||||
|
*/
|
||||||
|
~ChemistryModule();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the input script and extract information needed during runtime.
|
||||||
|
*
|
||||||
|
* **Only run by master**.
|
||||||
|
*
|
||||||
|
* Database must be loaded beforehand.
|
||||||
|
*
|
||||||
|
* \param input_script_path Path to input script to parse.
|
||||||
|
*/
|
||||||
|
void RunInitFile(const std::string &input_script_path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run the chemical simulation with parameters set.
|
||||||
|
*/
|
||||||
|
void RunCells();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the chemical field.
|
||||||
|
*/
|
||||||
|
auto GetField() const { return this->field; }
|
||||||
|
/**
|
||||||
|
* Returns all known species names, including not only aqueous species, but
|
||||||
|
* also equilibrium, exchange, surface and kinetic reactants.
|
||||||
|
*/
|
||||||
|
auto GetPropNames() const { return this->prop_names; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the accumulated runtime in seconds for chemical simulation.
|
||||||
|
*/
|
||||||
|
auto GetChemistryTime() const { return this->chem_t; }
|
||||||
|
|
||||||
|
#ifndef POET_USE_PRM
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new worker instance inside given MPI communicator.
|
||||||
|
*
|
||||||
|
* Wraps communication needed before instanciation can take place.
|
||||||
|
*
|
||||||
|
* \param communicator MPI communicator to distribute work in.
|
||||||
|
*
|
||||||
|
* \returns A worker instance with fixed work package size.
|
||||||
|
*/
|
||||||
|
static ChemistryModule createWorker(MPI_Comm communicator);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default work package size.
|
||||||
|
*/
|
||||||
|
static constexpr uint32_t CHEM_DEFAULT_WP_SIZE = 5;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Intended to alias input parameters for grid initialization with a single
|
||||||
|
* value per species.
|
||||||
|
*/
|
||||||
|
using SingleCMap = std::unordered_map<std::string, double>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Intended to alias input parameters for grid initialization with mutlitple
|
||||||
|
* values per species.
|
||||||
|
*/
|
||||||
|
using VectorCMap = std::unordered_map<std::string, std::vector<double>>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enumerating DHT file options
|
||||||
|
*/
|
||||||
|
enum {
|
||||||
|
DHT_FILES_DISABLED = 0, //!< disabled file output
|
||||||
|
DHT_FILES_SIMEND, //!< only output of snapshot after simulation
|
||||||
|
DHT_FILES_ITEREND //!< output snapshots after each iteration
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes field with a "DataFrame" containing a single value for each
|
||||||
|
* species.
|
||||||
|
*
|
||||||
|
* Each species must have been previously found by
|
||||||
|
* ChemistryModule::RunInitFile.
|
||||||
|
*
|
||||||
|
* \exception std::domain_error Species name of map is not defined.
|
||||||
|
*
|
||||||
|
* \param n_cells Count of cells for each species.
|
||||||
|
* \param mapped_values Unordered map containing one double value for each
|
||||||
|
* specified species.
|
||||||
|
*/
|
||||||
|
void InitializeField(uint32_t n_cells, const SingleCMap &mapped_values);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes field with a "DataFrame" containing a vector of values for each
|
||||||
|
* species.
|
||||||
|
*
|
||||||
|
* Each species must have been previously found by
|
||||||
|
* ChemistryModule::RunInitFile.
|
||||||
|
*
|
||||||
|
* There is no check if vector length matches count of grid cells defined.
|
||||||
|
*
|
||||||
|
* \exception std::domain_error Species name of map is not defined.
|
||||||
|
*
|
||||||
|
* \param mapped_values Unordered map containing a vector of multiple values.
|
||||||
|
* Size of the vectors shall be the count of grid cells defined previously.
|
||||||
|
*/
|
||||||
|
void InitializeField(const VectorCMap &mapped_values);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* **Only called by workers!** Start the worker listening loop.
|
||||||
|
*/
|
||||||
|
void WorkerLoop();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* **Called by master** Advise the workers to break the loop.
|
||||||
|
*/
|
||||||
|
void MasterLoopBreak();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* **Master only** Enables DHT usage for the workers.
|
||||||
|
*
|
||||||
|
* If called multiple times enabling the DHT, the current state of DHT will be
|
||||||
|
* overwritten with a new instance of the DHT.
|
||||||
|
*
|
||||||
|
* \param enable Enables or disables the usage of the DHT.
|
||||||
|
* \param size_mb Size in megabyte to allocate for the DHT if enabled.
|
||||||
|
*/
|
||||||
|
void SetDHTEnabled(bool enable, uint32_t size_mb);
|
||||||
|
/**
|
||||||
|
* **Master only** Set DHT snapshots to specific mode.
|
||||||
|
*
|
||||||
|
* \param type DHT snapshot mode.
|
||||||
|
* \param out_dir Path to output DHT snapshots.
|
||||||
|
*/
|
||||||
|
void SetDHTSnaps(int type, const std::string &out_dir);
|
||||||
|
/**
|
||||||
|
* **Master only** Set the vector with significant digits to round before
|
||||||
|
* inserting into DHT.
|
||||||
|
*
|
||||||
|
* \param signif_vec Vector defining significant digit for each species. Order
|
||||||
|
* is defined by prop_type vector (ChemistryModule::GetPropNames).
|
||||||
|
*/
|
||||||
|
void SetDHTSignifVector(std::vector<uint32_t> signif_vec);
|
||||||
|
/**
|
||||||
|
* **Master only** Set the DHT rounding type of each species. See
|
||||||
|
* DHT_PROP_TYPES enumemartion for explanation.
|
||||||
|
*
|
||||||
|
* \param proptype_vec Vector defining DHT prop type for each species.
|
||||||
|
*/
|
||||||
|
void SetDHTPropTypeVector(std::vector<uint32_t> proptype_vec);
|
||||||
|
/**
|
||||||
|
* **Master only** Load the state of the DHT from given file.
|
||||||
|
*
|
||||||
|
* \param input_file File to load data from.
|
||||||
|
*/
|
||||||
|
void ReadDHTFile(const std::string &input_file);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overwrite the current field state by another field.
|
||||||
|
*
|
||||||
|
* There are no checks if new vector dimensions matches expected sizes etc.
|
||||||
|
*
|
||||||
|
* \param field New input field. Current field state of the instance will be
|
||||||
|
* overwritten.
|
||||||
|
*/
|
||||||
|
void SetField(const std::vector<double> &field) { this->field = field; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* **Master only** Return count of grid cells.
|
||||||
|
*/
|
||||||
|
auto GetNCells() const { return this->n_cells; }
|
||||||
|
/**
|
||||||
|
* **Master only** Return work package size.
|
||||||
|
*/
|
||||||
|
auto GetWPSize() const { return this->wp_size; }
|
||||||
|
/**
|
||||||
|
* **Master only** Return the time in seconds the master spent waiting for any
|
||||||
|
* free worker.
|
||||||
|
*/
|
||||||
|
auto GetMasterIdleTime() const { return this->idle_t; }
|
||||||
|
/**
|
||||||
|
* **Master only** Return the time in seconds the master spent in sequential
|
||||||
|
* part of the simulation, including times for shuffling/unshuffling field
|
||||||
|
* etc.
|
||||||
|
*/
|
||||||
|
auto GetMasterSequentialTime() const { return this->seq_t; }
|
||||||
|
/**
|
||||||
|
* **Master only** Return the time in seconds the master spent in the
|
||||||
|
* send/receive loop.
|
||||||
|
*/
|
||||||
|
auto GetMasterLoopTime() const { return this->send_recv_t; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* **Master only** Collect and return all accumulated timings recorded by
|
||||||
|
* workers to run Phreeqc simulation.
|
||||||
|
*
|
||||||
|
* \return Vector of all accumulated Phreeqc timings.
|
||||||
|
*/
|
||||||
|
std::vector<double> GetWorkerPhreeqcTimings() const;
|
||||||
|
/**
|
||||||
|
* **Master only** Collect and return all accumulated timings recorded by
|
||||||
|
* workers to get values from the DHT.
|
||||||
|
*
|
||||||
|
* \return Vector of all accumulated DHT get times.
|
||||||
|
*/
|
||||||
|
std::vector<double> GetWorkerDHTGetTimings() const;
|
||||||
|
/**
|
||||||
|
* **Master only** Collect and return all accumulated timings recorded by
|
||||||
|
* workers to write values to the DHT.
|
||||||
|
*
|
||||||
|
* \return Vector of all accumulated DHT fill times.
|
||||||
|
*/
|
||||||
|
std::vector<double> GetWorkerDHTFillTimings() const;
|
||||||
|
/**
|
||||||
|
* **Master only** Collect and return all accumulated timings recorded by
|
||||||
|
* workers waiting for work packages from the master.
|
||||||
|
*
|
||||||
|
* \return Vector of all accumulated waiting times.
|
||||||
|
*/
|
||||||
|
std::vector<double> GetWorkerIdleTimings() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* **Master only** Collect and return DHT hits of all workers.
|
||||||
|
*
|
||||||
|
* \return Vector of all count of DHT hits.
|
||||||
|
*/
|
||||||
|
std::vector<uint32_t> GetWorkerDHTHits() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* **Master only** Collect and return DHT misses of all workers.
|
||||||
|
*
|
||||||
|
* \return Vector of all count of DHT misses.
|
||||||
|
*/
|
||||||
|
std::vector<uint32_t> GetWorkerDHTMiss() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* **Master only** Collect and return DHT evictions of all workers.
|
||||||
|
*
|
||||||
|
* \return Vector of all count of DHT evictions.
|
||||||
|
*/
|
||||||
|
std::vector<uint32_t> GetWorkerDHTEvictions() const;
|
||||||
|
#endif
|
||||||
|
protected:
|
||||||
|
#ifdef POET_USE_PRM
|
||||||
|
void PrmToPoetField(std::vector<double> &field);
|
||||||
|
#else
|
||||||
|
enum {
|
||||||
|
CHEM_INIT,
|
||||||
|
CHEM_WP_SIZE,
|
||||||
|
CHEM_DHT_ENABLE,
|
||||||
|
CHEM_DHT_SIGNIF_VEC,
|
||||||
|
CHEM_DHT_PROP_TYPE_VEC,
|
||||||
|
CHEM_DHT_SNAPS,
|
||||||
|
CHEM_DHT_READ_FILE,
|
||||||
|
CHEM_WORK_LOOP,
|
||||||
|
CHEM_PERF,
|
||||||
|
CHEM_BREAK_MAIN_LOOP
|
||||||
|
};
|
||||||
|
|
||||||
|
enum { LOOP_WORK, LOOP_END };
|
||||||
|
|
||||||
|
enum {
|
||||||
|
WORKER_PHREEQC,
|
||||||
|
WORKER_DHT_GET,
|
||||||
|
WORKER_DHT_FILL,
|
||||||
|
WORKER_IDLE,
|
||||||
|
WORKER_DHT_HITS,
|
||||||
|
WORKER_DHT_MISS,
|
||||||
|
WORKER_DHT_EVICTIONS
|
||||||
|
};
|
||||||
|
|
||||||
|
struct worker_s {
|
||||||
|
double phreeqc_t = 0.;
|
||||||
|
double dht_get = 0.;
|
||||||
|
double dht_fill = 0.;
|
||||||
|
double idle_t = 0.;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct worker_info_s {
|
||||||
|
char has_work = 0;
|
||||||
|
double *send_addr;
|
||||||
|
};
|
||||||
|
|
||||||
|
using worker_list_t = std::vector<struct worker_info_s>;
|
||||||
|
using workpointer_t = std::vector<double>::iterator;
|
||||||
|
|
||||||
|
void MasterRunParallel();
|
||||||
|
void MasterRunSequential();
|
||||||
|
|
||||||
|
void MasterSendPkgs(worker_list_t &w_list, workpointer_t &work_pointer,
|
||||||
|
int &pkg_to_send, int &count_pkgs, int &free_workers,
|
||||||
|
double dt, uint32_t iteration,
|
||||||
|
const std::vector<uint32_t> &wp_sizes_vector);
|
||||||
|
void MasterRecvPkgs(worker_list_t &w_list, int &pkg_to_recv, bool to_send,
|
||||||
|
int &free_workers);
|
||||||
|
|
||||||
|
std::vector<double> MasterGatherWorkerTimings(int type) const;
|
||||||
|
std::vector<uint32_t> MasterGatherWorkerMetrics(int type) const;
|
||||||
|
|
||||||
|
void WorkerProcessPkgs(struct worker_s &timings, uint32_t &iteration);
|
||||||
|
|
||||||
|
void WorkerDoWork(MPI_Status &probe_status, int double_count,
|
||||||
|
struct worker_s &timings);
|
||||||
|
void WorkerPostIter(MPI_Status &prope_status, uint32_t iteration);
|
||||||
|
void WorkerPostSim(uint32_t iteration);
|
||||||
|
|
||||||
|
void WorkerWriteDHTDump(uint32_t iteration);
|
||||||
|
void WorkerReadDHTDump(const std::string &dht_input_file);
|
||||||
|
|
||||||
|
void WorkerPerfToMaster(int type, const struct worker_s &timings);
|
||||||
|
void WorkerMetricsToMaster(int type);
|
||||||
|
|
||||||
|
IRM_RESULT WorkerRunWorkPackage(std::vector<double> &vecWP,
|
||||||
|
std::vector<int32_t> &vecMapping,
|
||||||
|
double dSimTime, double dTimestep);
|
||||||
|
|
||||||
|
void GetWPFromInternals(std::vector<double> &vecWP, uint32_t wp_size);
|
||||||
|
void SetInternalsFromWP(const std::vector<double> &vecWP, uint32_t wp_size);
|
||||||
|
|
||||||
|
std::vector<uint32_t> CalculateWPSizesVector(uint32_t n_cells,
|
||||||
|
uint32_t wp_size) const;
|
||||||
|
|
||||||
|
int comm_size, comm_rank;
|
||||||
|
MPI_Comm group_comm;
|
||||||
|
|
||||||
|
bool is_sequential;
|
||||||
|
bool is_master;
|
||||||
|
|
||||||
|
uint32_t wp_size;
|
||||||
|
bool dht_enabled = false;
|
||||||
|
int dht_snaps_type = DHT_FILES_DISABLED;
|
||||||
|
std::string dht_file_out_dir;
|
||||||
|
|
||||||
|
poet::DHT_Wrapper *dht = std::nullptr_t();
|
||||||
|
|
||||||
|
static constexpr uint32_t BUFFER_OFFSET = 5;
|
||||||
|
|
||||||
|
inline void ChemBCast(void *buf, int count, MPI_Datatype datatype) const {
|
||||||
|
MPI_Bcast(buf, count, datatype, 0, this->group_comm);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void PropagateFunctionType(int &type) const {
|
||||||
|
ChemBCast(&type, 1, MPI_INT);
|
||||||
|
}
|
||||||
|
double simtime = 0.;
|
||||||
|
double idle_t = 0.;
|
||||||
|
double seq_t = 0.;
|
||||||
|
double send_recv_t = 0.;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
double chem_t = 0.;
|
||||||
|
|
||||||
|
uint32_t n_cells = 0;
|
||||||
|
uint32_t prop_count = 0;
|
||||||
|
std::vector<std::string> prop_names;
|
||||||
|
std::vector<double> field;
|
||||||
|
std::vector<uint32_t> speciesPerModule;
|
||||||
|
static constexpr uint32_t MODULE_COUNT = 5;
|
||||||
|
};
|
||||||
|
} // namespace poet
|
||||||
|
|
||||||
|
#endif // CHEMISTRYMODULE_H_
|
||||||
8
include/poet/DHT_Types.hpp
Normal file
8
include/poet/DHT_Types.hpp
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#ifndef DHT_TYPES_H_
|
||||||
|
#define DHT_TYPES_H_
|
||||||
|
|
||||||
|
namespace poet {
|
||||||
|
enum DHT_PROP_TYPES { DHT_TYPE_DEFAULT, DHT_TYPE_ACT, DHT_TYPE_IGNORE };
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // DHT_TYPES_H_
|
||||||
@ -21,8 +21,6 @@
|
|||||||
#ifndef DHT_WRAPPER_H
|
#ifndef DHT_WRAPPER_H
|
||||||
#define DHT_WRAPPER_H
|
#define DHT_WRAPPER_H
|
||||||
|
|
||||||
#include "SimParams.hpp"
|
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -46,7 +44,7 @@ using DHT_ResultObject = struct DHTResobj {
|
|||||||
std::vector<std::vector<double>> results;
|
std::vector<std::vector<double>> results;
|
||||||
std::vector<bool> needPhreeqc;
|
std::vector<bool> needPhreeqc;
|
||||||
|
|
||||||
void ResultsToMapping(std::vector<int32_t> &curr_mapping);
|
void ResultsToMapping(std::vector<int32_t> &curr_mapping);
|
||||||
void ResultsToWP(std::vector<double> &curr_wp);
|
void ResultsToWP(std::vector<double> &curr_wp);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -79,15 +77,14 @@ public:
|
|||||||
* calling DHT_create with all given parameters. Also the fuzzing buffer will
|
* calling DHT_create with all given parameters. Also the fuzzing buffer will
|
||||||
* be allocated and all needed parameters extracted from simparams struct.
|
* be allocated and all needed parameters extracted from simparams struct.
|
||||||
*
|
*
|
||||||
* @param params Simulation parameter object
|
|
||||||
* @param dht_comm Communicator which addresses all participating DHT
|
* @param dht_comm Communicator which addresses all participating DHT
|
||||||
* processes
|
* processes
|
||||||
* @param buckets_per_process Count of buckets to allocate for each process
|
* @param buckets_per_process Count of buckets to allocate for each process
|
||||||
* @param key_count Count of key entries
|
* @param key_count Count of key entries
|
||||||
* @param data_count Count of data entries
|
* @param data_count Count of data entries
|
||||||
*/
|
*/
|
||||||
DHT_Wrapper(const poet::SimParams ¶ms, MPI_Comm dht_comm,
|
DHT_Wrapper(MPI_Comm dht_comm, uint32_t dht_size, uint32_t key_count,
|
||||||
uint32_t dht_size, uint32_t key_count, uint32_t data_count);
|
uint32_t data_count);
|
||||||
/**
|
/**
|
||||||
* @brief Destroy the dht wrapper object
|
* @brief Destroy the dht wrapper object
|
||||||
*
|
*
|
||||||
@ -173,138 +170,43 @@ public:
|
|||||||
*
|
*
|
||||||
* @return uint64_t Count of hits
|
* @return uint64_t Count of hits
|
||||||
*/
|
*/
|
||||||
uint64_t getHits();
|
auto getHits() { return this->dht_hits; };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the Misses object
|
* @brief Get the Misses object
|
||||||
*
|
*
|
||||||
* @return uint64_t Count of read misses
|
* @return uint64_t Count of read misses
|
||||||
*/
|
*/
|
||||||
uint64_t getMisses();
|
auto getMisses() { return this->dht_miss; };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the Evictions object
|
* @brief Get the Evictions object
|
||||||
*
|
*
|
||||||
* @return uint64_t Count of evictions
|
* @return uint64_t Count of evictions
|
||||||
*/
|
*/
|
||||||
uint64_t getEvictions();
|
auto getEvictions() { return this->dht_evictions; };
|
||||||
|
|
||||||
|
void SetSignifVector(std::vector<uint32_t> signif_vec);
|
||||||
|
void SetPropTypeVector(std::vector<uint32_t> prop_type_vec);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint32_t key_count;
|
uint32_t key_count;
|
||||||
uint32_t data_count;
|
uint32_t data_count;
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Transform given workpackage into DHT key
|
|
||||||
*
|
|
||||||
* A given workpackage will be transformed into a DHT key by rounding each
|
|
||||||
* value of a workpackage to a given significant digit. Three different types
|
|
||||||
* of variables 'act', 'logact' and 'ignore' are used. Those types are given
|
|
||||||
* via the dht_signif_vector.
|
|
||||||
*
|
|
||||||
* If a variable is defined as 'act', dht_log is true and non-negative, the
|
|
||||||
* logarithm with base 10 will be applied. After that the value is negated. In
|
|
||||||
* case the value is 0 the fuzzing_buffer is also set to 0 at this position.
|
|
||||||
* If the value is negative a correspondending warning will be printed to
|
|
||||||
* stderr and the fuzzing buffer will be set to 0 at this index.
|
|
||||||
*
|
|
||||||
* If a variable is defined as 'logact' the value will be cut after the
|
|
||||||
* significant digit.
|
|
||||||
*
|
|
||||||
* If a variable ist defined as 'ignore' the fuzzing_buffer will be set to 0
|
|
||||||
* at the index of the variable.
|
|
||||||
*
|
|
||||||
* If dt_differ is true the current time step of the simulation will be set at
|
|
||||||
* the end of the fuzzing_buffer.
|
|
||||||
*
|
|
||||||
* @param var_count Count of variables for the current work package
|
|
||||||
* @param key Pointer to work package handled as the key
|
|
||||||
* @param dt Current time step of the simulation
|
|
||||||
*/
|
|
||||||
std::vector<DHT_Keyelement> fuzzForDHT(int var_count, void *key, double dt);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief DHT handle
|
|
||||||
*
|
|
||||||
* Stores information about the DHT. Will be used as a handle for each DHT
|
|
||||||
* library call.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
DHT *dht_object;
|
DHT *dht_object;
|
||||||
|
|
||||||
/**
|
std::vector<DHT_Keyelement> fuzzForDHT(int var_count, void *key, double dt);
|
||||||
* @brief Count of hits
|
|
||||||
*
|
|
||||||
* The counter will be incremented if a previously simulated workpackage can
|
|
||||||
* be retrieved with a given key.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
uint64_t dht_hits = 0;
|
|
||||||
|
|
||||||
/**
|
uint32_t dht_hits = 0;
|
||||||
* @brief Count of read misses
|
uint32_t dht_miss = 0;
|
||||||
*
|
uint32_t dht_evictions = 0;
|
||||||
* The counter will be incremented if a given key doesn't retrieve a value
|
|
||||||
* from the DHT.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
uint64_t dht_miss = 0;
|
|
||||||
|
|
||||||
/**
|
std::vector<uint32_t> dht_signif_vector;
|
||||||
* @brief Count of evictions
|
std::vector<uint32_t> dht_prop_type_vector;
|
||||||
*
|
|
||||||
* If a value in the DHT must be evicted because of lack of space/reaching the
|
|
||||||
* last index etc., this counter will be incremented.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
uint64_t dht_evictions = 0;
|
|
||||||
|
|
||||||
/**
|
static constexpr int DHT_KEY_SIGNIF_DEFAULT = 5;
|
||||||
* @brief Rounded work package values
|
static constexpr int DHT_KEY_SIGNIF_TOTALS = 12;
|
||||||
*
|
static constexpr int DHT_KEY_SIGNIF_CHARGE = 3;
|
||||||
* Stores rounded work package values and serves as the DHT key pointer.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
double *fuzzing_buffer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Indicates change in time step during simulation
|
|
||||||
*
|
|
||||||
* If set to true, the time step of simulation will differ between iterations,
|
|
||||||
* so the current time step must be stored inside the DHT key. Otherwise wrong
|
|
||||||
* values would be obtained.
|
|
||||||
*
|
|
||||||
* If set to false the time step doesn't need to be stored in the DHT key.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
bool dt_differ;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Logarithm before rounding
|
|
||||||
*
|
|
||||||
* Indicates if the logarithm with base 10 will be applied to a variable
|
|
||||||
* before rounding.
|
|
||||||
*
|
|
||||||
* Defaults to true.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
bool dht_log;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Significant digits for each variable
|
|
||||||
*
|
|
||||||
* Stores the rounding/significant digits for each variable of the work
|
|
||||||
* package.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
std::vector<int> dht_signif_vector;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Type of each variable
|
|
||||||
*
|
|
||||||
* Defines the type of each variable of the work package.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
std::vector<std::string> dht_prop_type_vector;
|
|
||||||
};
|
};
|
||||||
} // namespace poet
|
} // namespace poet
|
||||||
|
|
||||||
|
|||||||
@ -39,7 +39,7 @@ namespace poet {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
constexpr const char *DIFFUSION_MODULE_NAME = "state_t";
|
constexpr const char *DIFFUSION_MODULE_NAME = "state_T";
|
||||||
|
|
||||||
class DiffusionModule {
|
class DiffusionModule {
|
||||||
public:
|
public:
|
||||||
|
|||||||
@ -22,6 +22,7 @@
|
|||||||
#define GRID_H
|
#define GRID_H
|
||||||
|
|
||||||
#include "poet/SimParams.hpp"
|
#include "poet/SimParams.hpp"
|
||||||
|
#include <RInside.h>
|
||||||
#include <Rcpp.h>
|
#include <Rcpp.h>
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
@ -97,6 +98,8 @@ public:
|
|||||||
std::string module_name = poet::GRID_MODULE_NAME) const
|
std::string module_name = poet::GRID_MODULE_NAME) const
|
||||||
-> std::vector<double>;
|
-> std::vector<double>;
|
||||||
|
|
||||||
|
void WriteFieldsToR(RInside &R);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<FlowInputOutputInfo> flow_vec;
|
std::vector<FlowInputOutputInfo> flow_vec;
|
||||||
|
|
||||||
|
|||||||
@ -1,50 +0,0 @@
|
|||||||
#ifndef PHREEQCWRAPPER_H_
|
|
||||||
#define PHREEQCWRAPPER_H_
|
|
||||||
|
|
||||||
#include "IrmResult.h"
|
|
||||||
#include "poet/SimParams.hpp"
|
|
||||||
#include <PhreeqcRM.h>
|
|
||||||
#include <cstdint>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace poet {
|
|
||||||
class PhreeqcWrapper : public PhreeqcRM {
|
|
||||||
public:
|
|
||||||
PhreeqcWrapper(uint32_t inxyz);
|
|
||||||
|
|
||||||
void SetupAndLoadDB(const poet::ChemistryParams &chemPar);
|
|
||||||
void InitFromFile(const std::string &strInputFile);
|
|
||||||
|
|
||||||
auto GetSpeciesCount() -> uint32_t;
|
|
||||||
auto GetSpeciesCountByModule() -> const std::vector<uint32_t> &;
|
|
||||||
auto GetSpeciesNamesFull() -> const std::vector<std::string> &;
|
|
||||||
|
|
||||||
void SetInternalsFromWP(const std::vector<double> &vecWP,
|
|
||||||
uint32_t iCurrWPSize);
|
|
||||||
void GetWPFromInternals(std::vector<double> &vecWP, uint32_t iCurrWPSize);
|
|
||||||
|
|
||||||
auto ReplaceTotalsByPotentials(const std::vector<double> &vecWP,
|
|
||||||
uint32_t iCurrWPSize) -> std::vector<double>;
|
|
||||||
|
|
||||||
IRM_RESULT RunWorkPackage(std::vector<double> &vecWP,
|
|
||||||
std::vector<int32_t> &vecMapping, double dSimTime,
|
|
||||||
double dTimestep);
|
|
||||||
|
|
||||||
private:
|
|
||||||
void InitInternals();
|
|
||||||
inline void SetMappingForWP(uint32_t iCurrWPSize);
|
|
||||||
|
|
||||||
static constexpr int MODULE_COUNT = 5;
|
|
||||||
static constexpr uint32_t DHT_SELOUT = 100;
|
|
||||||
|
|
||||||
uint32_t iWPSize;
|
|
||||||
bool bInactiveCells = false;
|
|
||||||
uint32_t iSpeciesCount;
|
|
||||||
std::vector<uint32_t> vecSpeciesPerModule;
|
|
||||||
std::vector<std::string> vecSpeciesNames;
|
|
||||||
std::vector<int> vecDefMapping;
|
|
||||||
};
|
|
||||||
} // namespace poet
|
|
||||||
|
|
||||||
#endif // PHREEQCWRAPPER_H_
|
|
||||||
@ -31,8 +31,8 @@
|
|||||||
#include <Rcpp.h>
|
#include <Rcpp.h>
|
||||||
// BSD-licenced
|
// BSD-licenced
|
||||||
|
|
||||||
/** Standard DHT Size (Defaults to 1 GiB) */
|
/** Standard DHT Size. Defaults to 1 GB (1000 MB) */
|
||||||
#define DHT_SIZE_PER_PROCESS 1073741824
|
constexpr uint32_t DHT_SIZE_PER_PROCESS_MB = 1E3;
|
||||||
/** Standard work package size */
|
/** Standard work package size */
|
||||||
#define WORK_PACKAGE_SIZE_DEFAULT 5
|
#define WORK_PACKAGE_SIZE_DEFAULT 5
|
||||||
|
|
||||||
@ -167,16 +167,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
void initVectorParams(RInside &R, int col_count);
|
void initVectorParams(RInside &R, int col_count);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Set if dt differs
|
|
||||||
*
|
|
||||||
* Set a boolean variable if the timestep differs between iterations of
|
|
||||||
* simulation.
|
|
||||||
*
|
|
||||||
* @param dt_differ Boolean value, if dt differs
|
|
||||||
*/
|
|
||||||
void setDtDiffer(bool dt_differ);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the numerical params struct
|
* @brief Get the numerical params struct
|
||||||
*
|
*
|
||||||
@ -185,7 +175,7 @@ public:
|
|||||||
*
|
*
|
||||||
* @return t_simparams Parameter struct
|
* @return t_simparams Parameter struct
|
||||||
*/
|
*/
|
||||||
t_simparams getNumParams() const;
|
auto getNumParams() const { return this->simparams; };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the DHT_Signif_Vector
|
* @brief Get the DHT_Signif_Vector
|
||||||
@ -196,7 +186,7 @@ public:
|
|||||||
* @return std::vector<int> Vector of integers containing information about
|
* @return std::vector<int> Vector of integers containing information about
|
||||||
* significant digits
|
* significant digits
|
||||||
*/
|
*/
|
||||||
std::vector<int> getDHTSignifVector() const;
|
auto getDHTSignifVector() const { return this->dht_signif_vector; };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the DHT_Prop_Type_Vector
|
* @brief Get the DHT_Prop_Type_Vector
|
||||||
@ -206,7 +196,7 @@ public:
|
|||||||
* @return std::vector<std::string> Vector if strings defining a type of a
|
* @return std::vector<std::string> Vector if strings defining a type of a
|
||||||
* variable
|
* variable
|
||||||
*/
|
*/
|
||||||
std::vector<std::string> getDHTPropTypeVector() const;
|
auto getDHTPropTypeVector() const { return this->dht_prop_type_vector; };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Return name of DHT snapshot.
|
* @brief Return name of DHT snapshot.
|
||||||
@ -216,7 +206,7 @@ public:
|
|||||||
*
|
*
|
||||||
* @return std::string Absolute paht to the DHT snapshot
|
* @return std::string Absolute paht to the DHT snapshot
|
||||||
*/
|
*/
|
||||||
std::string_view getDHTFile() const;
|
auto getDHTFile() const { return this->dht_file; };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the filesim name
|
* @brief Get the filesim name
|
||||||
@ -226,7 +216,7 @@ public:
|
|||||||
*
|
*
|
||||||
* @return std::string Absolute path to R file
|
* @return std::string Absolute path to R file
|
||||||
*/
|
*/
|
||||||
std::string_view getFilesim() const;
|
auto getFilesim() const { return this->filesim; };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the output directory
|
* @brief Get the output directory
|
||||||
@ -236,71 +226,23 @@ public:
|
|||||||
*
|
*
|
||||||
* @return std::string Absolute path to output path
|
* @return std::string Absolute path to output path
|
||||||
*/
|
*/
|
||||||
std::string_view getOutDir() const;
|
auto getOutDir() const { return this->out_dir; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
|
||||||
* @brief Validate program parameters and flags
|
|
||||||
*
|
|
||||||
* Therefore this function iterates over the list of flags and parameters and
|
|
||||||
* compare them to the class member flagList and paramList. If a program
|
|
||||||
* argument is not included it is put to a list. This list will be returned.
|
|
||||||
*
|
|
||||||
* @return std::list<std::string> List with all unknown parameters. Might be
|
|
||||||
* empty.
|
|
||||||
*/
|
|
||||||
std::list<std::string> validateOptions(argh::parser cmdl);
|
std::list<std::string> validateOptions(argh::parser cmdl);
|
||||||
|
|
||||||
/**
|
const std::set<std::string> flaglist{"ignore-result", "dht", "dht-nolog"};
|
||||||
* @brief Contains all valid program flags.
|
const std::set<std::string> paramlist{"work-package-size", "dht-signif",
|
||||||
*
|
"dht-strategy", "dht-size",
|
||||||
*/
|
"dht-snaps", "dht-file"};
|
||||||
std::set<std::string> flaglist{"ignore-result", "dht", "dht-nolog"};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Contains all valid program parameters.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
std::set<std::string> paramlist{"work-package-size", "dht-signif",
|
|
||||||
"dht-strategy", "dht-size",
|
|
||||||
"dht-snaps", "dht-file"};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Struct containing all simulation parameters
|
|
||||||
*
|
|
||||||
* Contains only those values which are standard arithmetic C types.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
t_simparams simparams;
|
t_simparams simparams;
|
||||||
|
|
||||||
/**
|
std::vector<uint32_t> dht_signif_vector;
|
||||||
* @brief Defines significant digits for each variable of a grid cell
|
std::vector<uint32_t> dht_prop_type_vector;
|
||||||
*
|
|
||||||
*/
|
|
||||||
std::vector<int> dht_signif_vector;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Defines the type of a variable
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
std::vector<std::string> dht_prop_type_vector;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Absolute path to a DHT snapshot
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
std::string dht_file;
|
std::string dht_file;
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Absolute path to R file containing simulation definitions
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
std::string filesim;
|
std::string filesim;
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Absolute path to output dir
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
std::string out_dir;
|
std::string out_dir;
|
||||||
};
|
};
|
||||||
} // namespace poet
|
} // namespace poet
|
||||||
|
|||||||
@ -1,12 +0,0 @@
|
|||||||
#include <poet/ChemSimSeq.hpp>
|
|
||||||
|
|
||||||
poet::BaseChemModule::BaseChemModule(SimParams ¶ms, RInside &R_,
|
|
||||||
Grid &grid_)
|
|
||||||
: R(R_), grid(grid_) {
|
|
||||||
t_simparams tmp = params.getNumParams();
|
|
||||||
this->world_rank = tmp.world_rank;
|
|
||||||
this->world_size = tmp.world_size;
|
|
||||||
this->prop_names = this->grid.GetPropNames();
|
|
||||||
|
|
||||||
this->n_cells_per_prop = this->grid.GetTotalCellCount();
|
|
||||||
}
|
|
||||||
@ -7,14 +7,10 @@ file(GLOB poet_lib_SRC
|
|||||||
find_library(MATH_LIBRARY m)
|
find_library(MATH_LIBRARY m)
|
||||||
find_library(CRYPTO_LIBRARY crypto)
|
find_library(CRYPTO_LIBRARY crypto)
|
||||||
|
|
||||||
option(POET_DHT_DEBUG "Build with DHT debug info" OFF)
|
|
||||||
|
|
||||||
add_library(poet_lib ${poet_lib_SRC})
|
add_library(poet_lib ${poet_lib_SRC})
|
||||||
target_include_directories(poet_lib PUBLIC ${PROJECT_SOURCE_DIR}/include)
|
target_include_directories(poet_lib PUBLIC ${PROJECT_SOURCE_DIR}/include)
|
||||||
target_link_libraries(poet_lib PUBLIC
|
target_link_libraries(poet_lib PUBLIC
|
||||||
MPI::MPI_C ${MATH_LIBRARY} ${CRYPTO_LIBRARY} RRuntime tug PhreeqcRM DataStructures)
|
MPI::MPI_CXX ${MATH_LIBRARY} ${CRYPTO_LIBRARY} RRuntime tug PhreeqcRM DataStructures ChemistryModule)
|
||||||
target_compile_definitions(poet_lib PUBLIC STRICT_R_HEADERS OMPI_SKIP_MPICXX)
|
target_compile_definitions(poet_lib PUBLIC STRICT_R_HEADERS OMPI_SKIP_MPICXX)
|
||||||
|
|
||||||
if(POET_DHT_DEBUG)
|
add_subdirectory(ChemistryModule)
|
||||||
target_compile_definitions(poet_lib PRIVATE DHT_STATISTICS)
|
|
||||||
endif()
|
|
||||||
|
|||||||
@ -1,445 +0,0 @@
|
|||||||
/*
|
|
||||||
** Copyright (C) 2018-2021 Alexander Lindemann, Max Luebke (University of
|
|
||||||
** Potsdam)
|
|
||||||
**
|
|
||||||
** Copyright (C) 2018-2022 Marco De Lucia, Max Luebke (GFZ Potsdam)
|
|
||||||
**
|
|
||||||
** POET is free software; you can redistribute it and/or modify it under the
|
|
||||||
** terms of the GNU General Public License as published by the Free Software
|
|
||||||
** Foundation; either version 2 of the License, or (at your option) any later
|
|
||||||
** version.
|
|
||||||
**
|
|
||||||
** POET is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
||||||
** WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
||||||
** A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
||||||
**
|
|
||||||
** You should have received a copy of the GNU General Public License along with
|
|
||||||
** this program; if not, write to the Free Software Foundation, Inc., 51
|
|
||||||
** Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "poet/ChemSimPar.hpp"
|
|
||||||
#include "poet/ChemSimSeq.hpp"
|
|
||||||
#include "poet/DiffusionModule.hpp"
|
|
||||||
#include "poet/Grid.hpp"
|
|
||||||
#include "poet/SimParams.hpp"
|
|
||||||
|
|
||||||
#include <Rcpp.h>
|
|
||||||
#include <array>
|
|
||||||
#include <cstdint>
|
|
||||||
#include <cstring>
|
|
||||||
#include <iostream>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
using namespace poet;
|
|
||||||
using namespace std;
|
|
||||||
using namespace Rcpp;
|
|
||||||
|
|
||||||
ChemMaster::ChemMaster(SimParams ¶ms, RInside &R_, Grid &grid_)
|
|
||||||
: BaseChemModule(params, R_, grid_) {
|
|
||||||
t_simparams tmp = params.getNumParams();
|
|
||||||
|
|
||||||
this->wp_size = tmp.wp_size;
|
|
||||||
this->dht_enabled = tmp.dht_enabled;
|
|
||||||
|
|
||||||
uint32_t grid_size = grid.GetTotalCellCount() * this->prop_names.size();
|
|
||||||
|
|
||||||
/* allocate memory */
|
|
||||||
this->workerlist = new worker_struct[this->world_size - 1];
|
|
||||||
std::memset(this->workerlist, '\0', sizeof(worker_struct) * (world_size - 1));
|
|
||||||
this->send_buffer =
|
|
||||||
new double[this->wp_size * this->prop_names.size() + BUFFER_OFFSET];
|
|
||||||
this->mpi_buffer = new double[grid_size];
|
|
||||||
|
|
||||||
/* calculate distribution of work packages */
|
|
||||||
uint32_t mod_pkgs = grid.GetTotalCellCount() % this->wp_size;
|
|
||||||
uint32_t n_packages = (uint32_t)(grid.GetTotalCellCount() / this->wp_size) +
|
|
||||||
(mod_pkgs != 0 ? 1 : 0);
|
|
||||||
|
|
||||||
Rcpp::Function wp_f("GetWorkPackageSizesVector");
|
|
||||||
this->wp_sizes_vector = Rcpp::as<std::vector<uint32_t>>(
|
|
||||||
wp_f(n_packages, this->wp_size, grid.GetTotalCellCount()));
|
|
||||||
|
|
||||||
this->state = this->grid.RegisterState(
|
|
||||||
poet::BaseChemModule::CHEMISTRY_MODULE_NAME, this->prop_names);
|
|
||||||
std::vector<double> &field = this->state->mem;
|
|
||||||
|
|
||||||
field.resize(this->n_cells_per_prop * this->prop_names.size());
|
|
||||||
for (uint32_t i = 0; i < this->prop_names.size(); i++) {
|
|
||||||
std::vector<double> prop_vec =
|
|
||||||
this->grid.GetSpeciesByName(this->prop_names[i]);
|
|
||||||
|
|
||||||
std::copy(prop_vec.begin(), prop_vec.end(),
|
|
||||||
field.begin() + (i * this->n_cells_per_prop));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ChemMaster::~ChemMaster() {
|
|
||||||
delete this->workerlist;
|
|
||||||
delete this->send_buffer;
|
|
||||||
delete this->mpi_buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChemMaster::Simulate(double dt) {
|
|
||||||
/* declare most of the needed variables here */
|
|
||||||
double chem_a, chem_b;
|
|
||||||
double seq_a, seq_b, seq_c, seq_d;
|
|
||||||
double worker_chemistry_a, worker_chemistry_b;
|
|
||||||
double sim_e_chemistry, sim_f_chemistry;
|
|
||||||
int pkg_to_send, pkg_to_recv;
|
|
||||||
int free_workers;
|
|
||||||
int i_pkgs;
|
|
||||||
uint32_t iteration;
|
|
||||||
|
|
||||||
/* start time measurement of whole chemistry simulation */
|
|
||||||
chem_a = MPI_Wtime();
|
|
||||||
|
|
||||||
/* start time measurement of sequential part */
|
|
||||||
seq_a = MPI_Wtime();
|
|
||||||
|
|
||||||
std::vector<double> &field = this->state->mem;
|
|
||||||
|
|
||||||
// HACK: transfer the field into R data structure serving as input for phreeqc
|
|
||||||
R["TMP_T"] = field;
|
|
||||||
|
|
||||||
R.parseEvalQ("mysetup$state_T <- setNames(data.frame(matrix(TMP_T, "
|
|
||||||
"ncol=length(mysetup$grid$props), nrow=" +
|
|
||||||
std::to_string(this->n_cells_per_prop) +
|
|
||||||
")), mysetup$grid$props)");
|
|
||||||
|
|
||||||
/* shuffle grid */
|
|
||||||
// grid.shuffleAndExport(mpi_buffer);
|
|
||||||
this->shuffleField(field, this->n_cells_per_prop, this->prop_names.size(),
|
|
||||||
mpi_buffer);
|
|
||||||
|
|
||||||
/* retrieve needed data from R runtime */
|
|
||||||
iteration = (int)R.parseEval("mysetup$iter");
|
|
||||||
// dt = (double)R.parseEval("mysetup$requested_dt");
|
|
||||||
|
|
||||||
/* setup local variables */
|
|
||||||
pkg_to_send = wp_sizes_vector.size();
|
|
||||||
pkg_to_recv = wp_sizes_vector.size();
|
|
||||||
double *work_pointer = mpi_buffer;
|
|
||||||
free_workers = world_size - 1;
|
|
||||||
i_pkgs = 0;
|
|
||||||
|
|
||||||
/* end time measurement of sequential part */
|
|
||||||
seq_b = MPI_Wtime();
|
|
||||||
seq_t += seq_b - seq_a;
|
|
||||||
|
|
||||||
/* start time measurement of chemistry time needed for send/recv loop */
|
|
||||||
worker_chemistry_a = MPI_Wtime();
|
|
||||||
|
|
||||||
/* start send/recv loop */
|
|
||||||
// while there are still packages to recv
|
|
||||||
while (pkg_to_recv > 0) {
|
|
||||||
// print a progressbar to stdout
|
|
||||||
printProgressbar((int)i_pkgs, (int)wp_sizes_vector.size());
|
|
||||||
// while there are still packages to send
|
|
||||||
if (pkg_to_send > 0) {
|
|
||||||
// send packages to all free workers ...
|
|
||||||
sendPkgs(pkg_to_send, i_pkgs, free_workers, work_pointer, dt, iteration);
|
|
||||||
}
|
|
||||||
// ... and try to receive them from workers who has finished their work
|
|
||||||
recvPkgs(pkg_to_recv, pkg_to_send > 0, free_workers);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Just to complete the progressbar
|
|
||||||
cout << endl;
|
|
||||||
|
|
||||||
/* stop time measurement of chemistry time needed for send/recv loop */
|
|
||||||
worker_chemistry_b = MPI_Wtime();
|
|
||||||
worker_t = worker_chemistry_b - worker_chemistry_a;
|
|
||||||
|
|
||||||
/* start time measurement of sequential part */
|
|
||||||
seq_c = MPI_Wtime();
|
|
||||||
|
|
||||||
/* unshuffle grid */
|
|
||||||
// grid.importAndUnshuffle(mpi_buffer);
|
|
||||||
this->unshuffleField(mpi_buffer, this->n_cells_per_prop,
|
|
||||||
this->prop_names.size(), field);
|
|
||||||
|
|
||||||
/* do master stuff */
|
|
||||||
|
|
||||||
/* start time measurement of master chemistry */
|
|
||||||
sim_e_chemistry = MPI_Wtime();
|
|
||||||
|
|
||||||
// HACK: We don't need to call master_chemistry here since our result is
|
|
||||||
// already written to the memory as a data frame
|
|
||||||
|
|
||||||
// R.parseEvalQ("mysetup <- master_chemistry(setup=mysetup, data=result)");
|
|
||||||
R["TMP_T"] = Rcpp::wrap(field);
|
|
||||||
R.parseEval(std::string(
|
|
||||||
"mysetup$state_C <- setNames(data.frame(matrix(TMP_T, nrow=" +
|
|
||||||
to_string(this->n_cells_per_prop) + ")), mysetup$grid$props)"));
|
|
||||||
|
|
||||||
/* end time measurement of master chemistry */
|
|
||||||
sim_f_chemistry = MPI_Wtime();
|
|
||||||
chem_master += sim_f_chemistry - sim_e_chemistry;
|
|
||||||
|
|
||||||
/* end time measurement of sequential part */
|
|
||||||
seq_d = MPI_Wtime();
|
|
||||||
seq_t += seq_d - seq_c;
|
|
||||||
|
|
||||||
/* end time measurement of whole chemistry simulation */
|
|
||||||
chem_b = MPI_Wtime();
|
|
||||||
chem_t += chem_b - chem_a;
|
|
||||||
|
|
||||||
/* advise workers to end chemistry iteration */
|
|
||||||
for (int i = 1; i < world_size; i++) {
|
|
||||||
MPI_Send(NULL, 0, MPI_DOUBLE, i, TAG_DHT_ITER, MPI_COMM_WORLD);
|
|
||||||
}
|
|
||||||
|
|
||||||
this->current_sim_time += dt;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void ChemMaster::sendPkgs(int &pkg_to_send, int &count_pkgs,
|
|
||||||
int &free_workers, double *&work_pointer,
|
|
||||||
const double &dt, const uint32_t iteration) {
|
|
||||||
/* declare variables */
|
|
||||||
double master_send_a, master_send_b;
|
|
||||||
int local_work_package_size;
|
|
||||||
int end_of_wp;
|
|
||||||
|
|
||||||
/* start time measurement */
|
|
||||||
master_send_a = MPI_Wtime();
|
|
||||||
|
|
||||||
/* search for free workers and send work */
|
|
||||||
for (int p = 0; p < world_size - 1; p++) {
|
|
||||||
if (workerlist[p].has_work == 0 && pkg_to_send > 0) /* worker is free */ {
|
|
||||||
/* to enable different work_package_size, set local copy of
|
|
||||||
* work_package_size to pre-calculated work package size vector */
|
|
||||||
|
|
||||||
local_work_package_size = (int)wp_sizes_vector[count_pkgs];
|
|
||||||
count_pkgs++;
|
|
||||||
|
|
||||||
/* note current processed work package in workerlist */
|
|
||||||
workerlist[p].send_addr = work_pointer;
|
|
||||||
|
|
||||||
/* push work pointer to next work package */
|
|
||||||
end_of_wp = local_work_package_size * grid.GetSpeciesCount();
|
|
||||||
work_pointer = &(work_pointer[end_of_wp]);
|
|
||||||
|
|
||||||
// fill send buffer starting with work_package ...
|
|
||||||
std::memcpy(send_buffer, workerlist[p].send_addr,
|
|
||||||
(end_of_wp) * sizeof(double));
|
|
||||||
// followed by: work_package_size
|
|
||||||
send_buffer[end_of_wp] = (double)local_work_package_size;
|
|
||||||
// current iteration of simulation
|
|
||||||
send_buffer[end_of_wp + 1] = (double)iteration;
|
|
||||||
// size of timestep in seconds
|
|
||||||
send_buffer[end_of_wp + 2] = dt;
|
|
||||||
// current time of simulation (age) in seconds
|
|
||||||
send_buffer[end_of_wp + 3] = current_sim_time;
|
|
||||||
// placeholder for work_package_count
|
|
||||||
send_buffer[end_of_wp + 4] = 0.;
|
|
||||||
|
|
||||||
/* ATTENTION Worker p has rank p+1 */
|
|
||||||
MPI_Send(send_buffer, end_of_wp + BUFFER_OFFSET, MPI_DOUBLE, p + 1,
|
|
||||||
TAG_WORK, MPI_COMM_WORLD);
|
|
||||||
|
|
||||||
/* Mark that worker has work to do */
|
|
||||||
workerlist[p].has_work = 1;
|
|
||||||
free_workers--;
|
|
||||||
pkg_to_send -= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
master_send_b = MPI_Wtime();
|
|
||||||
send_t += master_send_b - master_send_a;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void ChemMaster::recvPkgs(int &pkg_to_recv, bool to_send,
|
|
||||||
int &free_workers) {
|
|
||||||
/* declare most of the variables here */
|
|
||||||
int need_to_receive = 1;
|
|
||||||
double master_recv_a, master_recv_b;
|
|
||||||
double idle_a, idle_b;
|
|
||||||
int p, size;
|
|
||||||
|
|
||||||
MPI_Status probe_status;
|
|
||||||
master_recv_a = MPI_Wtime();
|
|
||||||
/* start to loop as long there are packages to recv and the need to receive
|
|
||||||
*/
|
|
||||||
while (need_to_receive && pkg_to_recv > 0) {
|
|
||||||
// only of there are still packages to send and free workers are available
|
|
||||||
if (to_send && free_workers > 0)
|
|
||||||
// non blocking probing
|
|
||||||
MPI_Iprobe(MPI_ANY_SOURCE, TAG_WORK, MPI_COMM_WORLD, &need_to_receive,
|
|
||||||
&probe_status);
|
|
||||||
else {
|
|
||||||
idle_a = MPI_Wtime();
|
|
||||||
// blocking probing
|
|
||||||
MPI_Probe(MPI_ANY_SOURCE, TAG_WORK, MPI_COMM_WORLD, &probe_status);
|
|
||||||
idle_b = MPI_Wtime();
|
|
||||||
master_idle += idle_b - idle_a;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* if need_to_receive was set to true above, so there is a message to
|
|
||||||
* receive */
|
|
||||||
if (need_to_receive) {
|
|
||||||
p = probe_status.MPI_SOURCE;
|
|
||||||
MPI_Get_count(&probe_status, MPI_DOUBLE, &size);
|
|
||||||
MPI_Recv(workerlist[p - 1].send_addr, size, MPI_DOUBLE, p, TAG_WORK,
|
|
||||||
MPI_COMM_WORLD, MPI_STATUS_IGNORE);
|
|
||||||
workerlist[p - 1].has_work = 0;
|
|
||||||
pkg_to_recv -= 1;
|
|
||||||
free_workers++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
master_recv_b = MPI_Wtime();
|
|
||||||
recv_t += master_recv_b - master_recv_a;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChemMaster::printProgressbar(int count_pkgs, int n_wp, int barWidth) {
|
|
||||||
/* visual progress */
|
|
||||||
double progress = (float)(count_pkgs + 1) / n_wp;
|
|
||||||
|
|
||||||
cout << "[";
|
|
||||||
int pos = barWidth * progress;
|
|
||||||
for (int iprog = 0; iprog < barWidth; ++iprog) {
|
|
||||||
if (iprog < pos)
|
|
||||||
cout << "=";
|
|
||||||
else if (iprog == pos)
|
|
||||||
cout << ">";
|
|
||||||
else
|
|
||||||
cout << " ";
|
|
||||||
}
|
|
||||||
std::cout << "] " << int(progress * 100.0) << " %\r";
|
|
||||||
std::cout.flush();
|
|
||||||
/* end visual progress */
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChemMaster::End() {
|
|
||||||
R["simtime_chemistry"] = chem_t;
|
|
||||||
R.parseEvalQ("profiling$simtime_chemistry <- simtime_chemistry");
|
|
||||||
|
|
||||||
Rcpp::NumericVector phreeqc_time;
|
|
||||||
Rcpp::NumericVector dht_get_time;
|
|
||||||
Rcpp::NumericVector dht_fill_time;
|
|
||||||
Rcpp::IntegerVector phreeqc_counts;
|
|
||||||
Rcpp::NumericVector idle_worker;
|
|
||||||
|
|
||||||
int phreeqc_tmp;
|
|
||||||
|
|
||||||
std::array<double, 3> timings;
|
|
||||||
std::array<int, 3> dht_perfs;
|
|
||||||
|
|
||||||
int dht_hits = 0;
|
|
||||||
int dht_miss = 0;
|
|
||||||
int dht_evictions = 0;
|
|
||||||
|
|
||||||
double idle_worker_tmp;
|
|
||||||
|
|
||||||
/* loop over all workers *
|
|
||||||
* ATTENTION Worker p has rank p+1 */
|
|
||||||
for (int p = 0; p < world_size - 1; p++) {
|
|
||||||
/* Send termination message to worker */
|
|
||||||
MPI_Send(NULL, 0, MPI_DOUBLE, p + 1, TAG_FINISH, MPI_COMM_WORLD);
|
|
||||||
|
|
||||||
/* ... and receive all timings and metrics from each worker */
|
|
||||||
MPI_Recv(timings.data(), 3, MPI_DOUBLE, p + 1, TAG_TIMING, MPI_COMM_WORLD,
|
|
||||||
MPI_STATUS_IGNORE);
|
|
||||||
phreeqc_time.push_back(timings[0], "w" + to_string(p + 1));
|
|
||||||
|
|
||||||
MPI_Recv(&phreeqc_tmp, 1, MPI_INT, p + 1, TAG_TIMING, MPI_COMM_WORLD,
|
|
||||||
MPI_STATUS_IGNORE);
|
|
||||||
phreeqc_counts.push_back(phreeqc_tmp, "w" + to_string(p + 1));
|
|
||||||
|
|
||||||
MPI_Recv(&idle_worker_tmp, 1, MPI_DOUBLE, p + 1, TAG_TIMING, MPI_COMM_WORLD,
|
|
||||||
MPI_STATUS_IGNORE);
|
|
||||||
idle_worker.push_back(idle_worker_tmp, "w" + to_string(p + 1));
|
|
||||||
|
|
||||||
if (dht_enabled) {
|
|
||||||
dht_get_time.push_back(timings[1], "w" + to_string(p + 1));
|
|
||||||
dht_fill_time.push_back(timings[2], "w" + to_string(p + 1));
|
|
||||||
|
|
||||||
MPI_Recv(dht_perfs.data(), 3, MPI_INT, p + 1, TAG_DHT_PERF,
|
|
||||||
MPI_COMM_WORLD, MPI_STATUS_IGNORE);
|
|
||||||
dht_hits += dht_perfs[0];
|
|
||||||
dht_miss += dht_perfs[1];
|
|
||||||
dht_evictions += dht_perfs[2];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* distribute all data to the R runtime */
|
|
||||||
R["simtime_chemistry"] = chem_t;
|
|
||||||
R.parseEvalQ("profiling$simtime_chemistry <- simtime_chemistry");
|
|
||||||
R["simtime_workers"] = worker_t;
|
|
||||||
R.parseEvalQ("profiling$simtime_workers <- simtime_workers");
|
|
||||||
R["simtime_chemistry_master"] = chem_master;
|
|
||||||
R.parseEvalQ(
|
|
||||||
"profiling$simtime_chemistry_master <- simtime_chemistry_master");
|
|
||||||
|
|
||||||
R["seq_master"] = seq_t;
|
|
||||||
R.parseEvalQ("profiling$seq_master <- seq_master");
|
|
||||||
|
|
||||||
R["idle_master"] = master_idle;
|
|
||||||
R.parseEvalQ("profiling$idle_master <- idle_master");
|
|
||||||
R["idle_worker"] = idle_worker;
|
|
||||||
R.parseEvalQ("profiling$idle_worker <- idle_worker");
|
|
||||||
|
|
||||||
R["phreeqc_time"] = phreeqc_time;
|
|
||||||
R.parseEvalQ("profiling$phreeqc <- phreeqc_time");
|
|
||||||
|
|
||||||
R["phreeqc_count"] = phreeqc_counts;
|
|
||||||
R.parseEvalQ("profiling$phreeqc_count <- phreeqc_count");
|
|
||||||
|
|
||||||
if (dht_enabled) {
|
|
||||||
R["dht_hits"] = dht_hits;
|
|
||||||
R.parseEvalQ("profiling$dht_hits <- dht_hits");
|
|
||||||
R["dht_miss"] = dht_miss;
|
|
||||||
R.parseEvalQ("profiling$dht_miss <- dht_miss");
|
|
||||||
R["dht_evictions"] = dht_evictions;
|
|
||||||
R.parseEvalQ("profiling$dht_evictions <- dht_evictions");
|
|
||||||
R["dht_get_time"] = dht_get_time;
|
|
||||||
R.parseEvalQ("profiling$dht_get_time <- dht_get_time");
|
|
||||||
R["dht_fill_time"] = dht_fill_time;
|
|
||||||
R.parseEvalQ("profiling$dht_fill_time <- dht_fill_time");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChemMaster::shuffleField(const std::vector<double> &in_field,
|
|
||||||
uint32_t size_per_prop, uint32_t prop_count,
|
|
||||||
double *out_buffer) {
|
|
||||||
uint32_t wp_count = this->wp_sizes_vector.size();
|
|
||||||
uint32_t write_i = 0;
|
|
||||||
for (uint32_t i = 0; i < wp_count; i++) {
|
|
||||||
for (uint32_t j = i; j < size_per_prop; j += wp_count) {
|
|
||||||
for (uint32_t k = 0; k < prop_count; k++) {
|
|
||||||
out_buffer[(write_i * prop_count) + k] =
|
|
||||||
in_field[(k * size_per_prop) + j];
|
|
||||||
}
|
|
||||||
write_i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChemMaster::unshuffleField(const double *in_buffer, uint32_t size_per_prop,
|
|
||||||
uint32_t prop_count,
|
|
||||||
std::vector<double> &out_field) {
|
|
||||||
uint32_t wp_count = this->wp_sizes_vector.size();
|
|
||||||
uint32_t read_i = 0;
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < wp_count; i++) {
|
|
||||||
for (uint32_t j = i; j < size_per_prop; j += wp_count) {
|
|
||||||
for (uint32_t k = 0; k < prop_count; k++) {
|
|
||||||
out_field[(k * size_per_prop) + j] =
|
|
||||||
in_buffer[(read_i * prop_count) + k];
|
|
||||||
}
|
|
||||||
read_i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
double ChemMaster::getSendTime() { return this->send_t; }
|
|
||||||
|
|
||||||
double ChemMaster::getRecvTime() { return this->recv_t; }
|
|
||||||
|
|
||||||
double ChemMaster::getIdleTime() { return this->master_idle; }
|
|
||||||
|
|
||||||
double ChemMaster::getWorkerTime() { return this->worker_t; }
|
|
||||||
|
|
||||||
double ChemMaster::getChemMasterTime() { return this->chem_master; }
|
|
||||||
|
|
||||||
double ChemMaster::getSeqTime() { return this->seq_t; }
|
|
||||||
112
src/ChemSeq.cpp
112
src/ChemSeq.cpp
@ -1,112 +0,0 @@
|
|||||||
/*
|
|
||||||
** Copyright (C) 2018-2021 Alexander Lindemann, Max Luebke (University of
|
|
||||||
** Potsdam)
|
|
||||||
**
|
|
||||||
** Copyright (C) 2018-2022 Marco De Lucia, Max Luebke (GFZ Potsdam)
|
|
||||||
**
|
|
||||||
** POET is free software; you can redistribute it and/or modify it under the
|
|
||||||
** terms of the GNU General Public License as published by the Free Software
|
|
||||||
** Foundation; either version 2 of the License, or (at your option) any later
|
|
||||||
** version.
|
|
||||||
**
|
|
||||||
** POET is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
||||||
** WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
||||||
** A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
||||||
**
|
|
||||||
** You should have received a copy of the GNU General Public License along with
|
|
||||||
** this program; if not, write to the Free Software Foundation, Inc., 51
|
|
||||||
** Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "poet/DiffusionModule.hpp"
|
|
||||||
#include "poet/SimParams.hpp"
|
|
||||||
#include <poet/ChemSimSeq.hpp>
|
|
||||||
#include <poet/Grid.hpp>
|
|
||||||
|
|
||||||
#include <Rcpp.h>
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <bits/stdint-uintn.h>
|
|
||||||
#include <iostream>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
using namespace Rcpp;
|
|
||||||
using namespace poet;
|
|
||||||
|
|
||||||
ChemSeq::ChemSeq(SimParams ¶ms, RInside &R_, Grid &grid_)
|
|
||||||
: BaseChemModule(params, R_, grid_) {
|
|
||||||
|
|
||||||
this->state = this->grid.RegisterState(
|
|
||||||
poet::BaseChemModule::CHEMISTRY_MODULE_NAME, this->prop_names);
|
|
||||||
std::vector<double> &field = this->state->mem;
|
|
||||||
|
|
||||||
field.resize(this->n_cells_per_prop * this->prop_names.size());
|
|
||||||
for (uint32_t i = 0; i < this->prop_names.size(); i++) {
|
|
||||||
std::vector<double> prop_vec =
|
|
||||||
this->grid.GetSpeciesByName(this->prop_names[i]);
|
|
||||||
|
|
||||||
std::copy(prop_vec.begin(), prop_vec.end(),
|
|
||||||
field.begin() + (i * this->n_cells_per_prop));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
poet::ChemSeq::~ChemSeq() {
|
|
||||||
if (this->phreeqc_rm) {
|
|
||||||
delete this->phreeqc_rm;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void poet::ChemSeq::InitModule(poet::ChemistryParams &chem_params) {
|
|
||||||
this->phreeqc_rm = new PhreeqcWrapper(this->n_cells_per_prop);
|
|
||||||
|
|
||||||
this->phreeqc_rm->SetupAndLoadDB(chem_params);
|
|
||||||
this->phreeqc_rm->InitFromFile(chem_params.input_script);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChemSeq::Simulate(double dt) {
|
|
||||||
double chem_a, chem_b;
|
|
||||||
|
|
||||||
/* start time measuring */
|
|
||||||
chem_a = MPI_Wtime();
|
|
||||||
|
|
||||||
std::vector<double> &field = this->state->mem;
|
|
||||||
|
|
||||||
// HACK: transfer the field into R data structure serving as input for phreeqc
|
|
||||||
R["TMP_T"] = field;
|
|
||||||
|
|
||||||
R.parseEvalQ("mysetup$state_T <- setNames(data.frame(matrix(TMP_T, "
|
|
||||||
"ncol=length(mysetup$grid$props), nrow=" +
|
|
||||||
std::to_string(this->n_cells_per_prop) +
|
|
||||||
")), mysetup$grid$props)");
|
|
||||||
|
|
||||||
this->phreeqc_rm->SetInternalsFromWP(field, this->n_cells_per_prop);
|
|
||||||
this->phreeqc_rm->SetTime(0);
|
|
||||||
this->phreeqc_rm->SetTimeStep(dt);
|
|
||||||
this->phreeqc_rm->RunCells();
|
|
||||||
|
|
||||||
// HACK: we will copy resulting field into global grid field. Maybe we will
|
|
||||||
// find a more performant way here ...
|
|
||||||
std::vector<double> vecSimResult;
|
|
||||||
this->phreeqc_rm->GetWPFromInternals(vecSimResult, this->n_cells_per_prop);
|
|
||||||
std::copy(vecSimResult.begin(), vecSimResult.end(), field.begin());
|
|
||||||
|
|
||||||
R["TMP_C"] = field;
|
|
||||||
|
|
||||||
R.parseEvalQ("mysetup$state_C <- setNames(data.frame(matrix(TMP_C, "
|
|
||||||
"ncol=length(mysetup$grid$props), nrow=" +
|
|
||||||
std::to_string(this->n_cells_per_prop) +
|
|
||||||
")), mysetup$grid$props)");
|
|
||||||
|
|
||||||
/* end time measuring */
|
|
||||||
chem_b = MPI_Wtime();
|
|
||||||
|
|
||||||
chem_t += chem_b - chem_a;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChemSeq::End() {
|
|
||||||
R["simtime_chemistry"] = this->chem_t;
|
|
||||||
R.parseEvalQ("profiling$simtime_chemistry <- simtime_chemistry");
|
|
||||||
}
|
|
||||||
|
|
||||||
double ChemSeq::getChemistryTime() { return this->chem_t; }
|
|
||||||
@ -1,305 +0,0 @@
|
|||||||
/*
|
|
||||||
** Copyright (C) 2018-2021 Alexander Lindemann, Max Luebke (University of
|
|
||||||
** Potsdam)
|
|
||||||
**
|
|
||||||
** Copyright (C) 2018-2021 Marco De Lucia (GFZ Potsdam)
|
|
||||||
**
|
|
||||||
** POET is free software; you can redistribute it and/or modify it under the
|
|
||||||
** terms of the GNU General Public License as published by the Free Software
|
|
||||||
** Foundation; either version 2 of the License, or (at your option) any later
|
|
||||||
** version.
|
|
||||||
**
|
|
||||||
** POET is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
||||||
** WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
||||||
** A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
||||||
**
|
|
||||||
** You should have received a copy of the GNU General Public License along with
|
|
||||||
** this program; if not, write to the Free Software Foundation, Inc., 51
|
|
||||||
** Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "poet/ChemSimPar.hpp"
|
|
||||||
#include "poet/DHT_Wrapper.hpp"
|
|
||||||
#include "poet/SimParams.hpp"
|
|
||||||
#include <Rcpp.h>
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <cmath>
|
|
||||||
#include <cstdint>
|
|
||||||
#include <iostream>
|
|
||||||
#include <mpi.h>
|
|
||||||
#include <ostream>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
using namespace poet;
|
|
||||||
using namespace std;
|
|
||||||
using namespace Rcpp;
|
|
||||||
|
|
||||||
ChemWorker::ChemWorker(SimParams ¶ms, RInside &R_, Grid &grid_,
|
|
||||||
MPI_Comm dht_comm)
|
|
||||||
: BaseChemModule(params, R_, grid_) {
|
|
||||||
t_simparams tmp = params.getNumParams();
|
|
||||||
this->wp_size = tmp.wp_size;
|
|
||||||
this->out_dir = params.getOutDir();
|
|
||||||
|
|
||||||
this->dt_differ = tmp.dt_differ;
|
|
||||||
this->dht_enabled = tmp.dht_enabled;
|
|
||||||
this->dht_size_per_process = tmp.dht_size_per_process;
|
|
||||||
this->dht_snaps = tmp.dht_snaps;
|
|
||||||
|
|
||||||
this->dht_file = params.getDHTFile();
|
|
||||||
|
|
||||||
this->mpi_buffer =
|
|
||||||
new double[(this->wp_size * this->prop_names.size()) + BUFFER_OFFSET];
|
|
||||||
this->mpi_buffer_results = new double[wp_size * this->prop_names.size()];
|
|
||||||
|
|
||||||
if (world_rank == 1)
|
|
||||||
cout << "CPP: Worker: DHT usage is " << (dht_enabled ? "ON" : "OFF")
|
|
||||||
<< endl;
|
|
||||||
|
|
||||||
if (this->dht_enabled) {
|
|
||||||
|
|
||||||
uint32_t iKeyCount = this->prop_names.size() + (dt_differ);
|
|
||||||
uint32_t iDataCount = this->prop_names.size();
|
|
||||||
|
|
||||||
if (world_rank == 1)
|
|
||||||
cout << "CPP: Worker: data count: " << iDataCount << " entries" << endl
|
|
||||||
<< "CPP: Worker: key count: " << iKeyCount << " entries" << endl
|
|
||||||
<< "CPP: Worker: memory per process "
|
|
||||||
<< params.getNumParams().dht_size_per_process / std::pow(10, 6)
|
|
||||||
<< " MByte" << endl;
|
|
||||||
|
|
||||||
dht = new DHT_Wrapper(params, dht_comm,
|
|
||||||
params.getNumParams().dht_size_per_process, iKeyCount,
|
|
||||||
iDataCount);
|
|
||||||
|
|
||||||
if (world_rank == 1)
|
|
||||||
cout << "CPP: Worker: DHT created!" << endl;
|
|
||||||
|
|
||||||
if (!dht_file.empty())
|
|
||||||
readFile();
|
|
||||||
// set size
|
|
||||||
dht_flags.resize(wp_size, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
this->timing.fill(0.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
ChemWorker::~ChemWorker() {
|
|
||||||
delete this->mpi_buffer;
|
|
||||||
delete this->mpi_buffer_results;
|
|
||||||
if (dht_enabled)
|
|
||||||
delete this->dht;
|
|
||||||
|
|
||||||
if (this->phreeqc_rm) {
|
|
||||||
delete this->phreeqc_rm;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChemWorker::loop() {
|
|
||||||
MPI_Status probe_status;
|
|
||||||
while (1) {
|
|
||||||
double idle_a = MPI_Wtime();
|
|
||||||
MPI_Probe(0, MPI_ANY_TAG, MPI_COMM_WORLD, &probe_status);
|
|
||||||
double idle_b = MPI_Wtime();
|
|
||||||
|
|
||||||
/* there is a work package to receive */
|
|
||||||
if (probe_status.MPI_TAG == TAG_WORK) {
|
|
||||||
idle_t += idle_b - idle_a;
|
|
||||||
doWork(probe_status);
|
|
||||||
}
|
|
||||||
/* end of iteration */
|
|
||||||
else if (probe_status.MPI_TAG == TAG_DHT_ITER) {
|
|
||||||
postIter();
|
|
||||||
}
|
|
||||||
/* end of simulation */
|
|
||||||
else if (probe_status.MPI_TAG == TAG_FINISH) {
|
|
||||||
finishWork();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void poet::ChemWorker::InitModule(poet::ChemistryParams &chem_params) {
|
|
||||||
this->phreeqc_rm = new PhreeqcWrapper(this->wp_size);
|
|
||||||
|
|
||||||
this->phreeqc_rm->SetupAndLoadDB(chem_params);
|
|
||||||
this->phreeqc_rm->InitFromFile(chem_params.input_script);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChemWorker::doWork(MPI_Status &probe_status) {
|
|
||||||
int count;
|
|
||||||
int local_work_package_size = 0;
|
|
||||||
|
|
||||||
static int counter = 1;
|
|
||||||
|
|
||||||
double dht_get_start, dht_get_end;
|
|
||||||
double phreeqc_time_start, phreeqc_time_end;
|
|
||||||
double dht_fill_start, dht_fill_end;
|
|
||||||
|
|
||||||
double dt;
|
|
||||||
|
|
||||||
bool bNoPhreeqc = false;
|
|
||||||
|
|
||||||
/* get number of doubles to be received */
|
|
||||||
MPI_Get_count(&probe_status, MPI_DOUBLE, &count);
|
|
||||||
|
|
||||||
/* receive */
|
|
||||||
MPI_Recv(mpi_buffer, count, MPI_DOUBLE, 0, TAG_WORK, MPI_COMM_WORLD,
|
|
||||||
MPI_STATUS_IGNORE);
|
|
||||||
|
|
||||||
/* decrement count of work_package by BUFFER_OFFSET */
|
|
||||||
count -= BUFFER_OFFSET;
|
|
||||||
|
|
||||||
/* check for changes on all additional variables given by the 'header' of
|
|
||||||
* mpi_buffer */
|
|
||||||
|
|
||||||
// work_package_size
|
|
||||||
local_work_package_size = mpi_buffer[count];
|
|
||||||
|
|
||||||
// current iteration of simulation
|
|
||||||
this->iteration = mpi_buffer[count + 1];
|
|
||||||
|
|
||||||
// current timestep size
|
|
||||||
dt = mpi_buffer[count + 2];
|
|
||||||
|
|
||||||
// current simulation time ('age' of simulation)
|
|
||||||
current_sim_time = mpi_buffer[count + 3];
|
|
||||||
|
|
||||||
/* 4th double value is currently a placeholder */
|
|
||||||
// placeholder = mpi_buffer[count+4];
|
|
||||||
|
|
||||||
std::vector<double> vecCurrWP(
|
|
||||||
mpi_buffer,
|
|
||||||
mpi_buffer + (local_work_package_size * this->prop_names.size()));
|
|
||||||
std::vector<int32_t> vecMappingWP(this->wp_size);
|
|
||||||
|
|
||||||
DHT_ResultObject DHT_Results;
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < local_work_package_size; i++) {
|
|
||||||
vecMappingWP[i] = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (local_work_package_size != this->wp_size) {
|
|
||||||
std::vector<double> vecFiller(
|
|
||||||
(this->wp_size - local_work_package_size) * this->prop_names.size(), 0);
|
|
||||||
vecCurrWP.insert(vecCurrWP.end(), vecFiller.begin(), vecFiller.end());
|
|
||||||
|
|
||||||
// set all remaining cells to inactive
|
|
||||||
for (int i = local_work_package_size; i < this->wp_size; i++) {
|
|
||||||
vecMappingWP[i] = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dht_enabled) {
|
|
||||||
/* check for values in DHT */
|
|
||||||
dht_get_start = MPI_Wtime();
|
|
||||||
DHT_Results = dht->checkDHT(local_work_package_size, dt, vecCurrWP);
|
|
||||||
dht_get_end = MPI_Wtime();
|
|
||||||
|
|
||||||
DHT_Results.ResultsToMapping(vecMappingWP);
|
|
||||||
}
|
|
||||||
|
|
||||||
phreeqc_time_start = MPI_Wtime();
|
|
||||||
this->phreeqc_rm->RunWorkPackage(vecCurrWP, vecMappingWP, current_sim_time,
|
|
||||||
dt);
|
|
||||||
phreeqc_time_end = MPI_Wtime();
|
|
||||||
|
|
||||||
if (dht_enabled) {
|
|
||||||
DHT_Results.ResultsToWP(vecCurrWP);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* send results to master */
|
|
||||||
MPI_Request send_req;
|
|
||||||
MPI_Isend(vecCurrWP.data(), count, MPI_DOUBLE, 0, TAG_WORK, MPI_COMM_WORLD,
|
|
||||||
&send_req);
|
|
||||||
|
|
||||||
if (dht_enabled) {
|
|
||||||
/* write results to DHT */
|
|
||||||
dht_fill_start = MPI_Wtime();
|
|
||||||
dht->fillDHT(local_work_package_size, DHT_Results, vecCurrWP);
|
|
||||||
dht_fill_end = MPI_Wtime();
|
|
||||||
|
|
||||||
timing[1] += dht_get_end - dht_get_start;
|
|
||||||
timing[2] += dht_fill_end - dht_fill_start;
|
|
||||||
}
|
|
||||||
|
|
||||||
timing[0] += phreeqc_time_end - phreeqc_time_start;
|
|
||||||
|
|
||||||
MPI_Wait(&send_req, MPI_STATUS_IGNORE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChemWorker::postIter() {
|
|
||||||
MPI_Recv(NULL, 0, MPI_DOUBLE, 0, TAG_DHT_ITER, MPI_COMM_WORLD,
|
|
||||||
MPI_STATUS_IGNORE);
|
|
||||||
if (dht_enabled) {
|
|
||||||
dht->printStatistics();
|
|
||||||
|
|
||||||
if (dht_snaps == 2) {
|
|
||||||
writeFile();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// synchronize all processes
|
|
||||||
MPI_Barrier(MPI_COMM_WORLD);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChemWorker::writeFile() {
|
|
||||||
cout.flush();
|
|
||||||
std::stringstream out;
|
|
||||||
out << out_dir << "/iter_" << setfill('0') << setw(3) << this->iteration
|
|
||||||
<< ".dht";
|
|
||||||
int res = dht->tableToFile(out.str().c_str());
|
|
||||||
if (res != DHT_SUCCESS && world_rank == 2)
|
|
||||||
cerr << "CPP: Worker: Error in writing current state of DHT to file."
|
|
||||||
<< endl;
|
|
||||||
else if (world_rank == 2)
|
|
||||||
cout << "CPP: Worker: Successfully written DHT to file " << out.str()
|
|
||||||
<< endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChemWorker::readFile() {
|
|
||||||
int res = dht->fileToTable((char *)dht_file.c_str());
|
|
||||||
if (res != DHT_SUCCESS) {
|
|
||||||
if (res == DHT_WRONG_FILE) {
|
|
||||||
if (world_rank == 1)
|
|
||||||
cerr << "CPP: Worker: Wrong file layout! Continue with empty DHT ..."
|
|
||||||
<< endl;
|
|
||||||
} else {
|
|
||||||
if (world_rank == 1)
|
|
||||||
cerr << "CPP: Worker: Error in loading current state of DHT from "
|
|
||||||
"file. Continue with empty DHT ..."
|
|
||||||
<< endl;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (world_rank == 2)
|
|
||||||
cout << "CPP: Worker: Successfully loaded state of DHT from file "
|
|
||||||
<< dht_file << endl;
|
|
||||||
std::cout.flush();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChemWorker::finishWork() {
|
|
||||||
/* before death, submit profiling/timings to master*/
|
|
||||||
MPI_Recv(NULL, 0, MPI_DOUBLE, 0, TAG_FINISH, MPI_COMM_WORLD,
|
|
||||||
MPI_STATUS_IGNORE);
|
|
||||||
|
|
||||||
// timings
|
|
||||||
MPI_Send(timing.data(), timing.size(), MPI_DOUBLE, 0, TAG_TIMING,
|
|
||||||
MPI_COMM_WORLD);
|
|
||||||
|
|
||||||
MPI_Send(&phreeqc_count, 1, MPI_INT, 0, TAG_TIMING, MPI_COMM_WORLD);
|
|
||||||
MPI_Send(&idle_t, 1, MPI_DOUBLE, 0, TAG_TIMING, MPI_COMM_WORLD);
|
|
||||||
|
|
||||||
if (dht_enabled) {
|
|
||||||
// dht_perf
|
|
||||||
int dht_perf[3];
|
|
||||||
dht_perf[0] = dht->getHits();
|
|
||||||
dht_perf[1] = dht->getMisses();
|
|
||||||
dht_perf[2] = dht->getEvictions();
|
|
||||||
MPI_Send(dht_perf, 3, MPI_INT, 0, TAG_DHT_PERF, MPI_COMM_WORLD);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dht_enabled && dht_snaps > 0)
|
|
||||||
writeFile();
|
|
||||||
}
|
|
||||||
32
src/ChemistryModule/CMakeLists.txt
Normal file
32
src/ChemistryModule/CMakeLists.txt
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
option(POET_USE_PRM_BACKEND "Use PhreeqcRM parallelization instead of poet's." OFF)
|
||||||
|
option(POET_DHT_DEBUG "Build with DHT debug info" OFF)
|
||||||
|
|
||||||
|
list(APPEND CHEM_MODEL_SRC "ChemistryModule.cpp" )
|
||||||
|
|
||||||
|
mark_as_advanced(PHREEQCRM_BUILD_MPI PHREEQCRM_DISABLE_OPENMP)
|
||||||
|
set(PHREEQCRM_DISABLE_OPENMP ON CACHE BOOL "" FORCE)
|
||||||
|
|
||||||
|
if(POET_USE_PRM_BACKEND)
|
||||||
|
set(PHREEQCRM_BUILD_MPI ON CACHE BOOL "" FORCE)
|
||||||
|
target_compile_definitions(poet_lib PRIVATE POET_USE_PRM)
|
||||||
|
else()
|
||||||
|
set(PHREEQCRM_BUILD_MPI OFF CACHE BOOL "" FORCE)
|
||||||
|
list(APPEND CHEM_MODEL_SRC "WorkerFunctions.cpp" "MasterFunctions.cpp" "DHT.c" "DHT_Wrapper.cpp" "HashFunctions.cpp")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_library(ChemistryModule ${CHEM_MODEL_SRC})
|
||||||
|
target_include_directories(ChemistryModule PUBLIC ${PROJECT_SOURCE_DIR}/include)
|
||||||
|
target_link_libraries(ChemistryModule
|
||||||
|
PUBLIC MPI::MPI_CXX PhreeqcRM
|
||||||
|
PRIVATE ${MATH_LIBRARY} ${CRYPTO_LIBRARY}
|
||||||
|
)
|
||||||
|
|
||||||
|
target_compile_definitions(ChemistryModule PUBLIC OMPI_SKIP_MPICXX)
|
||||||
|
|
||||||
|
if(POET_DHT_DEBUG)
|
||||||
|
target_compile_definitions(ChemistryModule PRIVATE DHT_STATISTICS)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(POET_USE_PRM_BACKEND)
|
||||||
|
target_compile_definitions(ChemistryModule PUBLIC POET_USE_PRM)
|
||||||
|
endif()
|
||||||
362
src/ChemistryModule/ChemistryModule.cpp
Normal file
362
src/ChemistryModule/ChemistryModule.cpp
Normal file
@ -0,0 +1,362 @@
|
|||||||
|
#include "poet/ChemistryModule.hpp"
|
||||||
|
#include "PhreeqcRM.h"
|
||||||
|
#include "poet/DHT_Wrapper.hpp"
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <mpi.h>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#ifndef POET_USE_PRM
|
||||||
|
poet::ChemistryModule::ChemistryModule(uint32_t nxyz, uint32_t wp_size,
|
||||||
|
MPI_Comm communicator)
|
||||||
|
: PhreeqcRM(nxyz, 1), group_comm(communicator), wp_size(wp_size) {
|
||||||
|
|
||||||
|
MPI_Comm_size(communicator, &this->comm_size);
|
||||||
|
MPI_Comm_rank(communicator, &this->comm_rank);
|
||||||
|
|
||||||
|
this->is_sequential = (this->comm_size == 1);
|
||||||
|
this->is_master = (this->comm_rank == 0);
|
||||||
|
|
||||||
|
if (!is_sequential && is_master) {
|
||||||
|
MPI_Bcast(&wp_size, 1, MPI_UINT32_T, 0, this->group_comm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
poet::ChemistryModule::~ChemistryModule() {
|
||||||
|
if (dht) {
|
||||||
|
delete dht;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
poet::ChemistryModule
|
||||||
|
poet::ChemistryModule::createWorker(MPI_Comm communicator) {
|
||||||
|
uint32_t wp_size;
|
||||||
|
MPI_Bcast(&wp_size, 1, MPI_UINT32_T, 0, communicator);
|
||||||
|
|
||||||
|
return ChemistryModule(wp_size, wp_size, communicator);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void poet::ChemistryModule::RunInitFile(const std::string &input_script_path) {
|
||||||
|
#ifndef POET_USE_PRM
|
||||||
|
if (this->is_master) {
|
||||||
|
int f_type = CHEM_INIT;
|
||||||
|
PropagateFunctionType(f_type);
|
||||||
|
|
||||||
|
int count = input_script_path.size();
|
||||||
|
ChemBCast(&count, 1, MPI_INT);
|
||||||
|
ChemBCast(const_cast<char *>(input_script_path.data()), count, MPI_CHAR);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
this->RunFile(true, true, false, input_script_path);
|
||||||
|
this->RunString(true, false, false, "DELETE; -all; PRINT; -warnings 0;");
|
||||||
|
|
||||||
|
this->FindComponents();
|
||||||
|
|
||||||
|
std::vector<std::string> props;
|
||||||
|
this->speciesPerModule.reserve(this->MODULE_COUNT);
|
||||||
|
|
||||||
|
std::vector<std::string> curr_prop_names = this->GetComponents();
|
||||||
|
props.insert(props.end(), curr_prop_names.begin(), curr_prop_names.end());
|
||||||
|
this->speciesPerModule.push_back(curr_prop_names.size());
|
||||||
|
|
||||||
|
curr_prop_names = this->GetEquilibriumPhases();
|
||||||
|
props.insert(props.end(), curr_prop_names.begin(), curr_prop_names.end());
|
||||||
|
char equilibrium = (curr_prop_names.empty() ? -1 : 1);
|
||||||
|
this->speciesPerModule.push_back(curr_prop_names.size());
|
||||||
|
|
||||||
|
curr_prop_names = this->GetExchangeNames();
|
||||||
|
props.insert(props.end(), curr_prop_names.begin(), curr_prop_names.end());
|
||||||
|
char exchange = (curr_prop_names.empty() ? -1 : 1);
|
||||||
|
this->speciesPerModule.push_back(curr_prop_names.size());
|
||||||
|
|
||||||
|
curr_prop_names = this->GetSurfaceNames();
|
||||||
|
props.insert(props.end(), curr_prop_names.begin(), curr_prop_names.end());
|
||||||
|
char surface = (curr_prop_names.empty() ? -1 : 1);
|
||||||
|
this->speciesPerModule.push_back(curr_prop_names.size());
|
||||||
|
|
||||||
|
// curr_prop_names = this->GetGasComponents();
|
||||||
|
// props.insert(props.end(), curr_prop_names.begin(), curr_prop_names.end());
|
||||||
|
// char gas = (curr_prop_names.empty() ? -1 : 1);
|
||||||
|
// this->speciesPerModule.push_back(curr_prop_names.size());
|
||||||
|
|
||||||
|
// curr_prop_names = this->GetSolidSolutionNames();
|
||||||
|
// props.insert(props.end(), curr_prop_names.begin(), curr_prop_names.end());
|
||||||
|
// char ssolutions = (curr_prop_names.empty() ? -1 : 1);
|
||||||
|
// this->speciesPerModule.push_back(curr_prop_names.size());
|
||||||
|
|
||||||
|
curr_prop_names = this->GetKineticReactions();
|
||||||
|
props.insert(props.end(), curr_prop_names.begin(), curr_prop_names.end());
|
||||||
|
char kinetics = (curr_prop_names.empty() ? -1 : 1);
|
||||||
|
this->speciesPerModule.push_back(curr_prop_names.size());
|
||||||
|
|
||||||
|
this->prop_count = props.size();
|
||||||
|
|
||||||
|
#ifdef POET_USE_PRM
|
||||||
|
std::vector<int> ic1;
|
||||||
|
ic1.resize(this->nxyz * 7, -1);
|
||||||
|
// TODO: hardcoded reaction modules
|
||||||
|
for (int i = 0; i < nxyz; i++) {
|
||||||
|
ic1[i] = 1; // Solution 1
|
||||||
|
ic1[nxyz + i] = equilibrium; // Equilibrium 1
|
||||||
|
ic1[2 * nxyz + i] = exchange; // Exchange none
|
||||||
|
ic1[3 * nxyz + i] = surface; // Surface none
|
||||||
|
ic1[4 * nxyz + i] = -1; // Gas phase none
|
||||||
|
ic1[5 * nxyz + i] = -1; // Solid solutions none
|
||||||
|
ic1[6 * nxyz + i] = kinetics; // Kinetics 1
|
||||||
|
}
|
||||||
|
|
||||||
|
this->InitialPhreeqc2Module(ic1);
|
||||||
|
#else
|
||||||
|
if (!this->is_master || this->is_sequential) {
|
||||||
|
std::vector<int> ic1;
|
||||||
|
ic1.resize(this->nxyz * 7, -1);
|
||||||
|
// TODO: hardcoded reaction modules
|
||||||
|
for (int i = 0; i < nxyz; i++) {
|
||||||
|
ic1[i] = 1; // Solution 1
|
||||||
|
ic1[nxyz + i] = equilibrium; // Equilibrium 1
|
||||||
|
ic1[2 * nxyz + i] = exchange; // Exchange none
|
||||||
|
ic1[3 * nxyz + i] = surface; // Surface none
|
||||||
|
ic1[4 * nxyz + i] = -1; // Gas phase none
|
||||||
|
ic1[5 * nxyz + i] = -1; // Solid solutions none
|
||||||
|
ic1[6 * nxyz + i] = kinetics; // Kinetics 1
|
||||||
|
}
|
||||||
|
|
||||||
|
this->InitialPhreeqc2Module(ic1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
this->prop_names = props;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef POET_USE_PRM
|
||||||
|
void poet::ChemistryModule::InitializeField(
|
||||||
|
uint32_t n_cells, const poet::ChemistryModule::SingleCMap &mapped_values) {
|
||||||
|
if (this->is_master) {
|
||||||
|
this->field.reserve(this->prop_count * n_cells);
|
||||||
|
for (const std::string &prop_name : this->prop_names) {
|
||||||
|
const auto m_it = mapped_values.find(prop_name);
|
||||||
|
if (m_it == mapped_values.end()) {
|
||||||
|
throw std::domain_error(
|
||||||
|
"Prop names vector does not match any key in given map.");
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<double> field_row(n_cells, m_it->second);
|
||||||
|
const auto chem_field_end = this->field.end();
|
||||||
|
this->field.insert(chem_field_end, field_row.begin(), field_row.end());
|
||||||
|
}
|
||||||
|
this->n_cells = n_cells;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void poet::ChemistryModule::InitializeField(
|
||||||
|
const poet::ChemistryModule::VectorCMap &mapped_values) {
|
||||||
|
if (this->is_master) {
|
||||||
|
for (const std::string &prop_name : this->prop_names) {
|
||||||
|
const auto m_it = mapped_values.find(prop_name);
|
||||||
|
if (m_it == mapped_values.end()) {
|
||||||
|
throw std::domain_error(
|
||||||
|
"Prop names vector does not match any key in given map.");
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto field_row = m_it->second;
|
||||||
|
const auto chem_field_end = this->field.end();
|
||||||
|
this->field.insert(chem_field_end, field_row.begin(), field_row.end());
|
||||||
|
}
|
||||||
|
this->n_cells = mapped_values.begin()->second.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void poet::ChemistryModule::SetDHTEnabled(bool enable, uint32_t size_mb) {
|
||||||
|
constexpr uint32_t MB_FACTOR = 1E6;
|
||||||
|
|
||||||
|
if (this->is_master) {
|
||||||
|
int ftype = CHEM_DHT_ENABLE;
|
||||||
|
PropagateFunctionType(ftype);
|
||||||
|
ChemBCast(&enable, 1, MPI_CXX_BOOL);
|
||||||
|
ChemBCast(&size_mb, 1, MPI_UINT32_T);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->dht_enabled = enable;
|
||||||
|
|
||||||
|
if (enable) {
|
||||||
|
MPI_Comm dht_comm;
|
||||||
|
|
||||||
|
if (this->is_master) {
|
||||||
|
MPI_Comm_split(this->group_comm, MPI_UNDEFINED, this->comm_rank,
|
||||||
|
&dht_comm);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MPI_Comm_split(this->group_comm, 1, this->comm_rank, &dht_comm);
|
||||||
|
|
||||||
|
if (this->dht) {
|
||||||
|
delete this->dht;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint32_t dht_size = size_mb * MB_FACTOR;
|
||||||
|
|
||||||
|
this->dht =
|
||||||
|
new DHT_Wrapper(dht_comm, dht_size, this->prop_count, this->prop_count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void poet::ChemistryModule::SetDHTSnaps(int type, const std::string &out_dir) {
|
||||||
|
if (this->is_master) {
|
||||||
|
int ftype = CHEM_DHT_SNAPS;
|
||||||
|
PropagateFunctionType(ftype);
|
||||||
|
|
||||||
|
int str_size = out_dir.size();
|
||||||
|
|
||||||
|
ChemBCast(&type, 1, MPI_INT);
|
||||||
|
ChemBCast(&str_size, 1, MPI_INT);
|
||||||
|
ChemBCast(const_cast<char *>(out_dir.data()), str_size, MPI_CHAR);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->dht_file_out_dir = out_dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
void poet::ChemistryModule::SetDHTSignifVector(
|
||||||
|
std::vector<uint32_t> signif_vec) {
|
||||||
|
if (this->is_master) {
|
||||||
|
if (signif_vec.size() != this->prop_count) {
|
||||||
|
throw std::runtime_error(
|
||||||
|
"Significant vector sizes mismatches prop count.");
|
||||||
|
}
|
||||||
|
|
||||||
|
int ftype = CHEM_DHT_SIGNIF_VEC;
|
||||||
|
PropagateFunctionType(ftype);
|
||||||
|
ChemBCast(signif_vec.data(), signif_vec.size(), MPI_UINT32_T);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->dht->SetSignifVector(signif_vec);
|
||||||
|
}
|
||||||
|
|
||||||
|
void poet::ChemistryModule::SetDHTPropTypeVector(
|
||||||
|
std::vector<uint32_t> proptype_vec) {
|
||||||
|
if (this->is_master) {
|
||||||
|
if (proptype_vec.size() != this->prop_count) {
|
||||||
|
throw std::runtime_error("Prop type vector sizes mismatches prop count.");
|
||||||
|
}
|
||||||
|
|
||||||
|
int ftype = CHEM_DHT_PROP_TYPE_VEC;
|
||||||
|
PropagateFunctionType(ftype);
|
||||||
|
ChemBCast(proptype_vec.data(), proptype_vec.size(), MPI_UINT32_T);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->dht->SetPropTypeVector(proptype_vec);
|
||||||
|
}
|
||||||
|
|
||||||
|
void poet::ChemistryModule::ReadDHTFile(const std::string &input_file) {
|
||||||
|
if (this->is_master) {
|
||||||
|
int ftype = CHEM_DHT_READ_FILE;
|
||||||
|
PropagateFunctionType(ftype);
|
||||||
|
int str_size = input_file.size();
|
||||||
|
|
||||||
|
ChemBCast(&str_size, 1, MPI_INT);
|
||||||
|
ChemBCast(const_cast<char *>(input_file.data()), str_size, MPI_CHAR);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this->dht_enabled) {
|
||||||
|
throw std::runtime_error("DHT file cannot be read. DHT is not enabled.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this->is_master) {
|
||||||
|
WorkerReadDHTDump(input_file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void poet::ChemistryModule::GetWPFromInternals(std::vector<double> &vecWP,
|
||||||
|
uint32_t wp_size) {
|
||||||
|
std::vector<double> vecCurrOutput;
|
||||||
|
|
||||||
|
vecWP.clear();
|
||||||
|
vecWP.reserve(this->prop_count * wp_size);
|
||||||
|
|
||||||
|
this->GetConcentrations(vecCurrOutput);
|
||||||
|
vecWP.insert(vecWP.end(), vecCurrOutput.begin(), vecCurrOutput.end());
|
||||||
|
|
||||||
|
if (this->speciesPerModule[1] != 0) {
|
||||||
|
this->GetPPhaseMoles(vecCurrOutput);
|
||||||
|
vecWP.insert(vecWP.end(), vecCurrOutput.begin(), vecCurrOutput.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: Block for 'Surface' and 'Exchange' is missing because of missing
|
||||||
|
// Getters @ PhreeqcRM
|
||||||
|
// ...
|
||||||
|
// BLOCK_END
|
||||||
|
|
||||||
|
if (this->speciesPerModule[4] != 0) {
|
||||||
|
this->GetKineticsMoles(vecCurrOutput);
|
||||||
|
vecWP.insert(vecWP.end(), vecCurrOutput.begin(), vecCurrOutput.end());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void poet::ChemistryModule::SetInternalsFromWP(const std::vector<double> &vecWP,
|
||||||
|
uint32_t wp_size) {
|
||||||
|
uint32_t iCurrElements;
|
||||||
|
|
||||||
|
auto itStart = vecWP.begin();
|
||||||
|
auto itEnd = itStart;
|
||||||
|
|
||||||
|
// this->SetMappingForWP(iCurrWPSize);
|
||||||
|
|
||||||
|
int nchem = this->GetChemistryCellCount();
|
||||||
|
|
||||||
|
iCurrElements = this->speciesPerModule[0];
|
||||||
|
|
||||||
|
itEnd += iCurrElements * wp_size;
|
||||||
|
this->SetConcentrations(std::vector<double>(itStart, itEnd));
|
||||||
|
itStart = itEnd;
|
||||||
|
|
||||||
|
// Equlibirum Phases
|
||||||
|
if ((iCurrElements = this->speciesPerModule[1]) != 0) {
|
||||||
|
itEnd += iCurrElements * wp_size;
|
||||||
|
this->SetPPhaseMoles(std::vector<double>(itStart, itEnd));
|
||||||
|
itStart = itEnd;
|
||||||
|
}
|
||||||
|
|
||||||
|
// // NOTE: Block for 'Surface' and 'Exchange' is missing because of missing
|
||||||
|
// // setters @ PhreeqcRM
|
||||||
|
// // ...
|
||||||
|
// // BLOCK_END
|
||||||
|
|
||||||
|
if ((iCurrElements = this->speciesPerModule[4]) != 0) {
|
||||||
|
itEnd += iCurrElements * wp_size;
|
||||||
|
this->SetKineticsMoles(std::vector<double>(itStart, itEnd));
|
||||||
|
itStart = itEnd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#else //POET_USE_PRM
|
||||||
|
|
||||||
|
inline void poet::ChemistryModule::PrmToPoetField(std::vector<double> &field) {
|
||||||
|
GetConcentrations(field);
|
||||||
|
int col = GetSelectedOutputColumnCount();
|
||||||
|
int rows = GetSelectedOutputRowCount();
|
||||||
|
|
||||||
|
field.reserve(field.size() + 3 * rows);
|
||||||
|
|
||||||
|
std::vector<double> so;
|
||||||
|
GetSelectedOutput(so);
|
||||||
|
|
||||||
|
for (int j = 0; j < col; j += 2) {
|
||||||
|
const auto start = so.begin() + (j * rows);
|
||||||
|
const auto end = start + rows;
|
||||||
|
field.insert(field.end(), start, end);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void poet::ChemistryModule::RunCells() {
|
||||||
|
PhreeqcRM::RunCells();
|
||||||
|
PrmToPoetField(this->field);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -18,18 +18,19 @@
|
|||||||
** Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
** Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "poet/DHT_Wrapper.hpp"
|
||||||
|
#include "poet/DHT_Types.hpp"
|
||||||
#include "poet/HashFunctions.hpp"
|
#include "poet/HashFunctions.hpp"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <openssl/evp.h>
|
|
||||||
#include <poet/DHT_Wrapper.hpp>
|
|
||||||
|
|
||||||
#include <math.h>
|
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <math.h>
|
||||||
|
#include <openssl/evp.h>
|
||||||
|
#include <stdexcept>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
using namespace poet;
|
using namespace poet;
|
||||||
@ -67,9 +68,8 @@ void poet::DHT_ResultObject::ResultsToWP(std::vector<double> &curr_wp) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DHT_Wrapper::DHT_Wrapper(const poet::SimParams ¶ms, MPI_Comm dht_comm,
|
DHT_Wrapper::DHT_Wrapper(MPI_Comm dht_comm, uint32_t dht_size,
|
||||||
uint32_t dht_size, uint32_t key_count,
|
uint32_t key_count, uint32_t data_count)
|
||||||
uint32_t data_count)
|
|
||||||
: key_count(key_count), data_count(data_count) {
|
: key_count(key_count), data_count(data_count) {
|
||||||
poet::initHashCtx(EVP_md5());
|
poet::initHashCtx(EVP_md5());
|
||||||
// initialize DHT object
|
// initialize DHT object
|
||||||
@ -80,20 +80,26 @@ DHT_Wrapper::DHT_Wrapper(const poet::SimParams ¶ms, MPI_Comm dht_comm,
|
|||||||
&poet::hashDHT);
|
&poet::hashDHT);
|
||||||
|
|
||||||
// extract needed values from sim_param struct
|
// extract needed values from sim_param struct
|
||||||
t_simparams tmp = params.getNumParams();
|
// t_simparams tmp = params.getNumParams();
|
||||||
|
|
||||||
this->dt_differ = tmp.dt_differ;
|
// this->dt_differ = tmp.dt_differ;
|
||||||
this->dht_log = tmp.dht_log;
|
// this->dht_log = tmp.dht_log;
|
||||||
|
|
||||||
this->dht_signif_vector = params.getDHTSignifVector();
|
// this->dht_signif_vector = params.getDHTSignifVector();
|
||||||
this->dht_prop_type_vector = params.getDHTPropTypeVector();
|
// this->dht_prop_type_vector = params.getDHTPropTypeVector();
|
||||||
|
|
||||||
|
this->dht_signif_vector.resize(key_size, DHT_KEY_SIGNIF_DEFAULT);
|
||||||
|
this->dht_signif_vector[0] = DHT_KEY_SIGNIF_TOTALS;
|
||||||
|
this->dht_signif_vector[1] = DHT_KEY_SIGNIF_TOTALS;
|
||||||
|
this->dht_signif_vector[2] = DHT_KEY_SIGNIF_CHARGE;
|
||||||
|
|
||||||
|
this->dht_prop_type_vector.resize(key_size, DHT_TYPE_DEFAULT);
|
||||||
}
|
}
|
||||||
|
|
||||||
DHT_Wrapper::~DHT_Wrapper() {
|
DHT_Wrapper::~DHT_Wrapper() {
|
||||||
// free DHT
|
// free DHT
|
||||||
DHT_free(dht_object, NULL, NULL);
|
DHT_free(dht_object, NULL, NULL);
|
||||||
// free fuzzing buffer
|
|
||||||
free(fuzzing_buffer);
|
|
||||||
poet::freeHashCtx();
|
poet::freeHashCtx();
|
||||||
}
|
}
|
||||||
auto DHT_Wrapper::checkDHT(int length, double dt,
|
auto DHT_Wrapper::checkDHT(int length, double dt,
|
||||||
@ -184,17 +190,11 @@ void DHT_Wrapper::printStatistics() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t DHT_Wrapper::getHits() { return this->dht_hits; }
|
|
||||||
|
|
||||||
uint64_t DHT_Wrapper::getMisses() { return this->dht_miss; }
|
|
||||||
|
|
||||||
uint64_t DHT_Wrapper::getEvictions() { return this->dht_evictions; }
|
|
||||||
|
|
||||||
std::vector<DHT_Keyelement> DHT_Wrapper::fuzzForDHT(int var_count, void *key,
|
std::vector<DHT_Keyelement> DHT_Wrapper::fuzzForDHT(int var_count, void *key,
|
||||||
double dt) {
|
double dt) {
|
||||||
constexpr double zero_val = 10E-14;
|
constexpr double zero_val = 10E-14;
|
||||||
|
|
||||||
std::vector<DHT_Keyelement> vecFuzz(var_count);
|
std::vector<DHT_Keyelement> vecFuzz(var_count + 1);
|
||||||
std::memset(&vecFuzz[0], 0, sizeof(DHT_Keyelement) * var_count);
|
std::memset(&vecFuzz[0], 0, sizeof(DHT_Keyelement) * var_count);
|
||||||
|
|
||||||
unsigned int i = 0;
|
unsigned int i = 0;
|
||||||
@ -203,10 +203,11 @@ std::vector<DHT_Keyelement> DHT_Wrapper::fuzzForDHT(int var_count, void *key,
|
|||||||
for (i = 0; i < (unsigned int)var_count; i++) {
|
for (i = 0; i < (unsigned int)var_count; i++) {
|
||||||
double &curr_key = ((double *)key)[i];
|
double &curr_key = ((double *)key)[i];
|
||||||
if (curr_key != 0) {
|
if (curr_key != 0) {
|
||||||
if (curr_key < zero_val && this->dht_prop_type_vector[i] == "act") {
|
if (curr_key < zero_val &&
|
||||||
|
this->dht_prop_type_vector[i] == DHT_TYPE_ACT) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (this->dht_prop_type_vector[i] == "ignore") {
|
if (this->dht_prop_type_vector[i] == DHT_TYPE_IGNORE) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
vecFuzz[i] = round_key_element(curr_key, dht_signif_vector[i]);
|
vecFuzz[i] = round_key_element(curr_key, dht_signif_vector[i]);
|
||||||
@ -214,9 +215,24 @@ std::vector<DHT_Keyelement> DHT_Wrapper::fuzzForDHT(int var_count, void *key,
|
|||||||
}
|
}
|
||||||
// if timestep differs over iterations set current current time step at the
|
// if timestep differs over iterations set current current time step at the
|
||||||
// end of fuzzing buffer
|
// end of fuzzing buffer
|
||||||
if (dt_differ) {
|
vecFuzz[var_count] = round_key_element(dt, 55);
|
||||||
vecFuzz[var_count] = round_key_element(dt, 55);
|
|
||||||
}
|
|
||||||
|
|
||||||
return vecFuzz;
|
return vecFuzz;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void poet::DHT_Wrapper::SetSignifVector(std::vector<uint32_t> signif_vec) {
|
||||||
|
if (signif_vec.size() != this->key_count) {
|
||||||
|
throw std::runtime_error(
|
||||||
|
"Significant vector size mismatches count of key elements.");
|
||||||
|
}
|
||||||
|
|
||||||
|
this->dht_signif_vector = signif_vec;
|
||||||
|
}
|
||||||
|
void poet::DHT_Wrapper::SetPropTypeVector(std::vector<uint32_t> prop_type_vec) {
|
||||||
|
if (prop_type_vec.size() != this->key_count) {
|
||||||
|
throw std::runtime_error(
|
||||||
|
"Prop type vector size mismatches count of key elements.");
|
||||||
|
}
|
||||||
|
|
||||||
|
this->dht_prop_type_vector = prop_type_vec;
|
||||||
|
}
|
||||||
360
src/ChemistryModule/MasterFunctions.cpp
Normal file
360
src/ChemistryModule/MasterFunctions.cpp
Normal file
@ -0,0 +1,360 @@
|
|||||||
|
#include "PhreeqcRM.h"
|
||||||
|
#include "poet/ChemistryModule.hpp"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <mpi.h>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
std::vector<uint32_t>
|
||||||
|
poet::ChemistryModule::MasterGatherWorkerMetrics(int type) const {
|
||||||
|
MPI_Bcast(&type, 1, MPI_INT, 0, this->group_comm);
|
||||||
|
|
||||||
|
uint32_t dummy;
|
||||||
|
std::vector<uint32_t> metrics(this->comm_size);
|
||||||
|
|
||||||
|
MPI_Gather(&dummy, 1, MPI_UINT32_T, metrics.data(), 1, MPI_UINT32_T, 0,
|
||||||
|
this->group_comm);
|
||||||
|
|
||||||
|
metrics.erase(metrics.begin());
|
||||||
|
return metrics;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<double>
|
||||||
|
poet::ChemistryModule::MasterGatherWorkerTimings(int type) const {
|
||||||
|
MPI_Bcast(&type, 1, MPI_INT, 0, this->group_comm);
|
||||||
|
|
||||||
|
double dummy;
|
||||||
|
std::vector<double> timings(this->comm_size);
|
||||||
|
|
||||||
|
MPI_Gather(&dummy, 1, MPI_DOUBLE, timings.data(), 1, MPI_DOUBLE, 0,
|
||||||
|
this->group_comm);
|
||||||
|
|
||||||
|
timings.erase(timings.begin());
|
||||||
|
return timings;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<double> poet::ChemistryModule::GetWorkerPhreeqcTimings() const {
|
||||||
|
int type = CHEM_PERF;
|
||||||
|
MPI_Bcast(&type, 1, MPI_INT, 0, this->group_comm);
|
||||||
|
return MasterGatherWorkerTimings(WORKER_PHREEQC);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<double> poet::ChemistryModule::GetWorkerDHTGetTimings() const {
|
||||||
|
int type = CHEM_PERF;
|
||||||
|
MPI_Bcast(&type, 1, MPI_INT, 0, this->group_comm);
|
||||||
|
return MasterGatherWorkerTimings(WORKER_DHT_GET);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<double> poet::ChemistryModule::GetWorkerDHTFillTimings() const {
|
||||||
|
int type = CHEM_PERF;
|
||||||
|
MPI_Bcast(&type, 1, MPI_INT, 0, this->group_comm);
|
||||||
|
return MasterGatherWorkerTimings(WORKER_DHT_FILL);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<double> poet::ChemistryModule::GetWorkerIdleTimings() const {
|
||||||
|
int type = CHEM_PERF;
|
||||||
|
MPI_Bcast(&type, 1, MPI_INT, 0, this->group_comm);
|
||||||
|
return MasterGatherWorkerTimings(WORKER_IDLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint32_t> poet::ChemistryModule::GetWorkerDHTHits() const {
|
||||||
|
int type = CHEM_PERF;
|
||||||
|
MPI_Bcast(&type, 1, MPI_INT, 0, this->group_comm);
|
||||||
|
return MasterGatherWorkerMetrics(WORKER_DHT_HITS);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint32_t> poet::ChemistryModule::GetWorkerDHTMiss() const {
|
||||||
|
int type = CHEM_PERF;
|
||||||
|
MPI_Bcast(&type, 1, MPI_INT, 0, this->group_comm);
|
||||||
|
return MasterGatherWorkerMetrics(WORKER_DHT_MISS);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint32_t> poet::ChemistryModule::GetWorkerDHTEvictions() const {
|
||||||
|
int type = CHEM_PERF;
|
||||||
|
MPI_Bcast(&type, 1, MPI_INT, 0, this->group_comm);
|
||||||
|
return MasterGatherWorkerMetrics(WORKER_DHT_EVICTIONS);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::vector<double> shuffleField(const std::vector<double> &in_field,
|
||||||
|
uint32_t size_per_prop,
|
||||||
|
uint32_t prop_count,
|
||||||
|
uint32_t wp_count) {
|
||||||
|
std::vector<double> out_buffer(in_field.size());
|
||||||
|
uint32_t write_i = 0;
|
||||||
|
for (uint32_t i = 0; i < wp_count; i++) {
|
||||||
|
for (uint32_t j = i; j < size_per_prop; j += wp_count) {
|
||||||
|
for (uint32_t k = 0; k < prop_count; k++) {
|
||||||
|
out_buffer[(write_i * prop_count) + k] =
|
||||||
|
in_field[(k * size_per_prop) + j];
|
||||||
|
}
|
||||||
|
write_i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void unshuffleField(const std::vector<double> &in_buffer,
|
||||||
|
uint32_t size_per_prop, uint32_t prop_count,
|
||||||
|
uint32_t wp_count, std::vector<double> &out_field) {
|
||||||
|
uint32_t read_i = 0;
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < wp_count; i++) {
|
||||||
|
for (uint32_t j = i; j < size_per_prop; j += wp_count) {
|
||||||
|
for (uint32_t k = 0; k < prop_count; k++) {
|
||||||
|
out_field[(k * size_per_prop) + j] =
|
||||||
|
in_buffer[(read_i * prop_count) + k];
|
||||||
|
}
|
||||||
|
read_i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void printProgressbar(int count_pkgs, int n_wp, int barWidth = 70) {
|
||||||
|
/* visual progress */
|
||||||
|
double progress = (float)(count_pkgs + 1) / n_wp;
|
||||||
|
|
||||||
|
std::cout << "[";
|
||||||
|
int pos = barWidth * progress;
|
||||||
|
for (int iprog = 0; iprog < barWidth; ++iprog) {
|
||||||
|
if (iprog < pos)
|
||||||
|
std::cout << "=";
|
||||||
|
else if (iprog == pos)
|
||||||
|
std::cout << ">";
|
||||||
|
else
|
||||||
|
std::cout << " ";
|
||||||
|
}
|
||||||
|
std::cout << "] " << int(progress * 100.0) << " %\r";
|
||||||
|
std::cout.flush();
|
||||||
|
/* end visual progress */
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void poet::ChemistryModule::MasterSendPkgs(
|
||||||
|
worker_list_t &w_list, workpointer_t &work_pointer, int &pkg_to_send,
|
||||||
|
int &count_pkgs, int &free_workers, double dt, uint32_t iteration,
|
||||||
|
const std::vector<uint32_t> &wp_sizes_vector) {
|
||||||
|
/* declare variables */
|
||||||
|
int local_work_package_size;
|
||||||
|
|
||||||
|
/* search for free workers and send work */
|
||||||
|
for (int p = 0; p < this->comm_size - 1; p++) {
|
||||||
|
if (w_list[p].has_work == 0 && pkg_to_send > 0) /* worker is free */ {
|
||||||
|
/* to enable different work_package_size, set local copy of
|
||||||
|
* work_package_size to pre-calculated work package size vector */
|
||||||
|
|
||||||
|
local_work_package_size = (int)wp_sizes_vector[count_pkgs];
|
||||||
|
count_pkgs++;
|
||||||
|
|
||||||
|
/* note current processed work package in workerlist */
|
||||||
|
w_list[p].send_addr = work_pointer.base();
|
||||||
|
|
||||||
|
/* push work pointer to next work package */
|
||||||
|
const uint32_t end_of_wp = local_work_package_size * this->prop_count;
|
||||||
|
std::vector<double> send_buffer(end_of_wp + this->BUFFER_OFFSET);
|
||||||
|
std::copy(work_pointer, work_pointer + end_of_wp, send_buffer.begin());
|
||||||
|
|
||||||
|
work_pointer += end_of_wp;
|
||||||
|
|
||||||
|
// fill send buffer starting with work_package ...
|
||||||
|
// followed by: work_package_size
|
||||||
|
send_buffer[end_of_wp] = (double)local_work_package_size;
|
||||||
|
// current iteration of simulation
|
||||||
|
send_buffer[end_of_wp + 1] = (double)iteration;
|
||||||
|
// size of timestep in seconds
|
||||||
|
send_buffer[end_of_wp + 2] = dt;
|
||||||
|
// current time of simulation (age) in seconds
|
||||||
|
send_buffer[end_of_wp + 3] = this->simtime;
|
||||||
|
// placeholder for work_package_count
|
||||||
|
send_buffer[end_of_wp + 4] = 0.;
|
||||||
|
|
||||||
|
/* ATTENTION Worker p has rank p+1 */
|
||||||
|
// MPI_Send(send_buffer, end_of_wp + BUFFER_OFFSET, MPI_DOUBLE, p + 1,
|
||||||
|
// LOOP_WORK, this->group_comm);
|
||||||
|
MPI_Send(send_buffer.data(), send_buffer.size(), MPI_DOUBLE, p + 1,
|
||||||
|
LOOP_WORK, this->group_comm);
|
||||||
|
|
||||||
|
/* Mark that worker has work to do */
|
||||||
|
w_list[p].has_work = 1;
|
||||||
|
free_workers--;
|
||||||
|
pkg_to_send -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void poet::ChemistryModule::MasterRecvPkgs(worker_list_t &w_list,
|
||||||
|
int &pkg_to_recv,
|
||||||
|
bool to_send,
|
||||||
|
int &free_workers) {
|
||||||
|
/* declare most of the variables here */
|
||||||
|
int need_to_receive = 1;
|
||||||
|
double idle_a, idle_b;
|
||||||
|
int p, size;
|
||||||
|
|
||||||
|
MPI_Status probe_status;
|
||||||
|
// master_recv_a = MPI_Wtime();
|
||||||
|
/* start to loop as long there are packages to recv and the need to receive
|
||||||
|
*/
|
||||||
|
while (need_to_receive && pkg_to_recv > 0) {
|
||||||
|
// only of there are still packages to send and free workers are available
|
||||||
|
if (to_send && free_workers > 0)
|
||||||
|
// non blocking probing
|
||||||
|
MPI_Iprobe(MPI_ANY_SOURCE, LOOP_WORK, MPI_COMM_WORLD, &need_to_receive,
|
||||||
|
&probe_status);
|
||||||
|
else {
|
||||||
|
idle_a = MPI_Wtime();
|
||||||
|
// blocking probing
|
||||||
|
MPI_Probe(MPI_ANY_SOURCE, LOOP_WORK, MPI_COMM_WORLD, &probe_status);
|
||||||
|
idle_b = MPI_Wtime();
|
||||||
|
this->idle_t += idle_b - idle_a;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if need_to_receive was set to true above, so there is a message to
|
||||||
|
* receive */
|
||||||
|
if (need_to_receive) {
|
||||||
|
p = probe_status.MPI_SOURCE;
|
||||||
|
MPI_Get_count(&probe_status, MPI_DOUBLE, &size);
|
||||||
|
MPI_Recv(w_list[p - 1].send_addr, size, MPI_DOUBLE, p, LOOP_WORK,
|
||||||
|
this->group_comm, MPI_STATUS_IGNORE);
|
||||||
|
w_list[p - 1].has_work = 0;
|
||||||
|
pkg_to_recv -= 1;
|
||||||
|
free_workers++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void poet::ChemistryModule::RunCells() {
|
||||||
|
if (this->is_sequential) {
|
||||||
|
MasterRunSequential();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MasterRunParallel();
|
||||||
|
}
|
||||||
|
|
||||||
|
void poet::ChemistryModule::MasterRunSequential() {
|
||||||
|
SetInternalsFromWP(this->field, this->nxyz);
|
||||||
|
PhreeqcRM::RunCells();
|
||||||
|
GetWPFromInternals(this->field, this->nxyz);
|
||||||
|
}
|
||||||
|
|
||||||
|
void poet::ChemistryModule::MasterRunParallel() {
|
||||||
|
/* declare most of the needed variables here */
|
||||||
|
double chem_a, chem_b;
|
||||||
|
double seq_a, seq_b, seq_c, seq_d;
|
||||||
|
double worker_chemistry_a, worker_chemistry_b;
|
||||||
|
double sim_e_chemistry, sim_f_chemistry;
|
||||||
|
int pkg_to_send, pkg_to_recv;
|
||||||
|
int free_workers;
|
||||||
|
int i_pkgs;
|
||||||
|
|
||||||
|
int ftype = CHEM_WORK_LOOP;
|
||||||
|
PropagateFunctionType(ftype);
|
||||||
|
|
||||||
|
MPI_Barrier(this->group_comm);
|
||||||
|
|
||||||
|
double dt = this->PhreeqcRM::GetTimeStep();
|
||||||
|
static uint32_t iteration = 0;
|
||||||
|
|
||||||
|
/* start time measurement of whole chemistry simulation */
|
||||||
|
chem_a = MPI_Wtime();
|
||||||
|
|
||||||
|
/* start time measurement of sequential part */
|
||||||
|
seq_a = MPI_Wtime();
|
||||||
|
|
||||||
|
const std::vector<uint32_t> wp_sizes_vector =
|
||||||
|
CalculateWPSizesVector(this->n_cells, this->wp_size);
|
||||||
|
|
||||||
|
/* shuffle grid */
|
||||||
|
// grid.shuffleAndExport(mpi_buffer);
|
||||||
|
std::vector<double> mpi_buffer = shuffleField(
|
||||||
|
this->field, this->n_cells, this->prop_count, wp_sizes_vector.size());
|
||||||
|
|
||||||
|
/* setup local variables */
|
||||||
|
pkg_to_send = wp_sizes_vector.size();
|
||||||
|
pkg_to_recv = wp_sizes_vector.size();
|
||||||
|
|
||||||
|
workpointer_t work_pointer = mpi_buffer.begin();
|
||||||
|
worker_list_t worker_list(this->comm_size - 1);
|
||||||
|
|
||||||
|
free_workers = this->comm_size - 1;
|
||||||
|
i_pkgs = 0;
|
||||||
|
|
||||||
|
/* end time measurement of sequential part */
|
||||||
|
seq_b = MPI_Wtime();
|
||||||
|
seq_t += seq_b - seq_a;
|
||||||
|
|
||||||
|
/* start time measurement of chemistry time needed for send/recv loop */
|
||||||
|
worker_chemistry_a = MPI_Wtime();
|
||||||
|
|
||||||
|
/* start send/recv loop */
|
||||||
|
// while there are still packages to recv
|
||||||
|
while (pkg_to_recv > 0) {
|
||||||
|
// print a progressbar to stdout
|
||||||
|
printProgressbar((int)i_pkgs, (int)wp_sizes_vector.size());
|
||||||
|
// while there are still packages to send
|
||||||
|
if (pkg_to_send > 0) {
|
||||||
|
// send packages to all free workers ...
|
||||||
|
MasterSendPkgs(worker_list, work_pointer, pkg_to_send, i_pkgs,
|
||||||
|
free_workers, dt, iteration, wp_sizes_vector);
|
||||||
|
}
|
||||||
|
// ... and try to receive them from workers who has finished their work
|
||||||
|
MasterRecvPkgs(worker_list, pkg_to_recv, pkg_to_send > 0, free_workers);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Just to complete the progressbar
|
||||||
|
std::cout << std::endl;
|
||||||
|
|
||||||
|
/* stop time measurement of chemistry time needed for send/recv loop */
|
||||||
|
worker_chemistry_b = MPI_Wtime();
|
||||||
|
this->send_recv_t += worker_chemistry_b - worker_chemistry_a;
|
||||||
|
|
||||||
|
/* start time measurement of sequential part */
|
||||||
|
seq_c = MPI_Wtime();
|
||||||
|
|
||||||
|
/* unshuffle grid */
|
||||||
|
// grid.importAndUnshuffle(mpi_buffer);
|
||||||
|
unshuffleField(mpi_buffer, this->n_cells, this->prop_count,
|
||||||
|
wp_sizes_vector.size(), this->field);
|
||||||
|
|
||||||
|
/* do master stuff */
|
||||||
|
|
||||||
|
/* start time measurement of master chemistry */
|
||||||
|
sim_e_chemistry = MPI_Wtime();
|
||||||
|
|
||||||
|
/* end time measurement of sequential part */
|
||||||
|
seq_d = MPI_Wtime();
|
||||||
|
this->seq_t += seq_d - seq_c;
|
||||||
|
|
||||||
|
/* end time measurement of whole chemistry simulation */
|
||||||
|
|
||||||
|
/* advise workers to end chemistry iteration */
|
||||||
|
for (int i = 1; i < this->comm_size; i++) {
|
||||||
|
MPI_Send(NULL, 0, MPI_DOUBLE, i, LOOP_END, this->group_comm);
|
||||||
|
}
|
||||||
|
chem_b = MPI_Wtime();
|
||||||
|
this->chem_t += chem_b - chem_a;
|
||||||
|
|
||||||
|
this->simtime += dt;
|
||||||
|
iteration++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void poet::ChemistryModule::MasterLoopBreak() {
|
||||||
|
int type = CHEM_BREAK_MAIN_LOOP;
|
||||||
|
MPI_Bcast(&type, 1, MPI_INT, 0, this->group_comm);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint32_t>
|
||||||
|
poet::ChemistryModule::CalculateWPSizesVector(uint32_t n_cells,
|
||||||
|
uint32_t wp_size) const {
|
||||||
|
bool mod_pkgs = (n_cells % wp_size) != 0;
|
||||||
|
uint32_t n_packages = (uint32_t)(n_cells / wp_size) + mod_pkgs;
|
||||||
|
|
||||||
|
std::vector<uint32_t> wp_sizes_vector(n_packages, 0);
|
||||||
|
|
||||||
|
for (int i = 0; i < n_cells; i++) {
|
||||||
|
wp_sizes_vector[i % n_packages] += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return wp_sizes_vector;
|
||||||
|
}
|
||||||
422
src/ChemistryModule/WorkerFunctions.cpp
Normal file
422
src/ChemistryModule/WorkerFunctions.cpp
Normal file
@ -0,0 +1,422 @@
|
|||||||
|
#include "IrmResult.h"
|
||||||
|
#include "poet/ChemistryModule.hpp"
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <iostream>
|
||||||
|
#include <mpi.h>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
inline std::string get_string(int root, MPI_Comm communicator) {
|
||||||
|
int count;
|
||||||
|
MPI_Bcast(&count, 1, MPI_INT, root, communicator);
|
||||||
|
|
||||||
|
char *buffer = new char[count + 1];
|
||||||
|
MPI_Bcast(buffer, count, MPI_CHAR, root, communicator);
|
||||||
|
|
||||||
|
buffer[count] = '\0';
|
||||||
|
|
||||||
|
std::string ret_str(buffer);
|
||||||
|
delete[] buffer;
|
||||||
|
|
||||||
|
return ret_str;
|
||||||
|
}
|
||||||
|
|
||||||
|
void poet::ChemistryModule::WorkerLoop() {
|
||||||
|
struct worker_s timings;
|
||||||
|
|
||||||
|
// HACK: defining the worker iteration count here, which will increment after
|
||||||
|
// each CHEM_ITER_END message
|
||||||
|
uint32_t iteration = 1;
|
||||||
|
bool loop = true;
|
||||||
|
|
||||||
|
while (loop) {
|
||||||
|
int func_type;
|
||||||
|
PropagateFunctionType(func_type);
|
||||||
|
|
||||||
|
switch (func_type) {
|
||||||
|
case CHEM_INIT: {
|
||||||
|
RunInitFile(get_string(0, this->group_comm));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CHEM_DHT_ENABLE: {
|
||||||
|
bool enable;
|
||||||
|
ChemBCast(&enable, 1, MPI_CXX_BOOL);
|
||||||
|
|
||||||
|
uint32_t size_mb;
|
||||||
|
ChemBCast(&size_mb, 1, MPI_UINT32_T);
|
||||||
|
|
||||||
|
SetDHTEnabled(enable, size_mb);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CHEM_DHT_SIGNIF_VEC: {
|
||||||
|
std::vector<uint32_t> input_vec(this->prop_count);
|
||||||
|
ChemBCast(input_vec.data(), this->prop_count, MPI_UINT32_T);
|
||||||
|
|
||||||
|
SetDHTSignifVector(input_vec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CHEM_DHT_PROP_TYPE_VEC: {
|
||||||
|
std::vector<uint32_t> input_vec(this->prop_count);
|
||||||
|
ChemBCast(input_vec.data(), this->prop_count, MPI_UINT32_T);
|
||||||
|
|
||||||
|
SetDHTPropTypeVector(input_vec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CHEM_DHT_SNAPS: {
|
||||||
|
int type;
|
||||||
|
ChemBCast(&type, 1, MPI_INT);
|
||||||
|
|
||||||
|
SetDHTSnaps(type, get_string(0, this->group_comm));
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CHEM_DHT_READ_FILE: {
|
||||||
|
ReadDHTFile(get_string(0, this->group_comm));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CHEM_WORK_LOOP: {
|
||||||
|
WorkerProcessPkgs(timings, iteration);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CHEM_PERF: {
|
||||||
|
int type;
|
||||||
|
ChemBCast(&type, 1, MPI_INT);
|
||||||
|
if (type < WORKER_DHT_HITS) {
|
||||||
|
WorkerPerfToMaster(type, timings);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
WorkerMetricsToMaster(type);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case CHEM_BREAK_MAIN_LOOP: {
|
||||||
|
WorkerPostSim(iteration);
|
||||||
|
loop = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
throw std::runtime_error("Worker received unknown tag from master.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void poet::ChemistryModule::WorkerProcessPkgs(struct worker_s &timings,
|
||||||
|
uint32_t &iteration) {
|
||||||
|
MPI_Status probe_status;
|
||||||
|
bool loop = true;
|
||||||
|
|
||||||
|
MPI_Barrier(this->group_comm);
|
||||||
|
|
||||||
|
while (loop) {
|
||||||
|
double idle_a = MPI_Wtime();
|
||||||
|
MPI_Probe(0, MPI_ANY_TAG, this->group_comm, &probe_status);
|
||||||
|
double idle_b = MPI_Wtime();
|
||||||
|
|
||||||
|
switch (probe_status.MPI_TAG) {
|
||||||
|
case LOOP_WORK: {
|
||||||
|
timings.idle_t += idle_b - idle_a;
|
||||||
|
int count;
|
||||||
|
MPI_Get_count(&probe_status, MPI_DOUBLE, &count);
|
||||||
|
|
||||||
|
WorkerDoWork(probe_status, count, timings);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case LOOP_END: {
|
||||||
|
WorkerPostIter(probe_status, iteration);
|
||||||
|
iteration++;
|
||||||
|
loop = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void poet::ChemistryModule::WorkerDoWork(MPI_Status &probe_status,
|
||||||
|
int double_count,
|
||||||
|
struct worker_s &timings) {
|
||||||
|
int local_work_package_size = 0;
|
||||||
|
|
||||||
|
static int counter = 1;
|
||||||
|
|
||||||
|
double dht_get_start, dht_get_end;
|
||||||
|
double phreeqc_time_start, phreeqc_time_end;
|
||||||
|
double dht_fill_start, dht_fill_end;
|
||||||
|
|
||||||
|
uint32_t iteration;
|
||||||
|
double dt;
|
||||||
|
double current_sim_time;
|
||||||
|
|
||||||
|
const uint32_t n_cells_times_props = this->prop_count * this->wp_size;
|
||||||
|
std::vector<double> vecCurrWP(n_cells_times_props + BUFFER_OFFSET);
|
||||||
|
int count = double_count;
|
||||||
|
|
||||||
|
/* receive */
|
||||||
|
MPI_Recv(vecCurrWP.data(), count, MPI_DOUBLE, 0, LOOP_WORK, this->group_comm,
|
||||||
|
MPI_STATUS_IGNORE);
|
||||||
|
|
||||||
|
/* decrement count of work_package by BUFFER_OFFSET */
|
||||||
|
count -= BUFFER_OFFSET;
|
||||||
|
|
||||||
|
/* check for changes on all additional variables given by the 'header' of
|
||||||
|
* mpi_buffer */
|
||||||
|
|
||||||
|
// work_package_size
|
||||||
|
local_work_package_size = vecCurrWP[count];
|
||||||
|
|
||||||
|
// current iteration of simulation
|
||||||
|
iteration = vecCurrWP[count + 1];
|
||||||
|
|
||||||
|
// current timestep size
|
||||||
|
dt = vecCurrWP[count + 2];
|
||||||
|
|
||||||
|
// current simulation time ('age' of simulation)
|
||||||
|
current_sim_time = vecCurrWP[count + 3];
|
||||||
|
|
||||||
|
/* 4th double value is currently a placeholder */
|
||||||
|
// placeholder = mpi_buffer[count+4];
|
||||||
|
|
||||||
|
// std::vector<double> vecCurrWP(
|
||||||
|
// mpi_buffer,
|
||||||
|
// mpi_buffer + (local_work_package_size * this->prop_names.size()));
|
||||||
|
vecCurrWP.resize(n_cells_times_props);
|
||||||
|
std::vector<int32_t> vecMappingWP(this->wp_size);
|
||||||
|
|
||||||
|
DHT_ResultObject DHT_Results;
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < local_work_package_size; i++) {
|
||||||
|
vecMappingWP[i] = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (local_work_package_size != this->wp_size) {
|
||||||
|
// std::vector<double> vecFiller(
|
||||||
|
// (this->wp_size - local_work_package_size) * prop_count, 0);
|
||||||
|
// vecCurrWP.insert(vecCurrWP.end(), vecFiller.begin(), vecFiller.end());
|
||||||
|
|
||||||
|
// set all remaining cells to inactive
|
||||||
|
for (int i = local_work_package_size; i < this->wp_size; i++) {
|
||||||
|
vecMappingWP[i] = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dht_enabled) {
|
||||||
|
/* check for values in DHT */
|
||||||
|
dht_get_start = MPI_Wtime();
|
||||||
|
DHT_Results = dht->checkDHT(local_work_package_size, dt, vecCurrWP);
|
||||||
|
dht_get_end = MPI_Wtime();
|
||||||
|
|
||||||
|
DHT_Results.ResultsToMapping(vecMappingWP);
|
||||||
|
}
|
||||||
|
|
||||||
|
phreeqc_time_start = MPI_Wtime();
|
||||||
|
|
||||||
|
WorkerRunWorkPackage(vecCurrWP, vecMappingWP, current_sim_time, dt);
|
||||||
|
|
||||||
|
phreeqc_time_end = MPI_Wtime();
|
||||||
|
|
||||||
|
if (dht_enabled) {
|
||||||
|
DHT_Results.ResultsToWP(vecCurrWP);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* send results to master */
|
||||||
|
MPI_Request send_req;
|
||||||
|
MPI_Isend(vecCurrWP.data(), count, MPI_DOUBLE, 0, LOOP_WORK, MPI_COMM_WORLD,
|
||||||
|
&send_req);
|
||||||
|
|
||||||
|
if (dht_enabled) {
|
||||||
|
/* write results to DHT */
|
||||||
|
dht_fill_start = MPI_Wtime();
|
||||||
|
dht->fillDHT(local_work_package_size, DHT_Results, vecCurrWP);
|
||||||
|
dht_fill_end = MPI_Wtime();
|
||||||
|
|
||||||
|
timings.dht_get += dht_get_end - dht_get_start;
|
||||||
|
timings.dht_fill += dht_fill_end - dht_fill_start;
|
||||||
|
}
|
||||||
|
|
||||||
|
timings.phreeqc_t += phreeqc_time_end - phreeqc_time_start;
|
||||||
|
|
||||||
|
MPI_Wait(&send_req, MPI_STATUS_IGNORE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void poet::ChemistryModule::WorkerPostIter(MPI_Status &prope_status,
|
||||||
|
uint32_t iteration) {
|
||||||
|
MPI_Recv(NULL, 0, MPI_DOUBLE, 0, LOOP_END, this->group_comm,
|
||||||
|
MPI_STATUS_IGNORE);
|
||||||
|
if (this->dht_enabled) {
|
||||||
|
this->dht->printStatistics();
|
||||||
|
|
||||||
|
if (this->dht_snaps_type == DHT_FILES_ITEREND) {
|
||||||
|
WorkerWriteDHTDump(iteration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void poet::ChemistryModule::WorkerPostSim(uint32_t iteration) {
|
||||||
|
/* before death, submit profiling/timings to master*/
|
||||||
|
|
||||||
|
// double timings_serialized[4];
|
||||||
|
// timings_serialized[0] = timings.phreeqc_t;
|
||||||
|
// timings_serialized[1] = timings.dht_get;
|
||||||
|
// timings_serialized[2] = timings.dht_fill;
|
||||||
|
// timings_serialized[3] = timings.idle_t;
|
||||||
|
|
||||||
|
// // timings
|
||||||
|
// MPI_Send(timings_serialized, 4, MPI_DOUBLE, 0, 0, this->group_comm);
|
||||||
|
|
||||||
|
// // MPI_Send(&phreeqc_count, 1, MPI_INT, 0, TAG_TIMING, MPI_COMM_WORLD);
|
||||||
|
// // MPI_Send(&idle_t, 1, MPI_DOUBLE, 0, TAG_TIMING, MPI_COMM_WORLD);
|
||||||
|
|
||||||
|
// if (this->dht_enabled) {
|
||||||
|
// // dht_perf
|
||||||
|
// int dht_perf[3];
|
||||||
|
// dht_perf[0] = dht->getHits();
|
||||||
|
// dht_perf[1] = dht->getMisses();
|
||||||
|
// dht_perf[2] = dht->getEvictions();
|
||||||
|
// MPI_Send(dht_perf, 3, MPI_INT, 0, 0, this->group_comm);
|
||||||
|
// }
|
||||||
|
|
||||||
|
if (this->dht_enabled && this->dht_snaps_type > DHT_FILES_SIMEND) {
|
||||||
|
WorkerWriteDHTDump(iteration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void poet::ChemistryModule::WorkerWriteDHTDump(uint32_t iteration) {
|
||||||
|
std::stringstream out;
|
||||||
|
out << this->dht_file_out_dir << "/iter_" << std::setfill('0') << std::setw(4)
|
||||||
|
<< iteration << ".dht";
|
||||||
|
int res = dht->tableToFile(out.str().c_str());
|
||||||
|
if (res != DHT_SUCCESS && this->comm_rank == 2)
|
||||||
|
std::cerr
|
||||||
|
<< "CPP: Worker: Error in writing current state of DHT to file.\n";
|
||||||
|
else if (this->comm_rank == 2)
|
||||||
|
std::cout << "CPP: Worker: Successfully written DHT to file " << out.str()
|
||||||
|
<< "\n";
|
||||||
|
}
|
||||||
|
void poet::ChemistryModule::WorkerReadDHTDump(
|
||||||
|
const std::string &dht_input_file) {
|
||||||
|
int res = dht->fileToTable((char *)dht_input_file.c_str());
|
||||||
|
if (res != DHT_SUCCESS) {
|
||||||
|
if (res == DHT_WRONG_FILE) {
|
||||||
|
if (this->comm_rank == 1)
|
||||||
|
std::cerr
|
||||||
|
<< "CPP: Worker: Wrong file layout! Continue with empty DHT ...\n";
|
||||||
|
} else {
|
||||||
|
if (this->comm_rank == 1)
|
||||||
|
std::cerr << "CPP: Worker: Error in loading current state of DHT from "
|
||||||
|
"file. Continue with empty DHT ...\n";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (this->comm_rank == 2)
|
||||||
|
std::cout << "CPP: Worker: Successfully loaded state of DHT from file "
|
||||||
|
<< dht_input_file << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IRM_RESULT
|
||||||
|
poet::ChemistryModule::WorkerRunWorkPackage(std::vector<double> &vecWP,
|
||||||
|
std::vector<int32_t> &vecMapping,
|
||||||
|
double dSimTime, double dTimestep) {
|
||||||
|
if (this->wp_size != vecMapping.size()) {
|
||||||
|
return IRM_INVALIDARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((this->wp_size * this->prop_count) != vecWP.size()) {
|
||||||
|
return IRM_INVALIDARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if we actually need to start phreeqc
|
||||||
|
bool bRunPhreeqc = false;
|
||||||
|
for (const auto &aMappingNum : vecMapping) {
|
||||||
|
if (aMappingNum != -1) {
|
||||||
|
bRunPhreeqc = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!bRunPhreeqc) {
|
||||||
|
return IRM_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<double> vecCopy;
|
||||||
|
|
||||||
|
vecCopy = vecWP;
|
||||||
|
for (uint32_t i = 0; i < this->prop_count; i++) {
|
||||||
|
for (uint32_t j = 0; j < this->wp_size; j++) {
|
||||||
|
vecWP[(i * this->wp_size) + j] = vecCopy[(j * this->prop_count) + i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IRM_RESULT result;
|
||||||
|
this->PhreeqcRM::CreateMapping(vecMapping);
|
||||||
|
this->SetInternalsFromWP(vecWP, this->wp_size);
|
||||||
|
|
||||||
|
this->PhreeqcRM::SetTime(dSimTime);
|
||||||
|
this->PhreeqcRM::SetTimeStep(dTimestep);
|
||||||
|
|
||||||
|
result = this->PhreeqcRM::RunCells();
|
||||||
|
|
||||||
|
this->GetWPFromInternals(vecWP, this->wp_size);
|
||||||
|
|
||||||
|
vecCopy = vecWP;
|
||||||
|
for (uint32_t i = 0; i < this->prop_count; i++) {
|
||||||
|
for (uint32_t j = 0; j < this->wp_size; j++) {
|
||||||
|
vecWP[(j * this->prop_count) + i] = vecCopy[(i * this->wp_size) + j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void poet::ChemistryModule::WorkerPerfToMaster(int type,
|
||||||
|
const struct worker_s &timings) {
|
||||||
|
switch (type) {
|
||||||
|
case WORKER_PHREEQC: {
|
||||||
|
MPI_Gather(&timings.phreeqc_t, 1, MPI_DOUBLE, NULL, 1, MPI_DOUBLE, 0,
|
||||||
|
this->group_comm);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WORKER_DHT_GET: {
|
||||||
|
MPI_Gather(&timings.dht_get, 1, MPI_DOUBLE, NULL, 1, MPI_DOUBLE, 0,
|
||||||
|
this->group_comm);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WORKER_DHT_FILL: {
|
||||||
|
MPI_Gather(&timings.dht_fill, 1, MPI_DOUBLE, NULL, 1, MPI_DOUBLE, 0,
|
||||||
|
this->group_comm);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WORKER_IDLE: {
|
||||||
|
MPI_Gather(&timings.idle_t, 1, MPI_DOUBLE, NULL, 1, MPI_DOUBLE, 0,
|
||||||
|
this->group_comm);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
throw std::runtime_error("Unknown perf type in master's message.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void poet::ChemistryModule::WorkerMetricsToMaster(int type) {
|
||||||
|
uint32_t value;
|
||||||
|
switch (type) {
|
||||||
|
case WORKER_DHT_HITS: {
|
||||||
|
value = dht->getHits();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WORKER_DHT_MISS: {
|
||||||
|
value = dht->getMisses();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WORKER_DHT_EVICTIONS: {
|
||||||
|
value = dht->getEvictions();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
throw std::runtime_error("Unknown perf type in master's message.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MPI_Gather(&value, 1, MPI_UINT32_T, NULL, 1, MPI_UINT32_T, 0,
|
||||||
|
this->group_comm);
|
||||||
|
}
|
||||||
@ -25,7 +25,6 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <bits/stdint-intn.h>
|
#include <bits/stdint-intn.h>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <poet/ChemSimSeq.hpp>
|
|
||||||
#include <poet/DiffusionModule.hpp>
|
#include <poet/DiffusionModule.hpp>
|
||||||
#include <poet/Grid.hpp>
|
#include <poet/Grid.hpp>
|
||||||
|
|
||||||
|
|||||||
19
src/Grid.cpp
19
src/Grid.cpp
@ -19,7 +19,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "poet/SimParams.hpp"
|
#include "poet/SimParams.hpp"
|
||||||
|
#include <RInside.h>
|
||||||
#include <Rcpp.h>
|
#include <Rcpp.h>
|
||||||
|
#include <Rcpp/internal/wrap.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
@ -253,3 +255,20 @@ auto poet::Grid::GetSpeciesByName(std::string name,
|
|||||||
return std::vector<double>(module_memory->mem.begin() + begin_vec,
|
return std::vector<double>(module_memory->mem.begin() + begin_vec,
|
||||||
module_memory->mem.begin() + end_vec);
|
module_memory->mem.begin() + end_vec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HACK: Helper function
|
||||||
|
void poet::Grid::WriteFieldsToR(RInside &R) {
|
||||||
|
|
||||||
|
for (auto const &elem : this->state_register) {
|
||||||
|
std::string field_name = elem.first;
|
||||||
|
StateMemory *field = elem.second;
|
||||||
|
|
||||||
|
const uint32_t n_cells_per_prop = field->mem.size() / field->props.size();
|
||||||
|
|
||||||
|
R["TMP"] = Rcpp::wrap(field->mem);
|
||||||
|
R["TMP_PROPS"] = Rcpp::wrap(field->props);
|
||||||
|
R.parseEval(std::string(
|
||||||
|
"mysetup$" + field_name + " <- setNames(data.frame(matrix(TMP, nrow=" +
|
||||||
|
std::to_string(n_cells_per_prop) + ")), TMP_PROPS)"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -1,336 +0,0 @@
|
|||||||
#include "poet/PhreeqcWrapper.hpp"
|
|
||||||
#include "IPhreeqc.hpp"
|
|
||||||
#include "IrmResult.h"
|
|
||||||
#include "PhreeqcRM.h"
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <cstdint>
|
|
||||||
#include <iterator>
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
poet::PhreeqcWrapper::PhreeqcWrapper(uint32_t inxyz)
|
|
||||||
: PhreeqcRM(inxyz, 1), iWPSize(inxyz) {
|
|
||||||
this->vecDefMapping.resize(inxyz);
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < inxyz; i++) {
|
|
||||||
this->vecDefMapping[i] = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void poet::PhreeqcWrapper::SetupAndLoadDB(
|
|
||||||
const poet::ChemistryParams &chemPar) {
|
|
||||||
// TODO: hardcoded options ...
|
|
||||||
this->SetErrorHandlerMode(1);
|
|
||||||
this->SetComponentH2O(false);
|
|
||||||
this->SetRebalanceFraction(0.5);
|
|
||||||
this->SetRebalanceByCell(true);
|
|
||||||
this->UseSolutionDensityVolume(false);
|
|
||||||
this->SetPartitionUZSolids(false);
|
|
||||||
|
|
||||||
// Set concentration units
|
|
||||||
// 1, mg/L; 2, mol/L; 3, kg/kgs
|
|
||||||
this->SetUnitsSolution(2);
|
|
||||||
// 0, mol/L cell; 1, mol/L water; 2 mol/L rock
|
|
||||||
this->SetUnitsPPassemblage(1);
|
|
||||||
// 0, mol/L cell; 1, mol/L water; 2 mol/L rock
|
|
||||||
this->SetUnitsExchange(1);
|
|
||||||
// 0, mol/L cell; 1, mol/L water; 2 mol/L rock
|
|
||||||
this->SetUnitsSurface(1);
|
|
||||||
// 0, mol/L cell; 1, mol/L water; 2 mol/L rock
|
|
||||||
this->SetUnitsGasPhase(1);
|
|
||||||
// 0, mol/L cell; 1, mol/L water; 2 mol/L rock
|
|
||||||
this->SetUnitsSSassemblage(1);
|
|
||||||
// 0, mol/L cell; 1, mol/L water; 2 mol/L rock
|
|
||||||
this->SetUnitsKinetics(1);
|
|
||||||
|
|
||||||
// Set representative volume
|
|
||||||
std::vector<double> rv;
|
|
||||||
rv.resize(this->iWPSize, 1.0);
|
|
||||||
this->SetRepresentativeVolume(rv);
|
|
||||||
|
|
||||||
// Set initial porosity
|
|
||||||
std::vector<double> por;
|
|
||||||
por.resize(this->iWPSize, 1);
|
|
||||||
this->SetPorosity(por);
|
|
||||||
|
|
||||||
// Set initial saturation
|
|
||||||
std::vector<double> sat;
|
|
||||||
sat.resize(this->iWPSize, 1.0);
|
|
||||||
this->SetSaturation(sat);
|
|
||||||
|
|
||||||
// Load database
|
|
||||||
this->LoadDatabase(chemPar.database_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
void poet::PhreeqcWrapper::InitFromFile(const std::string &strInputFile) {
|
|
||||||
this->RunFile(true, true, false, strInputFile);
|
|
||||||
// MDL: this is run only by the workers
|
|
||||||
this->RunString(true, false, true, "DELETE; -all; PRINT; -warnings 0;");
|
|
||||||
|
|
||||||
this->FindComponents();
|
|
||||||
|
|
||||||
std::vector<int> ic1;
|
|
||||||
ic1.resize(this->iWPSize * 7, -1);
|
|
||||||
// TODO: hardcoded reaction modules
|
|
||||||
for (int i = 0; i < nxyz; i++) {
|
|
||||||
ic1[i] = 1; // Solution 1
|
|
||||||
ic1[nxyz + i] = 1; // Equilibrium 1
|
|
||||||
ic1[2 * nxyz + i] = -1; // Exchange none
|
|
||||||
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 1
|
|
||||||
}
|
|
||||||
|
|
||||||
this->InitialPhreeqc2Module(ic1);
|
|
||||||
|
|
||||||
// Initial equilibration of cells
|
|
||||||
// double time = 0.0;
|
|
||||||
// double time_step = 0.0;
|
|
||||||
// this->SetTime(time);
|
|
||||||
// this->SetTimeStep(time_step);
|
|
||||||
// this->RunCells();
|
|
||||||
|
|
||||||
this->InitInternals();
|
|
||||||
}
|
|
||||||
|
|
||||||
void poet::PhreeqcWrapper::InitInternals() {
|
|
||||||
uint32_t sum = 0, curr_count;
|
|
||||||
std::vector<std::string> vecCurrSpecies;
|
|
||||||
|
|
||||||
this->vecSpeciesPerModule.reserve(this->MODULE_COUNT);
|
|
||||||
|
|
||||||
vecCurrSpecies = this->GetComponents();
|
|
||||||
this->vecSpeciesNames.insert(this->vecSpeciesNames.end(),
|
|
||||||
vecCurrSpecies.begin(), vecCurrSpecies.end());
|
|
||||||
this->vecSpeciesPerModule.push_back(vecCurrSpecies.size());
|
|
||||||
|
|
||||||
vecCurrSpecies = this->GetEquilibriumPhases();
|
|
||||||
this->vecSpeciesNames.insert(this->vecSpeciesNames.end(),
|
|
||||||
vecCurrSpecies.begin(), vecCurrSpecies.end());
|
|
||||||
this->vecSpeciesPerModule.push_back(vecCurrSpecies.size());
|
|
||||||
|
|
||||||
vecCurrSpecies = this->GetExchangeSpecies();
|
|
||||||
this->vecSpeciesNames.insert(this->vecSpeciesNames.end(),
|
|
||||||
vecCurrSpecies.begin(), vecCurrSpecies.end());
|
|
||||||
this->vecSpeciesPerModule.push_back(vecCurrSpecies.size());
|
|
||||||
|
|
||||||
vecCurrSpecies = this->GetSurfaceSpecies();
|
|
||||||
this->vecSpeciesNames.insert(this->vecSpeciesNames.end(),
|
|
||||||
vecCurrSpecies.begin(), vecCurrSpecies.end());
|
|
||||||
this->vecSpeciesPerModule.push_back(vecCurrSpecies.size());
|
|
||||||
|
|
||||||
vecCurrSpecies = this->GetKineticReactions();
|
|
||||||
this->vecSpeciesNames.insert(this->vecSpeciesNames.end(),
|
|
||||||
vecCurrSpecies.begin(), vecCurrSpecies.end());
|
|
||||||
this->vecSpeciesPerModule.push_back(vecCurrSpecies.size());
|
|
||||||
|
|
||||||
this->iSpeciesCount = this->vecSpeciesNames.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto poet::PhreeqcWrapper::GetSpeciesCount() -> uint32_t {
|
|
||||||
return this->iSpeciesCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto poet::PhreeqcWrapper::GetSpeciesCountByModule()
|
|
||||||
-> const std::vector<uint32_t> & {
|
|
||||||
return this->vecSpeciesPerModule;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto poet::PhreeqcWrapper::GetSpeciesNamesFull()
|
|
||||||
-> const std::vector<std::string> & {
|
|
||||||
return this->vecSpeciesNames;
|
|
||||||
}
|
|
||||||
|
|
||||||
void poet::PhreeqcWrapper::SetInternalsFromWP(const std::vector<double> &vecWP,
|
|
||||||
uint32_t iCurrWPSize) {
|
|
||||||
uint32_t iCurrElements;
|
|
||||||
|
|
||||||
auto itStart = vecWP.begin();
|
|
||||||
auto itEnd = itStart;
|
|
||||||
|
|
||||||
// this->SetMappingForWP(iCurrWPSize);
|
|
||||||
|
|
||||||
int nchem = this->GetChemistryCellCount();
|
|
||||||
|
|
||||||
iCurrElements = this->vecSpeciesPerModule[0];
|
|
||||||
|
|
||||||
itEnd += iCurrElements * this->iWPSize;
|
|
||||||
std::vector<double> out;
|
|
||||||
this->GetConcentrations(out);
|
|
||||||
this->SetConcentrations(std::vector<double>(itStart, itEnd));
|
|
||||||
itStart = itEnd;
|
|
||||||
|
|
||||||
// Equlibirum Phases
|
|
||||||
if ((iCurrElements = this->vecSpeciesPerModule[1]) != 0) {
|
|
||||||
itEnd += iCurrElements * this->iWPSize;
|
|
||||||
this->GetPPhaseMoles(out);
|
|
||||||
this->SetPPhaseMoles(std::vector<double>(itStart, itEnd));
|
|
||||||
itStart = itEnd;
|
|
||||||
}
|
|
||||||
|
|
||||||
// // NOTE: Block for 'Surface' and 'Exchange' is missing because of missing
|
|
||||||
// // setters @ PhreeqcRM
|
|
||||||
// // ...
|
|
||||||
// // BLOCK_END
|
|
||||||
|
|
||||||
if ((iCurrElements = this->vecSpeciesPerModule[4]) != 0) {
|
|
||||||
itEnd += iCurrElements * this->iWPSize;
|
|
||||||
this->GetKineticsMoles(out);
|
|
||||||
this->SetKineticsMoles(std::vector<double>(itStart, itEnd));
|
|
||||||
itStart = itEnd;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void poet::PhreeqcWrapper::GetWPFromInternals(std::vector<double> &vecWP,
|
|
||||||
uint32_t iCurrWPSize) {
|
|
||||||
std::vector<double> vecCurrOutput;
|
|
||||||
|
|
||||||
vecWP.clear();
|
|
||||||
vecWP.reserve(this->iSpeciesCount * this->iWPSize);
|
|
||||||
|
|
||||||
this->GetConcentrations(vecCurrOutput);
|
|
||||||
vecWP.insert(vecWP.end(), vecCurrOutput.begin(), vecCurrOutput.end());
|
|
||||||
|
|
||||||
if (this->vecSpeciesPerModule[1] != 0) {
|
|
||||||
this->GetPPhaseMoles(vecCurrOutput);
|
|
||||||
vecWP.insert(vecWP.end(), vecCurrOutput.begin(), vecCurrOutput.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE: Block for 'Surface' and 'Exchange' is missing because of missing
|
|
||||||
// Getters @ PhreeqcRM
|
|
||||||
// ...
|
|
||||||
// BLOCK_END
|
|
||||||
|
|
||||||
if (this->vecSpeciesPerModule[4] != 0) {
|
|
||||||
this->GetKineticsMoles(vecCurrOutput);
|
|
||||||
vecWP.insert(vecWP.end(), vecCurrOutput.begin(), vecCurrOutput.end());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto poet::PhreeqcWrapper::ReplaceTotalsByPotentials(
|
|
||||||
const std::vector<double> &vecWP, uint32_t iCurrWPSize)
|
|
||||||
-> std::vector<double> {
|
|
||||||
|
|
||||||
uint32_t iPropsPerCell = this->vecSpeciesNames.size();
|
|
||||||
|
|
||||||
int iphreeqcResult;
|
|
||||||
std::vector<double> vecOutput;
|
|
||||||
vecOutput.reserve((iPropsPerCell - 1) * iCurrWPSize);
|
|
||||||
|
|
||||||
auto itCStart = vecWP.begin();
|
|
||||||
auto itCEnd = itCStart + (this->vecSpeciesPerModule[0]);
|
|
||||||
uint32_t iDiff = iPropsPerCell - this->vecSpeciesPerModule[0];
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < iCurrWPSize; i++) {
|
|
||||||
std::vector<double> vecCIn(itCStart, itCEnd);
|
|
||||||
double pH, pe;
|
|
||||||
|
|
||||||
// FIXME: Hardcoded temperatures and pressures here!
|
|
||||||
IPhreeqc *util_ptr = this->Concentrations2Utility(
|
|
||||||
vecCIn, std::vector<double>(1, 25.0), std::vector<double>(1, 1.0));
|
|
||||||
|
|
||||||
std::string sInput = "SELECTED_OUTPUT " + std::to_string(this->DHT_SELOUT) +
|
|
||||||
"; -pH; -pe;RUN_CELLS; -cells 1; -time_step 0";
|
|
||||||
iphreeqcResult = util_ptr->RunString(sInput.c_str());
|
|
||||||
if (iphreeqcResult != 0) {
|
|
||||||
throw std::runtime_error("IPhreeqc Utility returned non-zero value: " +
|
|
||||||
std::to_string(iphreeqcResult));
|
|
||||||
}
|
|
||||||
|
|
||||||
util_ptr->SetCurrentSelectedOutputUserNumber(this->DHT_SELOUT);
|
|
||||||
|
|
||||||
int vtype;
|
|
||||||
static std::string svalue(100, '\0');
|
|
||||||
|
|
||||||
iphreeqcResult = util_ptr->GetSelectedOutputValue2(
|
|
||||||
1, 0, &vtype, &pH, svalue.data(), svalue.capacity());
|
|
||||||
if (iphreeqcResult != 0) {
|
|
||||||
throw std::runtime_error("IPhreeqc Utility returned non-zero value: " +
|
|
||||||
std::to_string(iphreeqcResult));
|
|
||||||
}
|
|
||||||
|
|
||||||
iphreeqcResult = util_ptr->GetSelectedOutputValue2(
|
|
||||||
1, 1, &vtype, &pe, svalue.data(), svalue.capacity());
|
|
||||||
if (iphreeqcResult != 0) {
|
|
||||||
throw std::runtime_error("IPhreeqc Utility returned non-zero value: " +
|
|
||||||
std::to_string(iphreeqcResult));
|
|
||||||
}
|
|
||||||
|
|
||||||
vecOutput.insert(vecOutput.end(), vecCIn.begin() + 3, vecCIn.end());
|
|
||||||
vecOutput.push_back(pH);
|
|
||||||
vecOutput.push_back(pe);
|
|
||||||
vecOutput.insert(vecOutput.end(), itCEnd, itCEnd + iDiff);
|
|
||||||
|
|
||||||
itCStart = itCEnd + iDiff;
|
|
||||||
itCEnd = itCStart + (this->vecSpeciesPerModule[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return vecOutput;
|
|
||||||
}
|
|
||||||
|
|
||||||
IRM_RESULT
|
|
||||||
poet::PhreeqcWrapper::RunWorkPackage(std::vector<double> &vecWP,
|
|
||||||
std::vector<int32_t> &vecMapping,
|
|
||||||
double dSimTime, double dTimestep) {
|
|
||||||
if (this->iWPSize != vecMapping.size()) {
|
|
||||||
return IRM_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((this->iWPSize * this->iSpeciesCount) != vecWP.size()) {
|
|
||||||
return IRM_INVALIDARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if we actually need to start phreeqc
|
|
||||||
bool bRunPhreeqc = false;
|
|
||||||
for (const auto &aMappingNum : vecMapping) {
|
|
||||||
if (aMappingNum != -1) {
|
|
||||||
bRunPhreeqc = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!bRunPhreeqc) {
|
|
||||||
return IRM_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<double> vecCopy;
|
|
||||||
|
|
||||||
vecCopy = vecWP;
|
|
||||||
for (uint32_t i = 0; i < this->iSpeciesCount; i++) {
|
|
||||||
for (uint32_t j = 0; j < this->iWPSize; j++) {
|
|
||||||
vecWP[(i * this->iWPSize) + j] = vecCopy[(j * this->iSpeciesCount) + i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
IRM_RESULT result;
|
|
||||||
this->CreateMapping(vecMapping);
|
|
||||||
this->SetInternalsFromWP(vecWP, this->iWPSize);
|
|
||||||
this->SetTime(dSimTime);
|
|
||||||
this->SetTimeStep(dTimestep);
|
|
||||||
result = this->PhreeqcRM::RunCells();
|
|
||||||
this->GetWPFromInternals(vecWP, this->iWPSize);
|
|
||||||
|
|
||||||
vecCopy = vecWP;
|
|
||||||
for (uint32_t i = 0; i < this->iSpeciesCount; i++) {
|
|
||||||
for (uint32_t j = 0; j < this->iWPSize; j++) {
|
|
||||||
vecWP[(j * this->iSpeciesCount) + i] = vecCopy[(i * this->iWPSize) + j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void poet::PhreeqcWrapper::SetMappingForWP(uint32_t iCurrWPSize) {
|
|
||||||
if (iCurrWPSize == this->iWPSize) {
|
|
||||||
this->CreateMapping(this->vecDefMapping);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<int> vecCurrMapping(this->vecDefMapping);
|
|
||||||
for (uint32_t i = iCurrWPSize; i < vecCurrMapping.size(); i++) {
|
|
||||||
vecCurrMapping[i] = -1;
|
|
||||||
}
|
|
||||||
this->CreateMapping(vecCurrMapping);
|
|
||||||
}
|
|
||||||
@ -18,6 +18,7 @@
|
|||||||
** Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
** Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "poet/DHT_Types.hpp"
|
||||||
#include <bits/stdint-uintn.h>
|
#include <bits/stdint-uintn.h>
|
||||||
#include <poet/SimParams.hpp>
|
#include <poet/SimParams.hpp>
|
||||||
|
|
||||||
@ -130,7 +131,7 @@ int SimParams::parseFromCmdl(char *argv[], RInside &R) {
|
|||||||
// cout << "CPP: DHT logarithm before rounding: " << ( dht_logarithm ? "ON"
|
// cout << "CPP: DHT logarithm before rounding: " << ( dht_logarithm ? "ON"
|
||||||
// : "OFF" ) << endl;
|
// : "OFF" ) << endl;
|
||||||
|
|
||||||
cmdl("dht-size", DHT_SIZE_PER_PROCESS) >> simparams.dht_size_per_process;
|
cmdl("dht-size", DHT_SIZE_PER_PROCESS_MB) >> simparams.dht_size_per_process;
|
||||||
// cout << "CPP: DHT size per process (Byte) = " << dht_size_per_process <<
|
// cout << "CPP: DHT size per process (Byte) = " << dht_size_per_process <<
|
||||||
// endl;
|
// endl;
|
||||||
|
|
||||||
@ -196,17 +197,30 @@ void SimParams::initVectorParams(RInside &R, int col_count) {
|
|||||||
/*Load significance vector from R setup file (or set default)*/
|
/*Load significance vector from R setup file (or set default)*/
|
||||||
bool signif_vector_exists = R.parseEval("exists('signif_vector')");
|
bool signif_vector_exists = R.parseEval("exists('signif_vector')");
|
||||||
if (signif_vector_exists) {
|
if (signif_vector_exists) {
|
||||||
dht_signif_vector = as<std::vector<int>>(R["signif_vector"]);
|
dht_signif_vector = as<std::vector<uint32_t>>(R["signif_vector"]);
|
||||||
} else {
|
|
||||||
dht_signif_vector.assign(col_count, simparams.dht_significant_digits);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*Load property type vector from R setup file (or set default)*/
|
/*Load property type vector from R setup file (or set default)*/
|
||||||
bool prop_type_vector_exists = R.parseEval("exists('prop_type')");
|
bool prop_type_vector_exists = R.parseEval("exists('prop_type')");
|
||||||
if (prop_type_vector_exists) {
|
if (prop_type_vector_exists) {
|
||||||
dht_prop_type_vector = as<std::vector<string>>(R["prop_type"]);
|
std::vector<std::string> prop_type_R =
|
||||||
} else {
|
as<std::vector<string>>(R["prop_type"]);
|
||||||
dht_prop_type_vector.assign(col_count, "act");
|
this->dht_prop_type_vector.clear();
|
||||||
|
this->dht_prop_type_vector.reserve(prop_type_R.size());
|
||||||
|
|
||||||
|
for (const auto &type : prop_type_R) {
|
||||||
|
if (type == "act") {
|
||||||
|
this->dht_prop_type_vector.push_back(DHT_TYPE_ACT);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == "ignore") {
|
||||||
|
this->dht_prop_type_vector.push_back(DHT_TYPE_IGNORE);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->dht_prop_type_vector.push_back(DHT_TYPE_DEFAULT);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (simparams.world_rank == 0) {
|
if (simparams.world_rank == 0) {
|
||||||
@ -228,21 +242,6 @@ void SimParams::initVectorParams(RInside &R, int col_count) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SimParams::setDtDiffer(bool dt_differ) { simparams.dt_differ = dt_differ; }
|
|
||||||
|
|
||||||
t_simparams SimParams::getNumParams() const { return this->simparams; }
|
|
||||||
|
|
||||||
std::vector<int> SimParams::getDHTSignifVector() const {
|
|
||||||
return this->dht_signif_vector;
|
|
||||||
}
|
|
||||||
std::vector<std::string> SimParams::getDHTPropTypeVector() const {
|
|
||||||
return this->dht_prop_type_vector;
|
|
||||||
}
|
|
||||||
std::string_view SimParams::getDHTFile() const { return this->dht_file; }
|
|
||||||
|
|
||||||
std::string_view SimParams::getFilesim() const { return this->filesim; }
|
|
||||||
std::string_view SimParams::getOutDir() const { return this->out_dir; }
|
|
||||||
|
|
||||||
std::list<std::string> SimParams::validateOptions(argh::parser cmdl) {
|
std::list<std::string> SimParams::validateOptions(argh::parser cmdl) {
|
||||||
/* store all unknown parameters here */
|
/* store all unknown parameters here */
|
||||||
std::list<std::string> retList;
|
std::list<std::string> retList;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user