feat: enable interpolation without DHT lookup

This commit is contained in:
Max Luebke 2023-08-10 14:15:26 +02:00
parent 20db291bae
commit 164406ff25
16 changed files with 393 additions and 514 deletions

View File

@ -224,21 +224,21 @@ inline double RunMasterLoop(SimParams &params, RInside &R,
R.parseEvalQ("profiling$dht_get_time <- dht_get_time"); R.parseEvalQ("profiling$dht_get_time <- dht_get_time");
R["dht_fill_time"] = Rcpp::wrap(chem.GetWorkerDHTFillTimings()); R["dht_fill_time"] = Rcpp::wrap(chem.GetWorkerDHTFillTimings());
R.parseEvalQ("profiling$dht_fill_time <- dht_fill_time"); R.parseEvalQ("profiling$dht_fill_time <- dht_fill_time");
if (params.getChemParams().use_interp) { }
R["interp_w"] = Rcpp::wrap(chem.GetWorkerInterpolationWriteTimings()); if (params.getChemParams().use_interp) {
R.parseEvalQ("profiling$interp_write <- interp_w"); R["interp_w"] = Rcpp::wrap(chem.GetWorkerInterpolationWriteTimings());
R["interp_r"] = Rcpp::wrap(chem.GetWorkerInterpolationReadTimings()); R.parseEvalQ("profiling$interp_write <- interp_w");
R.parseEvalQ("profiling$interp_read <- interp_r"); R["interp_r"] = Rcpp::wrap(chem.GetWorkerInterpolationReadTimings());
R["interp_g"] = Rcpp::wrap(chem.GetWorkerInterpolationGatherTimings()); R.parseEvalQ("profiling$interp_read <- interp_r");
R.parseEvalQ("profiling$interp_gather <- interp_g"); R["interp_g"] = Rcpp::wrap(chem.GetWorkerInterpolationGatherTimings());
R["interp_fc"] = R.parseEvalQ("profiling$interp_gather <- interp_g");
Rcpp::wrap(chem.GetWorkerInterpolationFunctionCallTimings()); R["interp_fc"] =
R.parseEvalQ("profiling$interp_function_calls <- interp_fc"); Rcpp::wrap(chem.GetWorkerInterpolationFunctionCallTimings());
R["interp_calls"] = Rcpp::wrap(chem.GetWorkerInterpolationCalls()); R.parseEvalQ("profiling$interp_function_calls <- interp_fc");
R.parseEvalQ("profiling$interp_calls <- interp_calls"); R["interp_calls"] = Rcpp::wrap(chem.GetWorkerInterpolationCalls());
R["interp_cached"] = Rcpp::wrap(chem.GetWorkerPHTCacheHits()); R.parseEvalQ("profiling$interp_calls <- interp_calls");
R.parseEvalQ("profiling$interp_cached <- interp_cached"); R["interp_cached"] = Rcpp::wrap(chem.GetWorkerPHTCacheHits());
} R.parseEvalQ("profiling$interp_cached <- interp_cached");
} }
chem.MasterLoopBreak(); chem.MasterLoopBreak();

@ -1 +1 @@
Subproject commit 89f713b273cd5340b2e8169523da04c2d7ad89c9 Subproject commit 6ed14c35322a245e3a9776ef262c0ac0eba3b301

View File

@ -1,15 +1,15 @@
// Time-stamp: "Last modified 2023-08-01 13:13:18 mluebke" // Time-stamp: "Last modified 2023-08-08 13:15:49 mluebke"
#ifndef CHEMISTRYMODULE_H_ #ifndef CHEMISTRYMODULE_H_
#define CHEMISTRYMODULE_H_ #define CHEMISTRYMODULE_H_
#include "DHT_Wrapper.hpp" #include "DHT_Wrapper.hpp"
#include "DataStructures.hpp"
#include "Field.hpp" #include "Field.hpp"
#include "Interpolation.hpp" #include "Interpolation.hpp"
#include "IrmResult.h" #include "IrmResult.h"
#include "PhreeqcRM.h" #include "PhreeqcRM.h"
#include "SimParams.hpp" #include "SimParams.hpp"
#include "DataStructures.hpp"
#include <array> #include <array>
#include <cstddef> #include <cstddef>
@ -322,9 +322,8 @@ protected:
void WorkerPerfToMaster(int type, const struct worker_s &timings); void WorkerPerfToMaster(int type, const struct worker_s &timings);
void WorkerMetricsToMaster(int type); void WorkerMetricsToMaster(int type);
IRM_RESULT WorkerRunWorkPackage(std::vector<double> &vecWP, IRM_RESULT WorkerRunWorkPackage(WorkPackage &work_package, double dSimTime,
std::vector<std::uint32_t> &vecMapping, double dTimestep);
double dSimTime, double dTimestep);
std::vector<uint32_t> CalculateWPSizesVector(uint32_t n_cells, std::vector<uint32_t> CalculateWPSizesVector(uint32_t n_cells,
uint32_t wp_size) const; uint32_t wp_size) const;

View File

@ -1,8 +0,0 @@
#ifndef DHT_TYPES_H_
#define DHT_TYPES_H_
namespace poet {
enum DHT_PROP_TYPES { DHT_TYPE_DEFAULT, DHT_TYPE_CHARGE, DHT_TYPE_TOTAL };
}
#endif // DHT_TYPES_H_

View File

@ -1,4 +1,4 @@
// Time-stamp: "Last modified 2023-08-01 13:48:34 mluebke" // Time-stamp: "Last modified 2023-08-08 18:01:12 mluebke"
/* /*
** Copyright (C) 2018-2021 Alexander Lindemann, Max Luebke (University of ** Copyright (C) 2018-2021 Alexander Lindemann, Max Luebke (University of
@ -25,7 +25,7 @@
#include "DataStructures.hpp" #include "DataStructures.hpp"
#include "LookupKey.hpp" #include "LookupKey.hpp"
#include "poet/DHT_Types.hpp" #include "enums.hpp"
#include "poet/HashFunctions.hpp" #include "poet/HashFunctions.hpp"
#include "poet/LookupKey.hpp" #include "poet/LookupKey.hpp"
#include "poet/Rounding.hpp" #include "poet/Rounding.hpp"
@ -57,12 +57,9 @@ using DHT_Location = std::pair<std::uint32_t, std::uint32_t>;
class DHT_Wrapper { class DHT_Wrapper {
public: public:
using DHT_ResultObject = struct DHTResobj { using DHT_ResultObject = struct DHTResobj {
uint32_t length;
std::vector<LookupKey> keys; std::vector<LookupKey> keys;
std::vector<std::vector<double>> results;
std::vector<double> old_values;
std::vector<bool> needPhreeqc;
std::vector<DHT_Location> locations; std::vector<DHT_Location> locations;
std::vector<bool> filledDHT;
}; };
static constexpr std::int32_t DHT_KEY_INPUT_CUSTOM = static constexpr std::int32_t DHT_KEY_INPUT_CUSTOM =
@ -119,9 +116,7 @@ public:
* @param[in,out] work_package Pointer to current work package * @param[in,out] work_package Pointer to current work package
* @param dt Current timestep of simulation * @param dt Current timestep of simulation
*/ */
auto checkDHT(int length, double dt, const std::vector<double> &work_package, auto checkDHT(WorkPackage &work_package) -> const DHT_ResultObject &;
std::vector<std::uint32_t> &curr_mapping)
-> const DHT_ResultObject &;
/** /**
* @brief Write simulated values into DHT * @brief Write simulated values into DHT
@ -139,7 +134,7 @@ public:
* outputs of the PHREEQC simulation * outputs of the PHREEQC simulation
* @param dt Current timestep of simulation * @param dt Current timestep of simulation
*/ */
void fillDHT(int length, const std::vector<double> &work_package); void fillDHT(const WorkPackage &work_package);
void resultsToWP(std::vector<double> &work_package); void resultsToWP(std::vector<double> &work_package);
@ -214,6 +209,14 @@ public:
std::uint32_t getOutputCount() const { return this->data_count; } std::uint32_t getOutputCount() const { return this->data_count; }
inline void prepareKeys(const std::vector<std::vector<double>> &input_values,
double dt) {
dht_results.keys.resize(input_values.size());
for (std::size_t i = 0; i < input_values.size(); i++) {
dht_results.keys[i] = fuzzForDHT(input_values[i], dt);
}
}
private: private:
uint32_t key_count; uint32_t key_count;
uint32_t data_count; uint32_t data_count;
@ -221,7 +224,7 @@ private:
DHT *dht_object; DHT *dht_object;
MPI_Comm communicator; MPI_Comm communicator;
LookupKey fuzzForDHT(int var_count, void *key, double dt); LookupKey fuzzForDHT(const std::vector<double> &cell, double dt);
std::vector<double> std::vector<double>
outputToInputAndRates(const std::vector<double> &old_results, outputToInputAndRates(const std::vector<double> &old_results,

View File

@ -1,13 +1,29 @@
#ifndef DATASTRUCTURES_H_ #ifndef DATASTRUCTURES_H_
#define DATASTRUCTURES_H_ #define DATASTRUCTURES_H_
#include "enums.hpp"
#include <cstddef> #include <cstddef>
#include <cstdint>
#include <string> #include <string>
#include <utility> #include <utility>
#include <vector> #include <vector>
namespace poet { namespace poet {
struct WorkPackage {
std::size_t size;
std::vector<std::vector<double>> input;
std::vector<std::vector<double>> output;
std::vector<std::uint8_t> mapping;
WorkPackage(size_t _size) : size(_size) {
input.resize(size);
output.resize(size);
mapping.resize(size, CHEM_PQC);
}
};
template <typename value_type> class NamedVector { template <typename value_type> class NamedVector {
public: public:
void insert(std::pair<std::string, value_type> to_insert) { void insert(std::pair<std::string, value_type> to_insert) {

View File

@ -1,4 +1,4 @@
// Time-stamp: "Last modified 2023-08-01 18:10:48 mluebke" // Time-stamp: "Last modified 2023-08-09 12:52:37 mluebke"
#ifndef INTERPOLATION_H_ #ifndef INTERPOLATION_H_
#define INTERPOLATION_H_ #define INTERPOLATION_H_
@ -65,10 +65,9 @@ public:
void writeLocationToPHT(LookupKey key, DHT_Location location); void writeLocationToPHT(LookupKey key, DHT_Location location);
const PHT_Result &query(const LookupKey &key, const PHT_Result &query(const LookupKey &key,
const std::vector<std::uint32_t> &signif, const std::uint32_t min_entries_needed,
std::uint32_t min_entries_needed, const std::uint32_t input_count,
std::uint32_t input_count, const std::uint32_t output_count);
std::uint32_t output_count);
std::uint64_t getLocations(const LookupKey &key); std::uint64_t getLocations(const LookupKey &key);
@ -185,10 +184,9 @@ public:
auto getMinEntriesNeeded() { return this->min_entries_needed; } auto getMinEntriesNeeded() { return this->min_entries_needed; }
void writePairs(const DHT_Wrapper::DHT_ResultObject &in); void writePairs();
void tryInterpolation(DHT_Wrapper::DHT_ResultObject &dht_results, void tryInterpolation(WorkPackage &work_package);
std::vector<std::uint32_t> &curr_mapping);
void resultsToWP(std::vector<double> &work_package) const; void resultsToWP(std::vector<double> &work_package) const;

10
include/poet/enums.hpp Normal file
View File

@ -0,0 +1,10 @@
#ifndef ENUMS_H_
#define ENUMS_H_
namespace poet {
enum DHT_PROP_TYPES { DHT_TYPE_DEFAULT, DHT_TYPE_CHARGE, DHT_TYPE_TOTAL };
enum CHEMISTRY_OUT_SOURCE { CHEM_PQC, CHEM_DHT, CHEM_INTERP };
} // namespace poet
#endif // ENUMS_H_

View File

@ -293,16 +293,23 @@ void poet::ChemistryModule::initializeField(const Field &trans_field) {
this->n_cells = trans_field.GetRequestedVecSize(); this->n_cells = trans_field.GetRequestedVecSize();
chem_field = Field(n_cells); chem_field = Field(n_cells);
std::vector<double> phreeqc_init; std::vector<std::vector<double>> phreeqc_dump(this->nxyz);
this->getDumpedField(phreeqc_init); this->getDumpedField(phreeqc_dump);
if (is_sequential) { if (is_sequential) {
std::vector<double> init_vec{phreeqc_init}; std::vector<double> init_vec;
this->unshuffleField(phreeqc_init, n_cells, prop_count, 1, init_vec); for (std::size_t i = 0; i < n_cells; i++) {
init_vec.insert(init_vec.end(), phreeqc_dump[i].begin(),
phreeqc_dump[i].end());
}
const auto tmp_buffer{init_vec};
this->unshuffleField(tmp_buffer, n_cells, prop_count, 1, init_vec);
chem_field.InitFromVec(init_vec, prop_names); chem_field.InitFromVec(init_vec, prop_names);
return; return;
} }
std::vector<double> &phreeqc_init = phreeqc_dump[0];
std::vector<std::vector<double>> initial_values; std::vector<std::vector<double>> initial_values;
for (const auto &vec : trans_field.As2DVector()) { for (const auto &vec : trans_field.As2DVector()) {

View File

@ -90,8 +90,8 @@ std::vector<uint32_t> poet::ChemistryModule::GetWorkerDHTEvictions() const {
MPI_Get_count(&probe, MPI_UINT32_T, &count); MPI_Get_count(&probe, MPI_UINT32_T, &count);
std::vector<uint32_t> ret(count); std::vector<uint32_t> ret(count);
MPI_Recv(ret.data(), count, MPI_UINT32_T, probe.MPI_SOURCE, WORKER_DHT_EVICTIONS, MPI_Recv(ret.data(), count, MPI_UINT32_T, probe.MPI_SOURCE,
this->group_comm, NULL); WORKER_DHT_EVICTIONS, this->group_comm, NULL);
return ret; return ret;
} }
@ -322,9 +322,24 @@ void poet::ChemistryModule::RunCells() {
void poet::ChemistryModule::MasterRunSequential() { void poet::ChemistryModule::MasterRunSequential() {
std::vector<double> shuffled_field = std::vector<double> shuffled_field =
shuffleField(chem_field.AsVector(), n_cells, prop_count, 1); shuffleField(chem_field.AsVector(), n_cells, prop_count, 1);
this->setDumpedField(shuffled_field);
std::vector<std::vector<double>> input;
for (std::size_t i = 0; i < n_cells; i++) {
input.push_back(
std::vector<double>(shuffled_field.begin() + (i * prop_count),
shuffled_field.begin() + ((i + 1) * prop_count)));
}
this->setDumpedField(input);
PhreeqcRM::RunCells(); PhreeqcRM::RunCells();
this->getDumpedField(shuffled_field); this->getDumpedField(input);
shuffled_field.clear();
for (std::size_t i = 0; i < n_cells; i++) {
shuffled_field.insert(shuffled_field.end(), input[i].begin(),
input[i].end());
}
std::vector<double> out_vec{shuffled_field}; std::vector<double> out_vec{shuffled_field};
unshuffleField(shuffled_field, n_cells, prop_count, 1, out_vec); unshuffleField(shuffled_field, n_cells, prop_count, 1, out_vec);
chem_field.SetFromVector(out_vec); chem_field.SetFromVector(out_vec);

View File

@ -1,4 +1,4 @@
/// Time-stamp: "Last modified 2023-06-28 15:58:19 mluebke" /// Time-stamp: "Last modified 2023-08-10 11:50:46 mluebke"
/* /*
** Copyright (C) 2017-2021 Max Luebke (University of Potsdam) ** Copyright (C) 2017-2021 Max Luebke (University of Potsdam)
** **
@ -35,8 +35,8 @@ static void determine_dest(uint64_t hash, int comm_size,
/** how many bytes do we need for one index? */ /** how many bytes do we need for one index? */
int index_size = sizeof(double) - (index_count - 1); int index_size = sizeof(double) - (index_count - 1);
for (int i = 0; i < index_count; i++) { for (int i = 0; i < index_count; i++) {
tmp_index = 0; tmp_index = (hash >> (i * 8)) & ((1ULL << (index_size * 8)) - 1);
memcpy(&tmp_index, (char *)&hash + i, index_size); /* memcpy(&tmp_index, (char *)&hash + i, index_size); */
index[i] = (uint64_t)(tmp_index % table_size); index[i] = (uint64_t)(tmp_index % table_size);
} }
*dest_rank = (unsigned int)(hash % comm_size); *dest_rank = (unsigned int)(hash % comm_size);

View File

@ -1,4 +1,4 @@
// Time-stamp: "Last modified 2023-08-01 13:41:57 mluebke" // Time-stamp: "Last modified 2023-08-09 14:05:01 mluebke"
/* /*
** Copyright (C) 2018-2021 Alexander Lindemann, Max Luebke (University of ** Copyright (C) 2018-2021 Alexander Lindemann, Max Luebke (University of
@ -21,11 +21,11 @@
*/ */
#include "poet/DHT_Wrapper.hpp" #include "poet/DHT_Wrapper.hpp"
#include "poet/DHT_Types.hpp"
#include "poet/HashFunctions.hpp" #include "poet/HashFunctions.hpp"
#include "poet/Interpolation.hpp" #include "poet/Interpolation.hpp"
#include "poet/LookupKey.hpp" #include "poet/LookupKey.hpp"
#include "poet/Rounding.hpp" #include "poet/Rounding.hpp"
#include "poet/enums.hpp"
#include <algorithm> #include <algorithm>
#include <cmath> #include <cmath>
@ -83,97 +83,68 @@ DHT_Wrapper::~DHT_Wrapper() {
// free DHT // free DHT
DHT_free(dht_object, NULL, NULL); DHT_free(dht_object, NULL, NULL);
} }
auto DHT_Wrapper::checkDHT(int length, double dt, auto DHT_Wrapper::checkDHT(WorkPackage &work_package)
const std::vector<double> &work_package,
std::vector<std::uint32_t> &curr_mapping)
-> const DHT_ResultObject & { -> const DHT_ResultObject & {
dht_results.length = length; const auto length = work_package.size;
dht_results.keys.resize(length);
dht_results.results.resize(length);
dht_results.needPhreeqc.resize(length);
std::vector<double> bucket_writer(this->data_count + std::vector<double> bucket_writer(this->data_count +
input_key_elements.size()); input_key_elements.size());
std::vector<std::uint32_t> new_mapping;
// loop over every grid cell contained in work package // loop over every grid cell contained in work package
for (int i = 0; i < length; i++) { for (int i = 0; i < length; i++) {
// point to current grid cell // point to current grid cell
void *key = (void *)&(work_package[i * this->data_count]);
auto &data = dht_results.results[i];
auto &key_vector = dht_results.keys[i]; auto &key_vector = dht_results.keys[i];
// data.resize(this->data_count);
key_vector = fuzzForDHT(this->key_count, key, dt);
// overwrite input with data from DHT, IF value is found in DHT // overwrite input with data from DHT, IF value is found in DHT
int res = int res =
DHT_read(this->dht_object, key_vector.data(), bucket_writer.data()); DHT_read(this->dht_object, key_vector.data(), bucket_writer.data());
switch (res) { switch (res) {
case DHT_SUCCESS: case DHT_SUCCESS:
dht_results.results[i] = inputAndRatesToOutput(bucket_writer); work_package.output[i] = inputAndRatesToOutput(bucket_writer);
dht_results.needPhreeqc[i] = false; work_package.mapping[i] = CHEM_DHT;
this->dht_hits++; this->dht_hits++;
break; break;
case DHT_READ_MISS: case DHT_READ_MISS:
dht_results.needPhreeqc[i] = true;
new_mapping.push_back(curr_mapping[i]);
dht_results.results[i] = std::vector<double>{
&work_package[i * this->data_count],
&work_package[i * this->data_count] + this->data_count};
// HACK: apply normalization to total H and O in results field of DHT
// dht_results.results[i][0] -= base_totals[0];
// dht_results.results[i][1] -= base_totals[1];
break; break;
} }
} }
curr_mapping = std::move(new_mapping);
dht_results.old_values = work_package;
return dht_results; return dht_results;
} }
void DHT_Wrapper::fillDHT(int length, const std::vector<double> &work_package) { void DHT_Wrapper::fillDHT(const WorkPackage &work_package) {
const auto length = work_package.size;
// loop over every grid cell contained in work package // loop over every grid cell contained in work package
dht_results.locations.resize(length); dht_results.locations.resize(length);
dht_results.filledDHT = std::vector<bool>(length, false);
for (int i = 0; i < length; i++) { for (int i = 0; i < length; i++) {
// If true grid cell was simulated, needs to be inserted into dht // If true grid cell was simulated, needs to be inserted into dht
if (dht_results.needPhreeqc[i]) { if (work_package.mapping[i] == CHEM_PQC) {
// check if calcite or dolomite is absent and present, resp.n and vice // check if calcite or dolomite is absent and present, resp.n and vice
// versa in input/output. If this is the case -> Do not write to DHT! // versa in input/output. If this is the case -> Do not write to DHT!
// HACK: hardcoded, should be fixed! // HACK: hardcoded, should be fixed!
if ((dht_results.old_values[i * this->data_count + 7] == 0) != if ((work_package.input[i][7] == 0) != (work_package.output[i][7] == 0)) {
(work_package[i * this->data_count + 7] == 0)) {
dht_results.needPhreeqc[i] = false;
continue; continue;
} }
if ((dht_results.old_values[i * this->data_count + 9] == 0) != if ((work_package.input[i][9] == 0) != (work_package.output[i][9] == 0)) {
(work_package[i * this->data_count + 9] == 0)) {
dht_results.needPhreeqc[i] = false;
continue; continue;
} }
uint32_t proc, index; uint32_t proc, index;
const auto &key = dht_results.keys[i]; auto &key = dht_results.keys[i];
const auto curr_old_data = std::vector<double>( const auto data =
dht_results.old_values.begin() + (i * this->data_count), outputToInputAndRates(work_package.input[i], work_package.output[i]);
dht_results.old_values.begin() + ((i + 1) * this->data_count));
const auto curr_new_data = std::vector<double>(
work_package.begin() + (i * this->data_count),
work_package.begin() + ((i + 1) * this->data_count));
const auto data = outputToInputAndRates(curr_old_data, curr_new_data);
// void *data = (void *)&(work_package[i * this->data_count]); // void *data = (void *)&(work_package[i * this->data_count]);
// fuzz data (round, logarithm etc.) // fuzz data (round, logarithm etc.)
// insert simulated data with fuzzed key into DHT // insert simulated data with fuzzed key into DHT
int res = DHT_write(this->dht_object, (void *)(key.data()), int res = DHT_write(this->dht_object, key.data(),
const_cast<double *>(data.data()), &proc, &index); const_cast<double *>(data.data()), &proc, &index);
dht_results.locations[i] = {proc, index}; dht_results.locations[i] = {proc, index};
@ -182,6 +153,8 @@ void DHT_Wrapper::fillDHT(int length, const std::vector<double> &work_package) {
if ((res != DHT_SUCCESS) && (res == DHT_WRITE_SUCCESS_WITH_EVICTION)) { if ((res != DHT_SUCCESS) && (res == DHT_WRITE_SUCCESS_WITH_EVICTION)) {
dht_evictions++; dht_evictions++;
} }
dht_results.filledDHT[i] = true;
} }
} }
} }
@ -218,14 +191,14 @@ DHT_Wrapper::inputAndRatesToOutput(const std::vector<double> &dht_data) {
return output; return output;
} }
void DHT_Wrapper::resultsToWP(std::vector<double> &work_package) { // void DHT_Wrapper::resultsToWP(std::vector<double> &work_package) {
for (int i = 0; i < dht_results.length; i++) { // for (int i = 0; i < dht_results.length; i++) {
if (!dht_results.needPhreeqc[i]) { // if (!dht_results.needPhreeqc[i]) {
std::copy(dht_results.results[i].begin(), dht_results.results[i].end(), // std::copy(dht_results.results[i].begin(), dht_results.results[i].end(),
work_package.begin() + (data_count * i)); // work_package.begin() + (data_count * i));
} // }
} // }
} // }
int DHT_Wrapper::tableToFile(const char *filename) { int DHT_Wrapper::tableToFile(const char *filename) {
int res = DHT_to_file(dht_object, filename); int res = DHT_to_file(dht_object, filename);
@ -255,11 +228,10 @@ void DHT_Wrapper::printStatistics() {
} }
} }
LookupKey DHT_Wrapper::fuzzForDHT(int var_count, void *key, double dt) { LookupKey DHT_Wrapper::fuzzForDHT(const std::vector<double> &cell, double dt) {
const auto c_zero_val = std::pow(10, AQUEOUS_EXP); const auto c_zero_val = std::pow(10, AQUEOUS_EXP);
const Lookup_Keyelement dummy = {.0}; LookupKey vecFuzz(this->key_count + 1, {.0});
LookupKey vecFuzz(var_count + 1, dummy);
DHT_Rounder rounder; DHT_Rounder rounder;
int totals_i = 0; int totals_i = 0;
@ -269,7 +241,7 @@ LookupKey DHT_Wrapper::fuzzForDHT(int var_count, void *key, double dt) {
if (input_key_elements[i] == DHT_KEY_INPUT_CUSTOM) { if (input_key_elements[i] == DHT_KEY_INPUT_CUSTOM) {
continue; continue;
} }
double curr_key = ((double *)key)[input_key_elements[i]]; double curr_key = cell[input_key_elements[i]];
if (curr_key != 0) { if (curr_key != 0) {
if (curr_key < c_zero_val && if (curr_key < c_zero_val &&
this->dht_prop_type_vector[i] == DHT_TYPE_DEFAULT) { this->dht_prop_type_vector[i] == DHT_TYPE_DEFAULT) {
@ -284,7 +256,7 @@ LookupKey DHT_Wrapper::fuzzForDHT(int var_count, void *key, double dt) {
} }
} }
// add timestep to the end of the key as double value // add timestep to the end of the key as double value
vecFuzz[var_count].fp_element = dt; vecFuzz[this->key_count].fp_element = dt;
return vecFuzz; return vecFuzz;
} }

View File

@ -1,4 +1,4 @@
// Time-stamp: "Last modified 2023-08-01 23:18:45 mluebke" // Time-stamp: "Last modified 2023-08-09 13:41:53 mluebke"
#include "poet/DHT_Wrapper.hpp" #include "poet/DHT_Wrapper.hpp"
#include "poet/HashFunctions.hpp" #include "poet/HashFunctions.hpp"
@ -48,31 +48,32 @@ void InterpolationModule::initPHT(std::uint32_t key_count,
key_size, data_size, entries_per_bucket, size_per_process, communicator); key_size, data_size, entries_per_bucket, size_per_process, communicator);
} }
void InterpolationModule::writePairs(const DHT_Wrapper::DHT_ResultObject &in) { void InterpolationModule::writePairs() {
for (int i = 0; i < in.length; i++) { const auto in = this->dht_instance.getDHTResults();
if (in.needPhreeqc[i]) { for (int i = 0; i < in.filledDHT.size(); i++) {
if (in.filledDHT[i]) {
const auto coarse_key = roundKey(in.keys[i]); const auto coarse_key = roundKey(in.keys[i]);
pht->writeLocationToPHT(coarse_key, in.locations[i]); pht->writeLocationToPHT(coarse_key, in.locations[i]);
} }
} }
} }
void InterpolationModule::tryInterpolation( void InterpolationModule::tryInterpolation(WorkPackage &work_package) {
DHT_Wrapper::DHT_ResultObject &dht_results, interp_result.status.resize(work_package.size, NOT_NEEDED);
std::vector<std::uint32_t> &curr_mapping) {
interp_result.status.resize(dht_results.length, NOT_NEEDED);
interp_result.results.resize(dht_results.length, {});
for (int i = 0; i < dht_results.length; i++) { const auto dht_results = this->dht_instance.getDHTResults();
if (!dht_results.needPhreeqc[i]) {
for (int i = 0; i < work_package.size; i++) {
if (work_package.mapping[i] != CHEM_PQC) {
interp_result.status[i] = NOT_NEEDED; interp_result.status[i] = NOT_NEEDED;
continue; continue;
} }
const auto rounded_key = roundKey(dht_results.keys[i]);
auto pht_result = auto pht_result =
pht->query(roundKey(dht_results.keys[i]), this->key_signifs.getValues(), pht->query(rounded_key, this->min_entries_needed,
this->min_entries_needed, dht_instance.getInputCount(), dht_instance.getInputCount(), dht_instance.getOutputCount());
dht_instance.getOutputCount());
int pht_i = 0; int pht_i = 0;
@ -85,9 +86,9 @@ void InterpolationModule::tryInterpolation(
auto out_it = pht_result.out_values.begin() + pht_i; auto out_it = pht_result.out_values.begin() + pht_i;
bool same_sig_calcite = (pht_result.in_values[pht_i][7] == 0) == bool same_sig_calcite = (pht_result.in_values[pht_i][7] == 0) ==
(dht_results.results[i][7] == 0); (work_package.input[i][7] == 0);
bool same_sig_dolomite = (pht_result.in_values[pht_i][8] == 0) == bool same_sig_dolomite = (pht_result.in_values[pht_i][8] == 0) ==
(dht_results.results[i][9] == 0); (work_package.input[i][9] == 0);
if (!same_sig_calcite || !same_sig_dolomite) { if (!same_sig_calcite || !same_sig_dolomite) {
pht_result.size -= 1; pht_result.size -= 1;
pht_result.in_values.erase(in_it); pht_result.in_values.erase(in_it);
@ -104,7 +105,7 @@ void InterpolationModule::tryInterpolation(
} }
#ifdef POET_PHT_ADD #ifdef POET_PHT_ADD
this->pht->incrementReadCounter(roundKey(dht_results.keys[i])); this->pht->incrementReadCounter(roundKey(roundedKey));
#endif #endif
double start_fc = MPI_Wtime(); double start_fc = MPI_Wtime();
@ -115,11 +116,11 @@ void InterpolationModule::tryInterpolation(
// } // }
// mean_water /= pht_result.size; // mean_water /= pht_result.size;
interp_result.results[i] = work_package.output[i] =
f_interpolate(dht_instance.getKeyElements(), dht_results.results[i], f_interpolate(dht_instance.getKeyElements(), work_package.input[i],
pht_result.in_values, pht_result.out_values); pht_result.in_values, pht_result.out_values);
if (interp_result.results[i][7] < 0 || interp_result.results[i][9] < 0) { if (work_package.output[i][7] < 0 || work_package.output[i][9] < 0) {
interp_result.status[i] = INSUFFICIENT_DATA; interp_result.status[i] = INSUFFICIENT_DATA;
continue; continue;
} }
@ -129,10 +130,7 @@ void InterpolationModule::tryInterpolation(
this->interpolations++; this->interpolations++;
curr_mapping.erase(std::remove(curr_mapping.begin(), curr_mapping.end(), i), work_package.mapping[i] = CHEM_INTERP;
curr_mapping.end());
dht_results.needPhreeqc[i] = false;
interp_result.status[i] = RES_OK; interp_result.status[i] = RES_OK;
} }
} }

View File

@ -1,4 +1,4 @@
// Time-stamp: "Last modified 2023-08-01 17:11:42 mluebke" // Time-stamp: "Last modified 2023-08-09 13:32:11 mluebke"
#include "poet/DHT_Wrapper.hpp" #include "poet/DHT_Wrapper.hpp"
#include "poet/HashFunctions.hpp" #include "poet/HashFunctions.hpp"
@ -106,9 +106,8 @@ void ProximityHashTable::writeLocationToPHT(LookupKey key,
} }
const ProximityHashTable::PHT_Result &ProximityHashTable::query( const ProximityHashTable::PHT_Result &ProximityHashTable::query(
const LookupKey &key, const std::vector<std::uint32_t> &signif, const LookupKey &key, const std::uint32_t min_entries_needed,
std::uint32_t min_entries_needed, std::uint32_t input_count, const std::uint32_t input_count, const std::uint32_t output_count) {
std::uint32_t output_count) {
double start_r = MPI_Wtime(); double start_r = MPI_Wtime();
const auto cache_ret = localCache[key]; const auto cache_ret = localCache[key];
@ -158,27 +157,6 @@ const ProximityHashTable::PHT_Result &ProximityHashTable::query(
buffer += input_count; buffer += input_count;
lookup_results.out_values.push_back( lookup_results.out_values.push_back(
std::vector<double>(buffer, buffer + output_count)); std::vector<double>(buffer, buffer + output_count));
// if (!similarityCheck(check_key, key, signif)) {
// // TODO: original stored location in PHT was overwritten in DHT.
// Need to
// // handle this!
// lookup_results.size--;
// if (lookup_results.size < min_entries_needed) {
// lookup_results.size = 0;
// break;
// }
// continue;
// }
// auto input = convertKeysFromDHT(buffer_start, dht_key_count);
// // remove timestep from the key
// input.pop_back();
// lookup_results.in_keys.push_back(input);
// auto *data = reinterpret_cast<double *>(buffer + dht_key_count);
// lookup_results.out_values.push_back(
// std::vector<double>(data, data + dht_data_count));
} }
if (lookup_results.size != 0) { if (lookup_results.size != 0) {

View File

@ -1,10 +1,10 @@
// Time-stamp: "Last modified 2023-08-01 17:22:20 mluebke" // Time-stamp: "Last modified 2023-08-10 12:14:24 mluebke"
#include "IrmResult.h"
#include "poet/ChemistryModule.hpp" #include "poet/ChemistryModule.hpp"
#include "poet/DHT_Wrapper.hpp" #include "poet/DHT_Wrapper.hpp"
#include "poet/Interpolation.hpp" #include "poet/Interpolation.hpp"
#include <IrmResult.h>
#include <algorithm> #include <algorithm>
#include <cassert> #include <cassert>
#include <cmath> #include <cmath>
@ -19,146 +19,6 @@
#include <vector> #include <vector>
namespace poet { namespace poet {
//std::vector<double>
//inverseDistanceWeighting(const std::vector<std::int32_t> &to_calc,
// const std::vector<double> &from,
// const std::vector<std::vector<double>> &input,
// const std::vector<std::vector<double>> &output) {
// std::vector<double> results = from;
//
// const std::uint32_t buffer_size = input.size() + 1;
// double buffer[buffer_size];
// double from_rescaled;
//
// const std::uint32_t data_set_n = input.size();
// double rescaled[to_calc.size()][data_set_n + 1];
// double weights[data_set_n];
//
// // rescaling over all key elements
// for (int key_comp_i = 0; key_comp_i < to_calc.size(); key_comp_i++) {
// const auto output_comp_i = to_calc[key_comp_i];
//
// // rescale input between 0 and 1
// for (int point_i = 0; point_i < data_set_n; point_i++) {
// rescaled[key_comp_i][point_i] = input[point_i][key_comp_i];
// }
//
// rescaled[key_comp_i][data_set_n] = from[output_comp_i];
//
// const double min = *std::min_element(rescaled[key_comp_i],
// rescaled[key_comp_i] + data_set_n + 1);
// const double max = *std::max_element(rescaled[key_comp_i],
// rescaled[key_comp_i] + data_set_n + 1);
//
// for (int point_i = 0; point_i < data_set_n; point_i++) {
// rescaled[key_comp_i][point_i] =
// ((max - min) != 0
// ? (rescaled[key_comp_i][point_i] - min) / (max - min)
// : 0);
// }
// rescaled[key_comp_i][data_set_n] =
// ((max - min) != 0 ? (from[output_comp_i] - min) / (max - min) : 0);
// }
//
// // calculate distances for each data set
// double inv_sum = 0;
// for (int point_i = 0; point_i < data_set_n; point_i++) {
// double distance = 0;
// for (int key_comp_i = 0; key_comp_i < to_calc.size(); key_comp_i++) {
// distance += std::pow(
// rescaled[key_comp_i][point_i] - rescaled[key_comp_i][data_set_n], 2);
// }
// weights[point_i] = 1 / std::sqrt(distance);
// assert(!std::isnan(weights[point_i]));
// inv_sum += weights[point_i];
// }
//
// assert(!std::isnan(inv_sum));
//
// // actual interpolation
// // bool has_h = false;
// // bool has_o = false;
//
// for (int key_comp_i = 0; key_comp_i < to_calc.size(); key_comp_i++) {
// const auto output_comp_i = to_calc[key_comp_i];
// double key_delta = 0;
//
// // if (interp_i == 0) {
// // has_h = true;
// // }
//
// // if (interp_i == 1) {
// // has_o = true;
// // }
//
// for (int j = 0; j < data_set_n; j++) {
// key_delta += weights[j] * input[j][key_comp_i];
// }
//
// key_delta /= inv_sum;
//
// results[output_comp_i] = from[output_comp_i] + key_delta;
// }
//
// // if (!has_h) {
// // double new_val = 0;
// // for (int j = 0; j < data_set_n; j++) {
// // new_val += weights[j] * output[j][0];
// // }
// // results[0] = new_val / inv_sum;
// // }
//
// // if (!has_h) {
// // double new_val = 0;
// // for (int j = 0; j < data_set_n; j++) {
// // new_val += weights[j] * output[j][1];
// // }
// // results[1] = new_val / inv_sum;
// // }
//
// // for (std::uint32_t i = 0; i < to_calc.size(); i++) {
// // const std::uint32_t interp_i = to_calc[i];
//
// // // rescale input between 0 and 1
// // for (int j = 0; j < input.size(); j++) {
// // buffer[j] = input[j].at(i);
// // }
//
// // buffer[buffer_size - 1] = from[interp_i];
//
// // const double min = *std::min_element(buffer, buffer + buffer_size);
// // const double max = *std::max_element(buffer, buffer + buffer_size);
//
// // for (int j = 0; j < input.size(); j++) {
// // buffer[j] = ((max - min) != 0 ? (buffer[j] - min) / (max - min) : 1);
// // }
// // from_rescaled =
// // ((max - min) != 0 ? (from[interp_i] - min) / (max - min) : 0);
//
// // double inv_sum = 0;
//
// // // calculate distances for each point
// // for (int i = 0; i < input.size(); i++) {
// // const double distance = std::pow(buffer[i] - from_rescaled, 2);
//
// // buffer[i] = distance > 0 ? (1 / std::sqrt(distance)) : 0;
// // inv_sum += buffer[i];
// // }
// // // calculate new values
// // double new_val = 0;
// // for (int i = 0; i < output.size(); i++) {
// // new_val += buffer[i] * output[i][interp_i];
// // }
// // results[interp_i] = new_val / inv_sum;
// // if (std::isnan(results[interp_i])) {
// // std::cout << "nan with new_val = " << output[0][i] << std::endl;
// // }
// // }
//
// return results;
//}
inline std::string get_string(int root, MPI_Comm communicator) { inline std::string get_string(int root, MPI_Comm communicator) {
int count; int count;
MPI_Bcast(&count, 1, MPI_INT, root, communicator); MPI_Bcast(&count, 1, MPI_INT, root, communicator);
@ -256,8 +116,6 @@ void poet::ChemistryModule::WorkerProcessPkgs(struct worker_s &timings,
void poet::ChemistryModule::WorkerDoWork(MPI_Status &probe_status, void poet::ChemistryModule::WorkerDoWork(MPI_Status &probe_status,
int double_count, int double_count,
struct worker_s &timings) { struct worker_s &timings) {
int local_work_package_size = 0;
static int counter = 1; static int counter = 1;
double dht_get_start, dht_get_end; double dht_get_start, dht_get_end;
@ -268,12 +126,11 @@ void poet::ChemistryModule::WorkerDoWork(MPI_Status &probe_status,
double dt; double dt;
double current_sim_time; 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; int count = double_count;
std::vector<double> mpi_buffer(count);
/* receive */ /* receive */
MPI_Recv(vecCurrWP.data(), count, MPI_DOUBLE, 0, LOOP_WORK, this->group_comm, MPI_Recv(mpi_buffer.data(), count, MPI_DOUBLE, 0, LOOP_WORK, this->group_comm,
MPI_STATUS_IGNORE); MPI_STATUS_IGNORE);
/* decrement count of work_package by BUFFER_OFFSET */ /* decrement count of work_package by BUFFER_OFFSET */
@ -283,72 +140,70 @@ void poet::ChemistryModule::WorkerDoWork(MPI_Status &probe_status,
* mpi_buffer */ * mpi_buffer */
// work_package_size // work_package_size
local_work_package_size = vecCurrWP[count]; poet::WorkPackage s_curr_wp(mpi_buffer[count]);
// current iteration of simulation // current iteration of simulation
iteration = vecCurrWP[count + 1]; iteration = mpi_buffer[count + 1];
// current timestep size // current timestep size
dt = vecCurrWP[count + 2]; dt = mpi_buffer[count + 2];
// current simulation time ('age' of simulation) // current simulation time ('age' of simulation)
current_sim_time = vecCurrWP[count + 3]; current_sim_time = mpi_buffer[count + 3];
/* 4th double value is currently a placeholder */ /* 4th double value is currently a placeholder */
// placeholder = mpi_buffer[count+4]; // placeholder = mpi_buffer[count+4];
vecCurrWP.resize(n_cells_times_props); for (std::size_t wp_i = 0; wp_i < s_curr_wp.size; wp_i++) {
std::vector<std::uint32_t> vecMappingWP(local_work_package_size); s_curr_wp.input[wp_i] =
std::vector<double>(mpi_buffer.begin() + this->prop_count * wp_i,
mpi_buffer.begin() + this->prop_count * (wp_i + 1));
}
{ // std::cout << this->comm_rank << ":" << counter++ << std::endl;
std::uint32_t i = 0; if (dht_enabled || interp_enabled) {
std::generate(vecMappingWP.begin(), vecMappingWP.end(), dht->prepareKeys(s_curr_wp.input, dt);
[&] { return i++; });
} }
if (dht_enabled) { if (dht_enabled) {
/* check for values in DHT */ /* check for values in DHT */
dht_get_start = MPI_Wtime(); dht_get_start = MPI_Wtime();
dht->checkDHT(local_work_package_size, dt, vecCurrWP, vecMappingWP); dht->checkDHT(s_curr_wp);
dht_get_end = MPI_Wtime(); dht_get_end = MPI_Wtime();
timings.dht_get += dht_get_end - dht_get_start;
}
if (interp_enabled) { if (interp_enabled) {
interp->tryInterpolation(dht->getDHTResults(), vecMappingWP); interp->tryInterpolation(s_curr_wp);
}
} }
phreeqc_time_start = MPI_Wtime(); phreeqc_time_start = MPI_Wtime();
if (WorkerRunWorkPackage(vecCurrWP, vecMappingWP, current_sim_time, dt) != if (WorkerRunWorkPackage(s_curr_wp, current_sim_time, dt) != IRM_OK) {
IRM_OK) { std::cerr << "Phreeqc error" << std::endl;
throw std::runtime_error("Phreeqc threw an error!");
}; };
phreeqc_time_end = MPI_Wtime(); phreeqc_time_end = MPI_Wtime();
if (dht_enabled) { for (std::size_t wp_i = 0; wp_i < s_curr_wp.size; wp_i++) {
dht->resultsToWP(vecCurrWP); std::copy(s_curr_wp.output[wp_i].begin(), s_curr_wp.output[wp_i].end(),
if (interp_enabled) { mpi_buffer.begin() + this->prop_count * wp_i);
interp->resultsToWP(vecCurrWP);
}
} }
/* send results to master */ /* send results to master */
MPI_Request send_req; MPI_Request send_req;
MPI_Isend(vecCurrWP.data(), count, MPI_DOUBLE, 0, LOOP_WORK, MPI_COMM_WORLD, MPI_Isend(mpi_buffer.data(), count, MPI_DOUBLE, 0, LOOP_WORK, MPI_COMM_WORLD,
&send_req); &send_req);
if (dht_enabled) { if (dht_enabled || interp_enabled) {
/* write results to DHT */ /* write results to DHT */
dht_fill_start = MPI_Wtime(); dht_fill_start = MPI_Wtime();
dht->fillDHT(local_work_package_size, vecCurrWP); dht->fillDHT(s_curr_wp);
dht_fill_end = MPI_Wtime(); dht_fill_end = MPI_Wtime();
if (interp_enabled) { if (interp_enabled) {
interp->writePairs(dht->getDHTResults()); interp->writePairs();
} }
timings.dht_get += dht_get_end - dht_get_start;
timings.dht_fill += dht_fill_end - dht_fill_start; timings.dht_fill += dht_fill_end - dht_fill_start;
} }
@ -429,36 +284,39 @@ void poet::ChemistryModule::WorkerReadDHTDump(
} }
IRM_RESULT IRM_RESULT
poet::ChemistryModule::WorkerRunWorkPackage( poet::ChemistryModule::WorkerRunWorkPackage(WorkPackage &work_package,
std::vector<double> &vecWP, std::vector<std::uint32_t> &vecMapping, double dSimTime, double dTimestep) {
double dSimTime, double dTimestep) {
if ((this->wp_size * this->prop_count) != vecWP.size()) {
return IRM_INVALIDARG;
}
// check if we actually need to start phreeqc // check if we actually need to start phreeqc
bool bRunPhreeqc = false; std::vector<std::uint32_t> pqc_mapping;
for (const auto &aMappingNum : vecMapping) {
if (aMappingNum != -1) { for (std::size_t i = 0; i < work_package.size; i++) {
bRunPhreeqc = true; if (work_package.mapping[i] == CHEM_PQC) {
break; pqc_mapping.push_back(i);
} }
} }
if (!bRunPhreeqc) { if (pqc_mapping.empty()) {
return IRM_OK; return IRM_OK;
} }
IRM_RESULT result; IRM_RESULT result;
this->PhreeqcRM::setPOETMapping(vecMapping); this->PhreeqcRM::setPOETMapping(pqc_mapping);
this->setDumpedField(vecWP); this->setDumpedField(work_package.input);
this->PhreeqcRM::SetTime(dSimTime); this->PhreeqcRM::SetTime(dSimTime);
this->PhreeqcRM::SetTimeStep(dTimestep); this->PhreeqcRM::SetTimeStep(dTimestep);
result = this->PhreeqcRM::RunCells(); result = this->PhreeqcRM::RunCells();
this->getDumpedField(vecWP); std::vector<std::vector<double>> output_tmp(work_package.size);
this->getDumpedField(output_tmp);
for (std::size_t i = 0; i < work_package.size; i++) {
if (work_package.mapping[i] == CHEM_PQC) {
work_package.output[i] = output_tmp[i];
}
}
return result; return result;
} }

View File

@ -18,15 +18,17 @@
** Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ** Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/ */
#include "poet/enums.hpp"
#include <algorithm> #include <algorithm>
#include <cassert> #include <cassert>
#include <cstdint> #include <cstdint>
#include <poet/DHT_Types.hpp>
#include <poet/SimParams.hpp> #include <poet/SimParams.hpp>
#include <RInside.h> #include <RInside.h>
#include <Rcpp.h> #include <Rcpp.h>
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <iostream> #include <iostream>
#include <string> #include <string>
#include <string_view> #include <string_view>
@ -37,202 +39,233 @@ using namespace std;
using namespace Rcpp; using namespace Rcpp;
poet::GridParams::s_GridParams(RInside &R) { poet::GridParams::s_GridParams(RInside &R) {
auto tmp_n_cells = auto tmp_n_cells =
Rcpp::as<std::vector<uint32_t>>(R.parseEval("mysetup$grid$n_cells")); Rcpp::as<std::vector<uint32_t>>(R.parseEval("mysetup$grid$n_cells"));
assert(tmp_n_cells.size() < 3); assert(tmp_n_cells.size() < 3);
this->dim = tmp_n_cells.size(); this->dim = tmp_n_cells.size();
std::copy(tmp_n_cells.begin(), tmp_n_cells.end(), this->n_cells.begin()); std::copy(tmp_n_cells.begin(), tmp_n_cells.end(), this->n_cells.begin());
auto tmp_s_cells = auto tmp_s_cells =
Rcpp::as<std::vector<double>>(R.parseEval("mysetup$grid$s_cells")); Rcpp::as<std::vector<double>>(R.parseEval("mysetup$grid$s_cells"));
assert(tmp_s_cells.size() == this->dim); assert(tmp_s_cells.size() == this->dim);
std::copy(tmp_s_cells.begin(), tmp_s_cells.end(), this->s_cells.begin()); std::copy(tmp_s_cells.begin(), tmp_s_cells.end(), this->s_cells.begin());
this->total_n = this->total_n =
(dim == 1 ? this->n_cells[0] : this->n_cells[0] * this->n_cells[1]); (dim == 1 ? this->n_cells[0] : this->n_cells[0] * this->n_cells[1]);
this->type = Rcpp::as<std::string>(R.parseEval("mysetup$grid$type")); this->type = Rcpp::as<std::string>(R.parseEval("mysetup$grid$type"));
} }
poet::DiffusionParams::s_DiffusionParams(RInside &R) { poet::DiffusionParams::s_DiffusionParams(RInside &R) {
this->initial_t = this->initial_t =
Rcpp::as<Rcpp::DataFrame>(R.parseEval("mysetup$diffusion$init")); Rcpp::as<Rcpp::DataFrame>(R.parseEval("mysetup$diffusion$init"));
this->alpha = this->alpha =
Rcpp::as<Rcpp::NumericVector>(R.parseEval("mysetup$diffusion$alpha")); Rcpp::as<Rcpp::NumericVector>(R.parseEval("mysetup$diffusion$alpha"));
if (Rcpp::as<bool>( if (Rcpp::as<bool>(
R.parseEval("'vecinj_inner' %in% names(mysetup$diffusion)"))) { R.parseEval("'vecinj_inner' %in% names(mysetup$diffusion)"))) {
this->vecinj_inner = this->vecinj_inner =
Rcpp::as<Rcpp::List>(R.parseEval("mysetup$diffusion$vecinj_inner")); Rcpp::as<Rcpp::List>(R.parseEval("mysetup$diffusion$vecinj_inner"));
} }
this->vecinj = this->vecinj =
Rcpp::as<Rcpp::DataFrame>(R.parseEval("mysetup$diffusion$vecinj")); Rcpp::as<Rcpp::DataFrame>(R.parseEval("mysetup$diffusion$vecinj"));
this->vecinj_index = this->vecinj_index =
Rcpp::as<Rcpp::DataFrame>(R.parseEval("mysetup$diffusion$vecinj_index")); Rcpp::as<Rcpp::DataFrame>(R.parseEval("mysetup$diffusion$vecinj_index"));
} }
void poet::ChemistryParams::initFromR(RInsidePOET &R) { void poet::ChemistryParams::initFromR(RInsidePOET &R) {
this->database_path = this->database_path =
Rcpp::as<std::string>(R.parseEval("mysetup$chemistry$database")); Rcpp::as<std::string>(R.parseEval("mysetup$chemistry$database"));
this->input_script = this->input_script =
Rcpp::as<std::string>(R.parseEval("mysetup$chemistry$input_script")); Rcpp::as<std::string>(R.parseEval("mysetup$chemistry$input_script"));
if (R.checkIfExists("dht_species", "mysetup$chemistry")) { if (R.checkIfExists("dht_species", "mysetup$chemistry")) {
this->dht_signifs = this->dht_signifs =
R.wrapNamedVector<std::uint32_t>("mysetup$chemistry$dht_species"); R.wrapNamedVector<std::uint32_t>("mysetup$chemistry$dht_species");
} }
if (R.checkIfExists("pht_species", "mysetup$chemistry")) { if (R.checkIfExists("pht_species", "mysetup$chemistry")) {
this->pht_signifs = this->pht_signifs =
R.wrapNamedVector<std::uint32_t>("mysetup$chemistry$pht_species"); R.wrapNamedVector<std::uint32_t>("mysetup$chemistry$pht_species");
} }
} }
SimParams::SimParams(int world_rank_, int world_size_) { SimParams::SimParams(int world_rank_, int world_size_) {
this->simparams.world_rank = world_rank_; this->simparams.world_rank = world_rank_;
this->simparams.world_size = world_size_; this->simparams.world_size = world_size_;
} }
int SimParams::parseFromCmdl(char *argv[], RInsidePOET &R) { int SimParams::parseFromCmdl(char *argv[], RInsidePOET &R) {
// initialize argh object // initialize argh object
argh::parser cmdl(argv); argh::parser cmdl(argv);
// if user asked for help // if user asked for help
if (cmdl[{"help", "h"}]) { if (cmdl[{"help", "h"}]) {
if (simparams.world_rank == 0) { if (simparams.world_rank == 0) {
MSG("Todo"); MSG("Todo");
MSG("See README.md for further information."); MSG("See README.md for further information.");
}
return poet::PARSER_HELP;
} }
// if positional arguments are missing return poet::PARSER_HELP;
else if (!cmdl(2)) { }
if (simparams.world_rank == 0) { // if positional arguments are missing
ERRMSG("Kin needs 2 positional arguments: "); else if (!cmdl(2)) {
ERRMSG("1) the R script defining your simulation and"); if (simparams.world_rank == 0) {
ERRMSG("2) the directory prefix where to save results and profiling"); ERRMSG("Kin needs 2 positional arguments: ");
} ERRMSG("1) the R script defining your simulation and");
return poet::PARSER_ERROR; ERRMSG("2) the directory prefix where to save results and profiling");
} }
return poet::PARSER_ERROR;
}
// collect all parameters which are not known, print them to stderr and return // collect all parameters which are not known, print them to stderr and return
// with PARSER_ERROR // with PARSER_ERROR
std::list<std::string> optionsError = validateOptions(cmdl); std::list<std::string> optionsError = validateOptions(cmdl);
if (!optionsError.empty()) { if (!optionsError.empty()) {
if (simparams.world_rank == 0) { if (simparams.world_rank == 0) {
ERRMSG("Unrecognized option(s):\n"); ERRMSG("Unrecognized option(s):\n");
for (auto option : optionsError) { for (auto option : optionsError) {
ERRMSG(std::string(option)); ERRMSG(std::string(option));
} }
ERRMSG("Make sure to use available options. Exiting!"); ERRMSG("Make sure to use available options. Exiting!");
}
return poet::PARSER_ERROR;
} }
return poet::PARSER_ERROR;
simparams.print_progressbar = cmdl[{"P", "progress"}]; }
/*Parse DHT arguments*/ simparams.print_progressbar = cmdl[{"P", "progress"}];
chem_params.use_dht = cmdl["dht"];
// cout << "CPP: DHT is " << ( dht_enabled ? "ON" : "OFF" ) << '\n'; simparams.print_progressbar = cmdl[{"P", "progress"}];
/*Parse DHT arguments*/
chem_params.use_dht = cmdl["dht"];
chem_params.use_interp = cmdl["interp"];
// cout << "CPP: DHT is " << ( dht_enabled ? "ON" : "OFF" ) << '\n';
cmdl("dht-size", DHT_SIZE_PER_PROCESS_MB) >> chem_params.dht_size;
// cout << "CPP: DHT size per process (Byte) = " << dht_size_per_process <<
// endl;
cmdl("dht-snaps", 0) >> chem_params.dht_snaps;
cmdl("dht-file") >> chem_params.dht_file;
/*Parse work package size*/
cmdl("work-package-size", WORK_PACKAGE_SIZE_DEFAULT) >> simparams.wp_size;
cmdl("interp-size", 100) >> chem_params.pht_size;
cmdl("interp-min", 5) >> chem_params.interp_min_entries;
cmdl("interp-bucket-entries", 20) >> chem_params.pht_max_entries;
/*Parse output options*/
simparams.store_result = !cmdl["ignore-result"];
cout << "CPP: Complete results storage is "
<< (simparams.store_result ? "ON" : "OFF") << endl;
cout << "CPP: Work Package Size: " << simparams.wp_size << endl;
cout << "CPP: DHT is " << (chem_params.use_dht ? "ON" : "OFF") << '\n';
if (chem_params.use_dht || chem_params.use_interp) {
cout << "CPP: DHT strategy is " << simparams.dht_strategy << endl;
cout << "CPP: DHT key default digits (ignored if 'signif_vector' is "
"defined) = "
<< simparams.dht_significant_digits << endl;
cout << "CPP: DHT logarithm before rounding: "
<< (simparams.dht_log ? "ON" : "OFF") << endl;
cout << "CPP: DHT size per process (Byte) = " << chem_params.dht_size
<< endl;
cout << "CPP: DHT save snapshots is " << chem_params.dht_snaps << endl;
cout << "CPP: DHT load file is " << chem_params.dht_file << endl;
}
/*Parse work package size*/
cmdl("work-package-size", WORK_PACKAGE_SIZE_DEFAULT) >> simparams.wp_size;
chem_params.use_interp = cmdl["interp"];
cmdl("interp-size", 100) >> chem_params.pht_size;
cmdl("interp-min", 5) >> chem_params.interp_min_entries;
cmdl("interp-bucket-entries", 20) >> chem_params.pht_max_entries;
/*Parse output options*/
simparams.store_result = !cmdl["ignore-result"];
if (simparams.world_rank == 0) {
MSG("Complete results storage is " + BOOL_PRINT(simparams.store_result));
MSG("Work Package Size: " + std::to_string(simparams.wp_size));
MSG("DHT is " + BOOL_PRINT(chem_params.use_dht));
if (chem_params.use_dht) { if (chem_params.use_dht) {
cmdl("dht-size", DHT_SIZE_PER_PROCESS_MB) >> chem_params.dht_size; MSG("DHT strategy is " + std::to_string(simparams.dht_strategy));
// cout << "CPP: DHT size per process (Byte) = " << dht_size_per_process << // MDL: these should be outdated (?)
// endl; // MSG("DHT key default digits (ignored if 'signif_vector' is "
// "defined) = "
cmdl("dht-snaps", 0) >> chem_params.dht_snaps; // << simparams.dht_significant_digits);
// MSG("DHT logarithm before rounding: "
cmdl("dht-file") >> chem_params.dht_file; // << (simparams.dht_log ? "ON" : "OFF"));
} MSG("DHT size per process (Byte) = " +
/*Parse work package size*/ std::to_string(chem_params.dht_size));
cmdl("work-package-size", WORK_PACKAGE_SIZE_DEFAULT) >> simparams.wp_size; MSG("DHT save snapshots is " + BOOL_PRINT(chem_params.dht_snaps));
MSG("DHT load file is " + chem_params.dht_file);
chem_params.use_interp = cmdl["interp"];
cmdl("interp-size", 100) >> chem_params.pht_size;
cmdl("interp-min", 5) >> chem_params.interp_min_entries;
cmdl("interp-bucket-entries", 20) >> chem_params.pht_max_entries;
/*Parse output options*/
simparams.store_result = !cmdl["ignore-result"];
if (simparams.world_rank == 0) {
MSG("Complete results storage is " + BOOL_PRINT(simparams.store_result));
MSG("Work Package Size: " + std::to_string(simparams.wp_size));
MSG("DHT is " + BOOL_PRINT(chem_params.use_dht));
if (chem_params.use_dht) {
MSG("DHT strategy is " + std::to_string(simparams.dht_strategy));
// MDL: these should be outdated (?)
// MSG("DHT key default digits (ignored if 'signif_vector' is "
// "defined) = "
// << simparams.dht_significant_digits);
// MSG("DHT logarithm before rounding: "
// << (simparams.dht_log ? "ON" : "OFF"));
MSG("DHT size per process (Byte) = " + std::to_string(chem_params.dht_size));
MSG("DHT save snapshots is " + BOOL_PRINT(chem_params.dht_snaps));
MSG("DHT load file is " + chem_params.dht_file);
}
if (chem_params.use_interp) {
MSG("PHT interpolation enabled: " + BOOL_PRINT(chem_params.use_interp));
MSG("PHT interp-size = " + std::to_string(chem_params.pht_size));
MSG("PHT interp-min = " + std::to_string(chem_params.interp_min_entries));
MSG("PHT interp-bucket-entries = " + std::to_string(chem_params.pht_max_entries));
}
} }
cmdl(1) >> filesim; if (chem_params.use_interp) {
cmdl(2) >> out_dir; MSG("PHT interpolation enabled: " + BOOL_PRINT(chem_params.use_interp));
MSG("PHT interp-size = " + std::to_string(chem_params.pht_size));
MSG("PHT interp-min = " +
std::to_string(chem_params.interp_min_entries));
MSG("PHT interp-bucket-entries = " +
std::to_string(chem_params.pht_max_entries));
}
}
chem_params.dht_outdir = out_dir; cmdl(1) >> filesim;
cmdl(2) >> out_dir;
/* distribute information to R runtime */ chem_params.dht_outdir = out_dir;
// if local_rank == 0 then master else worker
R["local_rank"] = simparams.world_rank;
// assign a char* (string) to 'filesim'
R["filesim"] = wrap(filesim);
// assign a char* (string) to 'fileout'
R["fileout"] = wrap(out_dir);
// pass the boolean "store_result" to the R process
R["store_result"] = simparams.store_result;
// worker count
R["n_procs"] = simparams.world_size - 1;
// work package size
R["work_package_size"] = simparams.wp_size;
// dht enabled?
R["dht_enabled"] = chem_params.use_dht;
// log before rounding?
R["dht_log"] = simparams.dht_log;
// eval the init string, ignoring any returns /* distribute information to R runtime */
R.parseEvalQ("source(filesim)"); // if local_rank == 0 then master else worker
R.parseEvalQ("mysetup <- setup"); R["local_rank"] = simparams.world_rank;
// assign a char* (string) to 'filesim'
R["filesim"] = wrap(filesim);
// assign a char* (string) to 'fileout'
R["fileout"] = wrap(out_dir);
// pass the boolean "store_result" to the R process
R["store_result"] = simparams.store_result;
// worker count
R["n_procs"] = simparams.world_size - 1;
// work package size
R["work_package_size"] = simparams.wp_size;
// dht enabled?
R["dht_enabled"] = chem_params.use_dht;
// log before rounding?
R["dht_log"] = simparams.dht_log;
this->chem_params.initFromR(R); // eval the init string, ignoring any returns
R.parseEvalQ("source(filesim)");
R.parseEvalQ("mysetup <- setup");
return poet::PARSER_OK; this->chem_params.initFromR(R);
return poet::PARSER_OK;
} }
void SimParams::initVectorParams(RInside &R) {} void SimParams::initVectorParams(RInside &R) {}
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;
/* loop over all flags and compare to given flaglist*/ /* loop over all flags and compare to given flaglist*/
for (auto &flag : cmdl.flags()) { for (auto &flag : cmdl.flags()) {
if (!(flaglist.find(flag) != flaglist.end())) if (!(flaglist.find(flag) != flaglist.end()))
retList.push_back(flag); retList.push_back(flag);
} }
/* and loop also over params and compare to given paramlist */ /* and loop also over params and compare to given paramlist */
for (auto &param : cmdl.params()) { for (auto &param : cmdl.params()) {
if (!(paramlist.find(param.first) != paramlist.end())) if (!(paramlist.find(param.first) != paramlist.end()))
retList.push_back(param.first); retList.push_back(param.first);
} }
return retList; return retList;
} }