1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
|
// SPDX-License-Identifier: LGPL-3.0-or-later
// Author: Kristian Lytje
#include <table/DebyeTableManager.h>
#include <table/ArrayDebyeTable.h>
#include <stdexcept>
#include <numeric>
#include <cassert>
using namespace ausaxs;
using namespace ausaxs::table;
DebyeTableManager::DebyeTableManager() = default;
DebyeTableManager::DebyeTableManager(const DebyeTableManager& table) {*this = table;}
DebyeTableManager::DebyeTableManager(DebyeTableManager&&) noexcept = default;
DebyeTableManager& DebyeTableManager::operator=(DebyeTableManager&&) noexcept = default;
DebyeTableManager& DebyeTableManager::operator=(const DebyeTableManager& table) {
q = table.q;
d = table.d;
use_custom_table = table.use_custom_table;
if (table.custom_sinc_table) {
custom_sinc_table = std::make_unique<table::VectorDebyeTable>(d.axis, q.axis);
}
return *this;
}
observer_ptr<const table::DebyeTable> DebyeTableManager::get_sinc_table() const {
if (use_custom_table) {
if (recalculate) {
if (q.defaulted && d.defaulted) {
throw std::runtime_error("DebyeTableManager::get_sinc_table(): both q-axis and d-axis are defaulted, but custom table requested.");
} else if (q.defaulted) {
custom_sinc_table = std::make_unique<table::VectorDebyeTable>(d.axis, constants::axes::q_vals);
} else if (d.defaulted) {
custom_sinc_table = std::make_unique<table::VectorDebyeTable>(constants::axes::d_vals, q.axis);
} else {
custom_sinc_table = std::make_unique<table::VectorDebyeTable>(d.axis, q.axis);
}
recalculate = false;
}
return custom_sinc_table.get();
} else {
return &ArrayDebyeTable::get_default_table();
}
}
void DebyeTableManager::reset_to_default() {
q.defaulted = true;
d.defaulted = true;
use_custom_table = false;
}
bool appears_identical(const std::vector<double>& a, const std::vector<double>& b) {
if (a.size() != b.size()) {return false;}
if (a.size() > 10) {
for (size_t i = 0; i < 5; ++i) {
if (a[i] != b[i]) {return false;}
}
for (size_t i = a.size()-5; i < a.size(); ++i) {
if (a[i] != b[i]) {return false;}
}
}
// extra assert in debug mode. if the above is not sufficient, this should catch it during testing
assert(
std::abs(std::accumulate(a.begin(), a.end(), 0.0) - std::accumulate(b.begin(), b.end(), 0.0)) < 1e-9
&& "appears_identical: Sums do not match"
);
return true;
}
template<typename T, typename>
void DebyeTableManager::set_q_axis(T&& q_axis) {
if (appears_identical(q.axis, q_axis)) {return;} // no change
q.axis = std::forward<T>(q_axis);
q.defaulted = false;
use_custom_table = true;
recalculate = true;
}
template<typename T, typename>
void DebyeTableManager::set_d_axis(T&& d_axis) {
if (appears_identical(d.axis, d_axis)) {return;} // no change
d.axis = std::forward<T>(d_axis);
d.defaulted = false;
use_custom_table = true;
recalculate = true;
}
template void DebyeTableManager::set_q_axis(std::vector<double>&& q_axis);
template void DebyeTableManager::set_q_axis(const std::vector<double>& q_axis);
template void DebyeTableManager::set_q_axis(std::vector<double>& q_axis);
template void DebyeTableManager::set_d_axis(std::vector<double>&& d_axis);
template void DebyeTableManager::set_d_axis(const std::vector<double>& d_axis);
template void DebyeTableManager::set_d_axis(std::vector<double>& d_axis);
|