21#ifndef B2CASE_DATABASE_H_
22#define B2CASE_DATABASE_H_
28#include "b2model_database.H"
29#include "b2ppconfig.h"
31#include "model_imp/b2case_component.H"
36#include "utils/b2splines.H"
37#include "utils/b2threading.H"
39namespace b2000::b2dbv3 {
50 std::string get_stage_id(
int stage = -1)
const override = 0;
52 void push_rtable(
const RTable& rtable) { rtable_list.push_back(&rtable); }
54 void set_case_rtable(
const RTable& rtable) { case_rtable = &rtable; }
56 const RTable& get_case_rtable() {
return *case_rtable; }
58 void set_stage_rtable(
const RTable& rtable) { stage_rtable = &rtable; }
60 const RTable& top_rtable() {
return *rtable_list.back(); }
62 void pop_rtable() { rtable_list.pop_back(); }
64 void set_cmdline_opt(
Dictionary* cmdline_set_) { cmdline_set = cmdline_set_; }
67 rtable_list = case_.rtable_list;
68 cmdline_set = case_.cmdline_set;
71 bool has_key(
const std::string& key)
const override {
72 if (cmdline_set && cmdline_set->
has_key(key)) {
return true; }
73 std::string case_key(
"CASE");
76 std::string stage_key = case_key +
"STAGE" + get_stage_id() +
'.' + key;
78 if (cmdline_set && (cmdline_set->
has_key(case_key) || cmdline_set->
has_key(stage_key))) {
81 if (stage_rtable && stage_rtable->
has_key(key)) {
return true; }
82 if (case_rtable && case_rtable->
has_key(key)) {
return true; }
83 if (key_value.
has_key(key)) {
return true; }
84 for (std::vector<const RTable*>::const_reverse_iterator i = rtable_list.rbegin();
85 i != rtable_list.rend(); ++i) {
86 if ((*i)->has_key(key)) {
return true; }
88 keys_conversion_t::const_iterator res = keys_conversion.find(key);
89 if (res != keys_conversion.end()) {
return has_key(res->second); }
94 T get(
const std::string& key)
const {
95 std::string case_key(
"CASE");
98 std::string stage_key = case_key +
"STAGE" + get_stage_id() +
'.' + key;
100 if (cmdline_set && cmdline_set->
has_key(stage_key)) {
102 T r = cmdline_set->
get<T>(stage_key);
103 const_cast<RTable&
>(solution_rtable).set(key, r);
107 <<
logging::warning <<
"Cannot parse the command line directive adir: " << e
108 << logging::LOGFLUSH;
112 T r = key_value.
get<T>(key);
113 const_cast<RTable&
>(solution_rtable).set(key, r);
116 if (stage_rtable && stage_rtable->
has_key(key)) {
117 T r = stage_rtable->
get<T>(key);
118 const_cast<RTable&
>(solution_rtable).set(key, r);
121 if (cmdline_set && cmdline_set->
has_key(case_key)) {
123 T r = cmdline_set->
get<T>(case_key);
124 const_cast<RTable&
>(solution_rtable).set(key, r);
128 <<
logging::warning <<
"Cannot parse the command line directive adir: " << e
129 << logging::LOGFLUSH;
132 if (case_rtable && case_rtable->
has_key(key)) {
133 T r = case_rtable->
get<T>(key);
134 const_cast<RTable&
>(solution_rtable).set(key, r);
137 if (cmdline_set && cmdline_set->
has_key(key)) {
139 T r = cmdline_set->
get<T>(key);
140 const_cast<RTable&
>(solution_rtable).set(key, r);
144 <<
logging::warning <<
"Cannot parse the command line directive adir: " << e
145 << logging::LOGFLUSH;
148 for (std::vector<const RTable*>::const_reverse_iterator ii = rtable_list.rbegin();
149 ii != rtable_list.rend(); ++ii) {
150 if ((*ii)->has_key(key)) {
151 T r = (*ii)->get<T>(key);
152 const_cast<RTable&
>(solution_rtable).set(key, r);
156 keys_conversion_t::const_iterator res = keys_conversion.find(key);
157 if (res != keys_conversion.end()) {
158 T r = get<T>(res->second);
159 const_cast<RTable&
>(solution_rtable).set(key, r);
162 Exception() <<
"The key " << key <<
" of type " <<
typeid(T)
163 <<
" is needed but not defined for "
165 << get_id() <<
"." <<
THROW;
169 template <
typename T>
170 T get(
const std::string& key,
const T& default_)
const {
171 if (!has_key(key)) {
return default_; }
175 std::string get_string(
const std::string& key)
const override {
return get<std::string>(key); }
177 bool get_bool(
const std::string& key)
const override {
return get<bool>(key); }
179 int get_int(
const std::string& key)
const override {
return get<int>(key); }
181 double get_double(
const std::string& key)
const override {
return get<double>(key); }
183 b2000::csda<double> get_csda_double(
const std::string& key)
const override {
184 return get<b2000::csda<double>>(key);
187 std::complex<double> get_complex_double(
const std::string& key)
const override {
188 return get<std::complex<double>>(key);
191 std::string get_string(
const std::string& key,
const std::string& default_)
const override {
192 return get<std::string>(key, default_);
195 bool get_bool(
const std::string& key,
const bool& default_)
const {
196 return get<bool>(key, default_);
199 int get_int(
const std::string& key,
const int& default_)
const {
200 return get<int>(key, default_);
203 double get_double(
const std::string& key,
const double& default_)
const {
204 return get<double>(key, default_);
207 b2000::csda<double> get_csda_double(
208 const std::string& key,
const b2000::csda<double>& default_)
const {
209 return get<b2000::csda<double>>(key, default_);
212 std::complex<double> get_complex_double(
213 const std::string& key,
const std::complex<double>& default_)
const {
214 return get<std::complex<double>>(key, default_);
217 template <
typename T>
218 void get(
const std::string& key, std::vector<T>& v)
const {
219 std::string case_key(
"CASE");
220 case_key += get_id();
222 std::string stage_key = case_key +
"STAGE" + get_stage_id() +
'.' + key;
224 if (cmdline_set && cmdline_set->
has_key(stage_key)) {
226 cmdline_set->
get(stage_key, v);
227 const_cast<RTable&
>(solution_rtable).set(key, v);
231 <<
logging::warning <<
"Cannot parse the command line directive adir: " << e
232 << logging::LOGFLUSH;
235 if (stage_rtable && stage_rtable->
has_key(key)) {
236 stage_rtable->
get(key, v);
237 const_cast<RTable&
>(solution_rtable).set(key, v);
240 if (cmdline_set && cmdline_set->
has_key(case_key)) {
242 cmdline_set->
get(case_key, v);
243 const_cast<RTable&
>(solution_rtable).set(key, v);
247 <<
logging::warning <<
"Cannot parse the command line directive adir: " << e
248 << logging::LOGFLUSH;
251 if (case_rtable && case_rtable->
has_key(key)) {
252 case_rtable->
get(key, v);
253 const_cast<RTable&
>(solution_rtable).set(key, v);
256 if (cmdline_set && cmdline_set->
has_key(key)) {
258 cmdline_set->
get(key, v);
259 const_cast<RTable&
>(solution_rtable).set(key, v);
263 <<
logging::warning <<
"Cannot parse the command line directive adir: " << e
264 << logging::LOGFLUSH;
267 for (std::vector<const RTable*>::const_reverse_iterator i = rtable_list.rbegin();
268 i != rtable_list.rend(); ++i) {
269 if ((*i)->has_key(key)) {
271 const_cast<RTable&
>(solution_rtable).set(key, v);
275 keys_conversion_t::const_iterator res = keys_conversion.find(key);
276 if (res != keys_conversion.end()) {
278 const_cast<RTable&
>(solution_rtable).set(key, v);
281 Exception() <<
"The key " << key <<
" of type array of " <<
typeid(T)
282 <<
" is needed but not "
283 "defined for the case "
284 << get_id() <<
"." <<
THROW;
287 void set(
const std::string& key,
int value)
override { key_value.
set(key, value); }
289 void set(
const std::string& key,
double value)
override { key_value.
set(key, value); }
291 void set(
const std::string& key, b2000::csda<double> value)
override {
292 key_value.
set(key, value);
295 void set(
const std::string& key, std::complex<double> value)
override {
296 key_value.
set(key, value);
299 void set(
const std::string& key,
const std::string& value)
override {
300 key_value.
set(key, value);
303 void get(
const std::string& key, std::vector<int>& v)
const override { get<int>(key, v); }
305 void get(
const std::string& key, std::vector<double>& v)
const override { get<double>(key, v); }
307 void get(
const std::string& key, std::vector<b2000::csda<double>>& v)
const override {
308 get<b2000::csda<double>>(key, v);
311 void get(
const std::string& key, std::vector<std::complex<double>>& v)
const override {
312 get<std::complex<double>>(key, v);
315 void warn_on_non_used_key()
const override {
319 RTable& get_solution_rtable() {
return solution_rtable; }
322 std::vector<const RTable*> rtable_list;
323 const RTable* case_rtable;
324 const RTable* stage_rtable;
326 using keys_conversion_t = std::map<std::string, std::string>;
327 keys_conversion_t keys_conversion;
335 for (
auto& comp : list_comp) { comp->decref_or_free(); }
336 for (
auto& time_func : list_time_function) {
delete time_func; }
338 void init(Model& model,
const std::string& db_id, Allocator& allocator);
342 Model& model,
const std::string& case_id,
const RTable& rt,
343 const std::string& subtype_name,
double scalef, Allocator& allocator);
346 Component& get_component(
const std::string& comp_id);
348 std::string get_id()
const override {
return id; }
350 void get_subcase_ids(std::set<int>& subcase_ids_)
const override { subcase_ids_ = subcase_ids; }
352 size_t get_number_of_stage()
const override {
return 1; }
354 std::string get_stage_id(
int stage = -1)
const override {
return id; }
356 int get_stage_number()
const override {
return 0; }
358 double get_stage_size(
int stage = -1)
const override {
359 double pamax = get_double(
"PAMAX", 1.0);
360 if (pamax == 0.0) { pamax = 1.0; }
364 bool next_stage()
override {
return false; }
366 void set_stage(
int stage)
override {
return; }
368 class CaseComponentIterator :
public ComponentIterator {
370 Component* next()
override {
371 ensure_matching_subcase_id();
372 if (begin == end) {
return nullptr; }
377 friend class b2dbv3::Case;
378 CaseComponentIterator(Component** begin_, Component** end_,
const int subcase_id_)
379 : begin(begin_), end(end_), subcase_id(subcase_id_) {
380 ensure_matching_subcase_id();
383 void ensure_matching_subcase_id() {
384 if (subcase_id < 0) {
return; }
385 for (; begin != end; ++begin) {
386 if (*begin !=
nullptr && (*begin)->get_subcase_id() == subcase_id) {
break; }
390 using list_comp_t = std::vector<Component*>;
396 component_iterator get_component_iterator()
override {
397 return component_iterator(
398 new CaseComponentIterator(&list_comp.front(), &list_comp.back() + 1, -1));
401 component_iterator get_component_iterator_for_stage(
size_t stage)
override {
402 return get_component_iterator();
405 component_iterator get_component_iterator_for_stage_and_subcase(
406 size_t stage_,
int subcase_id_)
override {
407 if (stage_ != 0 && subcase_id_ != 0) {
412 return component_iterator(
413 new CaseComponentIterator(&list_comp.front(), &list_comp.back() + 1, subcase_id_));
416 using type_t = ObjectTypeComplete<Case>;
420 class TimeFunction :
public b2000::TimeFunction {
422 TimeFunction(
double scale_) : scale(scale_) {}
424 double d_value(
double t,
int order)
override {
427 static const int binomial_coefficient[7][7] = {
433 {1, -5, 10, -10, 5, -1},
434 {1, -6, 15, -20, 15, -6, 1}};
437 double vt = value(t);
446 for (
int i = 0; i <= order; ++i) {
447 new_r += binomial_coefficient[order][i] * value(t + (order / 2.0 - i) * h);
449 for (
int i = 0; i != order; ++i) { new_r /= h; }
450 if (std::abs(new_r - r) < 0.0000001) {
return new_r; }
461 class TimeFunctionIdentity :
public TimeFunction {
463 TimeFunctionIdentity(
double scale_) : TimeFunction(scale_) {}
465 double value(
double t)
override {
return scale * t; }
467 double d_value(
double t,
int order)
override {
468 if (order == 1) {
return scale; }
469 if (order > 1) {
return 0; }
470 Exception() <<
THROW;
475 class TimeFunctionExpression :
public TimeFunction {
477 TimeFunctionExpression(
double scale_,
const std::string& expression_string)
478 : TimeFunction(scale_) {
479 expression.SetExpr(expression_string);
480 expression.DefineVar(
"t", &var_t);
481 expression.SetVarFactory(AddVariable,
this);
485 expression.ClearConst();
491 double value(
double t)
override {
493 b2spin_rw_mutex::scoped_lock lock(mutex);
496 return scale * expression.Eval();
497 }
catch (mu::Parser::exception_type& e) {
498 Exception() <<
"In the expression \"" << expression.GetExpr()
499 <<
"\": " << e.GetMsg() <<
THROW;
505 b2spin_rw_mutex mutex;
507 static double* AddVariable(
const char* a_szName,
void* pUserData) {
508 TimeFunctionExpression* this_ =
static_cast<TimeFunctionExpression*
>(pUserData);
509 std::deque<double>& dyn_var = this_->dyn_var;
511 b2spin_rw_mutex::scoped_lock lock(this_->mutex);
513 dyn_var.push_back(0);
514 return &(dyn_var.back());
517 mu::Parser expression;
518 std::deque<double> dyn_var;
521 class TimeFunctionTabulated :
public TimeFunction {
523 TimeFunctionTabulated(
double scale_,
const std::vector<double>& tabulated_vector)
524 : TimeFunction(scale_),
525 spline(tabulated_vector.begin(), tabulated_vector.end(), true) {}
527 double value(
double t)
override {
return scale * spline(t); }
535 using list_comp_t = std::vector<Component*>;
536 list_comp_t list_comp;
538 using list_time_function_t = std::vector<TimeFunction*>;
539 list_time_function_t list_time_function;
540 std::set<int> subcase_ids;
542 void add_case(Model& model,
const std::string& set_id,
double scalef, Allocator& allocator);
545class CaseStage :
public Case {
547 void init(Model& model,
const std::string& db_id, Allocator& allocator);
549 size_t get_number_of_stage()
const override {
return list_stage.size(); }
551 std::string get_stage_id(
int stage_ = -1)
const override {
553 return stage->first.get_id();
555 return get_stage(stage_)->first.get_id();
559 int get_stage_number()
const override {
return stage_number; }
561 double get_stage_size(
int stage_ = -1)
const override {
563 return stage->second;
565 return get_stage(stage_)->second;
569 bool next_stage()
override;
571 void set_stage(
int stage_)
override;
573 component_iterator get_component_iterator()
override {
574 return stage->first.get_component_iterator();
577 component_iterator get_component_iterator_for_stage(
size_t stage_)
override {
578 return get_stage(stage_)->first.get_component_iterator();
581 component_iterator get_component_iterator_for_stage_and_subcase(
582 size_t stage_,
int subcase_id_)
override {
583 if (stage_ != 0 && subcase_id_ != 0) {
588 return get_stage(stage_)->first.get_component_iterator();
591 using type_t = ObjectTypeComplete<CaseStage>;
595 void add_stage(Model& model,
const std::string& set_id,
double scalef, Allocator& allocator);
597 using list_stage_t = std::list<std::pair<Case, double>>;
598 list_stage_t list_stage;
599 list_stage_t::iterator stage;
602 list_stage_t::const_iterator get_stage(
int stage_)
const {
603 if (stage_ < 0 ||
size_t(stage_) >= list_stage.size()) { Exception() <<
THROW; }
604 list_stage_t::const_iterator i = list_stage.begin();
605 while (stage_--) { ++i; }
609 list_stage_t::iterator get_stage(
int stage_) {
610 if (stage_ < 0 ||
size_t(stage_) >= list_stage.size()) { Exception() <<
THROW; }
611 list_stage_t::iterator i = list_stage.begin();
612 while (stage_--) { ++i; }
621 size_t get_number_of_case()
const override {
return size(); }
623 class CaseIterator :
public b2000::CaseList::CaseIterator {
625 Case* next()
override {
626 if (begin != end) {
return *begin++; }
629 size_t get_number_of_case()
const override {
return end - begin; }
632 friend class b2dbv3::CaseList;
633 CaseIterator(std::vector<Case*>& cl) : begin(cl.begin()), end(cl.end()) {}
634 std::vector<Case*>::iterator begin;
635 std::vector<Case*>::iterator end;
638 b2000::CaseList::case_iterator get_case_iterator()
override {
639 return case_iterator(
new CaseIterator(*
this));
642 b2000::CaseList::case_list_iterator get_case_sublist_iterator(
643 const b2000::Domain* domain, b2000::CaseList::SortType st)
override {
644 return case_list_iterator(
new CaseListIterator(*
this, std::less<Case*>()));
647 b2000::CaseList::case_list_iterator get_case_sublist_iterator(
648 const NaturalBoundaryCondition* nbc, b2000::CaseList::SortType st)
override {
649 return case_list_iterator(
new CaseListIterator(*
this, std::less<Case*>()));
652 b2000::CaseList::case_list_iterator get_case_sublist_iterator(
653 const EssentialBoundaryCondition* ebc, b2000::CaseList::SortType st)
override {
654 return case_list_iterator(
new CaseListIterator(*
this, std::less<Case*>()));
657 b2000::CaseList::case_list_iterator get_case_sublist_iterator(
658 const ModelReductionBoundaryCondition* mrbc, b2000::CaseList::SortType st)
override {
659 return case_list_iterator(
new CaseListIterator(*
this, std::less<Case*>()));
662 case_list_iterator get_case_sublist_iterator(
663 const InitialCondition* ic, b2000::CaseList::SortType st)
override {
664 return case_list_iterator(
new CaseListIterator(*
this, std::less<Case*>()));
667 class CaseListIterator :
public b2000::CaseList::CaseListIterator {
669 CaseList* next()
override {
670 if (iter != list_of_case_list.end()) {
return &(*(iter++)); }
673 size_t get_number_of_case_list()
const override {
return list_of_case_list.size(); }
676 friend class b2dbv3::CaseList;
678 template <
typename CASE_COMP>
679 CaseListIterator(std::vector<Case*>& clist,
const CASE_COMP& comp) {
680 std::vector<Case*> tmp(clist);
681 std::vector<Case*>::iterator i = tmp.begin();
682 std::sort(i, tmp.end(), comp);
683 list_of_case_list.push_back(CaseList());
684 list_of_case_list.back().push_back(*i++);
685 for (; i != tmp.end(); ++i) {
686 if (comp(list_of_case_list.back().front(), *i)) {
687 list_of_case_list.push_back(CaseList());
689 list_of_case_list.back().push_back(*i);
691 iter = list_of_case_list.begin();
693 std::list<CaseList>::iterator iter;
694 std::list<CaseList> list_of_case_list;
697 friend class CaseListIterator;
699 using type_t = ObjectTypeComplete<CaseList, CaseList::type_t>;
703class CaseListRoot :
public CaseList {
705 ~CaseListRoot()
override {
706 for (std::vector<Case*>::iterator i = begin(); i != end(); ++i) { (*i)->decref_or_free(); }
711 void init(Model& model, Dictionary* cmdline_set_,
const RTable& adir,
const RTable& strat);
713 using type_t = ObjectTypeComplete<CaseListRoot, CaseList::type_t>;
#define THROW
Definition b2exception.H:198
virtual double get_stage_size(int stage=-1) const =0
virtual int get_stage_number() const =0
virtual std::string get_stage_id(int stage=-1) const =0
Definition b2dictionary.H:48
virtual void warn_on_non_used_key() const =0
T get(const std::string &key) const
Definition b2dictionary.H:121
virtual bool has_key(const std::string &key) const =0
Definition b2exception.H:131
Definition b2rtable.H:427
bool has_key(const std::string &key) const
Definition b2rtable.H:433
T get(const std::string &key) const
Definition b2rtable.H:647
void set(const std::string &key, const T &v, const bool new_key=false)
Assign a single value. If new_key is true, the key must not exist.
Definition b2rtable.H:463
Definition b2case_database.H:46
Logger & get_logger(const std::string &logger_name="")
Definition b2logging.H:829
GenericException< UnimplementedError_name > UnimplementedError
Definition b2exception.H:314