Program Listing for File parameter_set.cpp¶
↰ Return to documentation for file (src_qcm/parameter_set.cpp)
#include <fstream>
#include <set>
#include "parameter_set.hpp"
#include "parser.hpp"
#include "global_parameter.hpp"
#include "lattice_model.hpp"
#define FIELD_WIDTH 26
//==============================================================================
// implementation of struct 'parameter'
parameter::parameter(const string& _name, int _label, double v)
: name(_name), label(_label), value(v), ref(), multiplier(1.0)
{
if(name == "") qcm_throw("parameter must have a name");
}
void parameter::check_name(const string &str)
{
size_t pos = str.rfind(separator);
if(pos != string::npos) qcm_throw("The character '" + string(1,separator) + "' is forbidden in parameter names ("+str+")");
}
//==============================================================================
// implementation of struct 'parameter_set'
bool parameter_set::parameter_set_defined = false;
parameter_set::parameter_set()
{
}
parameter_set::parameter_set(shared_ptr<lattice_model> _model, vector<pair<string, double>> values, vector<tuple<string, double, string>> equiv)
: model(_model)
{
if(parameter_set_defined){
qcm_throw("parameter_set() can only be called once!");
}
parameter_set_defined = true;
model->close_model(); // once the parameters are initialized, the model can no longer be modified
set<string> param_list;
for(auto& [name, value] : values){
check_existence(name);
if(param_list.find(name) != param_list.end()){
qcm_throw(name+" has been assigned more than once. This is forbidden for safety reasons.");
}
param_list.insert(name);
auto P = model->name_and_label(name);
param[P.first] = make_shared<parameter>(name, P.second, value);
}
for(auto& [name1, mult, name2] : equiv){
check_existence(name1);
if(param_list.find(name1) != param_list.end()){
qcm_throw(name1+" has been assigned more than once. This is forbidden for safety reasons.");
}
param_list.insert(name1);
auto P = model->name_and_label(name1);
if(param.find(name2) == param.end()){
qcm_throw(name2+" has not been assigned so far and cannot be used as a reference");
}
auto X = make_shared<parameter>(P.first, P.second, mult*param.at(name2)->value);
param[name1] = X;
X->ref = param[name2];
X->multiplier = mult;
param[name2]->deref.insert(X);
}
// completing with implicit dependent operators
set<shared_ptr<parameter>> param_tmp;
for(auto& [pname, p] : param){
if(p->label == 0){
auto& op = model->term.at(pname);
for(int s=0; s<model->systems.size(); s++){
int c = model->systems[s].clus;
if(!op->in_cluster[c]) continue;
string name = pname+parameter::separator+to_string(s+1);
if(param.find(name) != param.end()) continue;
auto tmp = make_shared<parameter>(name, s+1, p->value);
param_tmp.insert(tmp);
tmp->ref = p;
}
}
}
for(auto& x : param_tmp){
param[x->name] = x;
x->ref->deref.insert(x);
}
}
void parameter_set::set_value(const string& name, const double &v)
{
if(param.find(name) == param.end()) qcm_throw("parameter "+name+" does not exist! impossible to set value");
if(param[name]->ref != nullptr){
cout << "WARNING: parameter " << name << " is dependent; set_value() ignored." << endl;
return;
}
set_value(param[name], v);
}
void parameter_set::set_value(shared_ptr<parameter> P, const double &v)
{
P->value = v;
for(auto& x : P->deref){
set_value(x, v*x->multiplier);
}
}
void parameter_set::set_multiplier(const string& name, const double &v)
{
if(param.find(name) == param.end()) qcm_throw("parameter "+name+" does not exist! impossible to set multiplier");
if(param[name]->ref == nullptr)
qcm_throw("parameter "+name+" is independent! impossible to set multiplier");
param[name]->multiplier = v;
}
void parameter_set::check_existence(string& name)
{
auto P = model->name_and_label(name, true);
if(P.second){
if(!ED::exists(model->systems[P.second-1].name, P.first)) qcm_throw("operator "+name+" does not exist in model");
}
}
map<string,double> parameter_set::value_map()
{
map<string,double> X;
for(auto& [name, p] : param){
X[name] = p->value;
}
return X;
}
void parameter_set::print(ostream& out)
{
out << setprecision(10);
for(auto& [name, p] : param){
if(p->ref!=nullptr){
ostringstream sout;
sout << name << " := " << p->multiplier << " x " << p->ref->name;
out << left << setw(FIELD_WIDTH) << sout.str();
}
else{
ostringstream sout; sout << name << " = " << p->value;
out << left << setw(FIELD_WIDTH) << sout.str();
}
if(p->deref.size()){
auto it = p->deref.begin();
out << "--> " << (*it)->name;
it++;
while(it != p->deref.end()){
out << ", " << (*it)->name;
it++;
}
}
out << endl;
}
}
bool parameter_set::is_dependent(const string &S)
{
if(param.find(S)==param.end())
qcm_throw(S + " is not in the set of parameters. Its dependence cannot even be checked!");
return (param.at(S)->ref != nullptr);
}
void parameter_set::CDMFT_variational_set(const vector<vector<string>>& vars) {
for(int c=0; c<vars.size(); c++){
for(auto& s : vars[c]){
if(param.find(s)==param.end())
qcm_throw(s + " is not in the set of parameters: it cannot be a variational parameter.");
if(is_dependent(s)) qcm_throw("parameter "+s+" is dependent. Cannot be a variational parameter.");
}
}
CDMFT_variational = vars;
}