poet/src/ChemistryModule/DHT_Wrapper.cpp
2023-03-28 14:27:00 +02:00

239 lines
7.2 KiB
C++

/*
** 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/DHT_Wrapper.hpp"
#include "poet/DHT_Types.hpp"
#include "poet/HashFunctions.hpp"
#include <algorithm>
#include <cmath>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <iostream>
#include <math.h>
#include <openssl/evp.h>
#include <stdexcept>
#include <vector>
using namespace poet;
using namespace std;
inline DHT_Keyelement round_key_element(double value, std::uint32_t signif) {
std::int8_t exp = (std::int8_t)std::floor(std::log10(std::fabs(value)));
std::int64_t significant = value * std::pow(10, signif - exp - 1);
DHT_Keyelement elem;
elem.exp = exp;
elem.significant = significant;
return elem;
}
void poet::DHT_ResultObject::ResultsToMapping(
std::vector<int32_t> &curr_mapping) {
uint32_t iMappingIndex = 0;
for (uint32_t i = 0; i < this->length; i++) {
if (curr_mapping[i] == -1) {
continue;
}
curr_mapping[i] = (this->needPhreeqc[i] ? iMappingIndex++ : -1);
}
}
void poet::DHT_ResultObject::ResultsToWP(std::vector<double> &curr_wp) {
for (uint32_t i = 0; i < this->length; i++) {
if (!this->needPhreeqc[i]) {
const uint32_t length = this->results[i].end() - this->results[i].begin();
std::copy(this->results[i].begin(), this->results[i].end(),
curr_wp.begin() + (length * i));
}
}
}
DHT_Wrapper::DHT_Wrapper(MPI_Comm dht_comm, uint32_t dht_size,
uint32_t key_count, uint32_t data_count)
: key_count(key_count), data_count(data_count) {
poet::initHashCtx(EVP_md5());
// initialize DHT object
uint32_t key_size = key_count * sizeof(DHT_Keyelement);
uint32_t data_size = data_count * sizeof(double);
uint32_t buckets_per_process = dht_size / (1 + data_size + key_size);
dht_object = DHT_create(dht_comm, buckets_per_process, data_size, key_size + 1,
&poet::Murmur2_64A);
// extract needed values from sim_param struct
// t_simparams tmp = params.getNumParams();
// this->dt_differ = tmp.dt_differ;
// this->dht_log = tmp.dht_log;
// this->dht_signif_vector = params.getDHTSignifVector();
// 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() {
// free DHT
DHT_free(dht_object, NULL, NULL);
poet::freeHashCtx();
}
auto DHT_Wrapper::checkDHT(int length, double dt,
const std::vector<double> &work_package)
-> poet::DHT_ResultObject {
DHT_ResultObject check_data;
check_data.length = length;
check_data.keys.resize(length);
check_data.results.resize(length);
check_data.needPhreeqc.resize(length);
// loop over every grid cell contained in work package
for (int i = 0; i < length; i++) {
// point to current grid cell
void *key = (void *)&(work_package[i * this->key_count]);
auto &data = check_data.results[i];
auto &key_vector = check_data.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
int res = DHT_read(this->dht_object, key_vector.data(), data.data());
switch (res) {
case DHT_SUCCESS:
check_data.needPhreeqc[i] = false;
this->dht_hits++;
break;
case DHT_READ_MISS:
check_data.needPhreeqc[i] = true;
this->dht_miss++;
break;
}
}
return check_data;
}
void DHT_Wrapper::fillDHT(int length, const DHT_ResultObject &dht_check_data,
const std::vector<double> &results) {
// loop over every grid cell contained in work package
for (int i = 0; i < length; i++) {
// If true grid cell was simulated, needs to be inserted into dht
if (dht_check_data.needPhreeqc[i]) {
const auto &key = dht_check_data.keys[i];
void *data = (void *)&(results[i * this->data_count]);
// fuzz data (round, logarithm etc.)
// insert simulated data with fuzzed key into DHT
int res = DHT_write(this->dht_object, (void *)key.data(), data);
// if data was successfully written ...
if ((res != DHT_SUCCESS) && (res == DHT_WRITE_SUCCESS_WITH_EVICTION)) {
dht_evictions++;
}
}
}
}
int DHT_Wrapper::tableToFile(const char *filename) {
int res = DHT_to_file(dht_object, filename);
return res;
}
int DHT_Wrapper::fileToTable(const char *filename) {
int res = DHT_from_file(dht_object, filename);
if (res != DHT_SUCCESS)
return res;
#ifdef DHT_STATISTICS
DHT_print_statistics(dht_object);
#endif
return DHT_SUCCESS;
}
void DHT_Wrapper::printStatistics() {
int res;
res = DHT_print_statistics(dht_object);
if (res != DHT_SUCCESS) {
// MPI ERROR ... WHAT TO DO NOW?
// RUNNING CIRCLES WHILE SCREAMING
}
}
std::vector<DHT_Keyelement> DHT_Wrapper::fuzzForDHT(int var_count, void *key,
double dt) {
constexpr double zero_val = 10E-14;
std::vector<DHT_Keyelement> vecFuzz(var_count + 1);
std::memset(&vecFuzz[0], 0, sizeof(DHT_Keyelement) * var_count);
unsigned int i = 0;
// introduce fuzzing to allow more hits in DHT
// loop over every variable of grid cell
for (i = 0; i < (unsigned int)var_count; i++) {
double &curr_key = ((double *)key)[i];
if (curr_key != 0) {
if (curr_key < zero_val &&
this->dht_prop_type_vector[i] == DHT_TYPE_ACT) {
continue;
}
if (this->dht_prop_type_vector[i] == DHT_TYPE_IGNORE) {
continue;
}
vecFuzz[i] = round_key_element(curr_key, dht_signif_vector[i]);
}
}
// if timestep differs over iterations set current current time step at the
// end of fuzzing buffer
vecFuzz[var_count] = round_key_element(dt, 55);
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;
}