Commit 632549c9 authored by ext-calvo_p's avatar ext-calvo_p
Browse files

Merge branch '657-element-output-files-must-not-be-overwritten' into 'master'

Resolve "Element output files must not be overwritten"

Closes #657

See merge request !503
parents 759529cb c6f4883c
// ------------------------------------------------------------------------
// $RCSfile: OpalData.cpp,v $
// ------------------------------------------------------------------------
// $Revision: 1.1.1.1.4.2 $
// ------------------------------------------------------------------------
// Copyright: see Copyright.readme
// ------------------------------------------------------------------------
// //
// Class: OpalData // Class OpalData
// The global OPAL structure. // The global OPAL structure.
// The OPAL object holds all global data required for a OPAL execution. // The OPAL object holds all global data required for a OPAL execution.
// In particular it contains the main Directory, which allows retrieval
// of command objects by their name. For other data refer to the
// implementation file.
// //
// ------------------------------------------------------------------------ // Copyright (c) 200x - 2021, Paul Scherrer Institut, Villigen PSI, Switzerland
// All rights reserved
// //
// $Date: 2004/11/12 20:10:11 $ // This file is part of OPAL.
// $Author: adelmann $ //
// OPAL 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 3 of the License, or
// (at your option) any later version.
//
// You should have received a copy of the GNU General Public License
// along with OPAL. If not, see <https://www.gnu.org/licenses/>.
// //
// ------------------------------------------------------------------------
#include "AbstractObjects/OpalData.h" #include "AbstractObjects/OpalData.h"
#include "Structure/DataSink.h"
#include "Structure/BoundaryGeometry.h"
#include "AbstractObjects/Attribute.h" #include "AbstractObjects/Attribute.h"
#include "AbstractObjects/Directory.h" #include "AbstractObjects/Directory.h"
#include "AbstractObjects/Expressions.h"
#include "AbstractObjects/Object.h" #include "AbstractObjects/Object.h"
#include "AbstractObjects/ObjectFunction.h" #include "AbstractObjects/ObjectFunction.h"
#include "AbstractObjects/Table.h" #include "AbstractObjects/Table.h"
#include "AbstractObjects/ValueDefinition.h" #include "AbstractObjects/ValueDefinition.h"
#include "Algorithms/PartBunchBase.h"
#include "Attributes/Attributes.h"
#include "OpalParser/OpalParser.h"
#include "Parser/FileStream.h"
#include "Parser/StringStream.h"
#include "Structure/DataSink.h"
#include "Structure/BoundaryGeometry.h"
#include "Utilities/OpalException.h" #include "Utilities/OpalException.h"
#include "Utilities/Options.h" #include "Utilities/Options.h"
#include "Utilities/RegularExpression.h" #include "Utilities/RegularExpression.h"
#include "ValueDefinitions/RealVariable.h"
#include "ValueDefinitions/StringConstant.h"
#include <iostream> #include <iostream>
#include <list> #include <list>
#include <set> #include <set>
#include <algorithm>
// DTA
#include "AbstractObjects/Expressions.h"
#include "Attributes/Attributes.h"
#include "ValueDefinitions/RealVariable.h"
#include "ValueDefinitions/StringConstant.h"
#include "OpalParser/OpalParser.h"
#include "Parser/FileStream.h"
#include "Parser/StringStream.h"
#include "Algorithms/PartBunchBase.h"
// /DTA
#define MAX_NUM_INSTANCES 10 #define MAX_NUM_INSTANCES 10
// Class OpalData::ClearReference
// ------------------------------------------------------------------------
void OpalData::ClearReference::operator()(Object *object) const { void OpalData::ClearReference::operator()(Object *object) const {
object->clear(); object->clear();
} }
...@@ -57,7 +57,6 @@ void OpalData::ClearReference::operator()(Object *object) const { ...@@ -57,7 +57,6 @@ void OpalData::ClearReference::operator()(Object *object) const {
// Struct OpalDataImpl. // Struct OpalDataImpl.
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
struct OpalDataImpl { struct OpalDataImpl {
OpalDataImpl(); OpalDataImpl();
~OpalDataImpl(); ~OpalDataImpl();
...@@ -87,9 +86,6 @@ struct OpalDataImpl { ...@@ -87,9 +86,6 @@ struct OpalDataImpl {
// true if we restart a simulation // true if we restart a simulation
bool isRestart_m; bool isRestart_m;
// Input file name
std::string inputFn_m;
// Where to resume in a restart run // Where to resume in a restart run
int restartStep_m; int restartStep_m;
...@@ -102,6 +98,11 @@ struct OpalDataImpl { ...@@ -102,6 +98,11 @@ struct OpalDataImpl {
// dump frequency as found in restart file // dump frequency as found in restart file
int restart_dump_freq_m; int restart_dump_freq_m;
// Input file name
std::string inputFn_m;
std::set<std::string> outFiles_m;
/// Mode for writing files /// Mode for writing files
OpalData::OPENMODE openMode_m = OpalData::OPENMODE::WRITE; OpalData::OPENMODE openMode_m = OpalData::OPENMODE::WRITE;
...@@ -182,22 +183,17 @@ OpalDataImpl::~OpalDataImpl() { ...@@ -182,22 +183,17 @@ OpalDataImpl::~OpalDataImpl() {
delete bg_m; delete bg_m;
delete dataSink_m; delete dataSink_m;
mainDirectory.erase(); mainDirectory.erase();
tableDirectory.clear(); tableDirectory.clear();
exprDirectory.clear(); exprDirectory.clear();
} }
// Class OpalData
// ------------------------------------------------------------------------
bool OpalData::isInstantiated = false; bool OpalData::isInstantiated = false;
OpalData *OpalData::instance = nullptr; OpalData *OpalData::instance = nullptr;
std::stack<OpalData*> OpalData::stashedInstances; std::stack<OpalData*> OpalData::stashedInstances;
OpalData *OpalData::getInstance() { OpalData *OpalData::getInstance() {
if(!isInstantiated) { if (!isInstantiated) {
instance = new OpalData(); instance = new OpalData();
isInstantiated = true; isInstantiated = true;
return instance; return instance;
...@@ -248,7 +244,6 @@ void OpalData::incMaxTrackSteps(unsigned long long s) { ...@@ -248,7 +244,6 @@ void OpalData::incMaxTrackSteps(unsigned long long s) {
p->maxTrackSteps_m += s; p->maxTrackSteps_m += s;
} }
OpalData::OpalData() { OpalData::OpalData() {
p = new OpalDataImpl(); p = new OpalDataImpl();
} }
...@@ -321,7 +316,6 @@ void OpalData::setRestartRun(const bool &value) { ...@@ -321,7 +316,6 @@ void OpalData::setRestartRun(const bool &value) {
p->isRestart_m = value; p->isRestart_m = value;
} }
void OpalData::setRestartStep(int s) { void OpalData::setRestartStep(int s) {
p->restartStep_m = s; p->restartStep_m = s;
} }
...@@ -330,12 +324,10 @@ int OpalData::getRestartStep() { ...@@ -330,12 +324,10 @@ int OpalData::getRestartStep() {
return p->restartStep_m; return p->restartStep_m;
} }
std::string OpalData::getRestartFileName() { std::string OpalData::getRestartFileName() {
return p->restartFn_m; return p->restartFn_m;
} }
void OpalData::setRestartFileName(std::string s) { void OpalData::setRestartFileName(std::string s) {
p->restartFn_m = s; p->restartFn_m = s;
p->hasRestartFile_m = true; p->hasRestartFile_m = true;
...@@ -343,7 +335,6 @@ void OpalData::setRestartFileName(std::string s) { ...@@ -343,7 +335,6 @@ void OpalData::setRestartFileName(std::string s) {
bool OpalData::hasRestartFile() { bool OpalData::hasRestartFile() {
return p->hasRestartFile_m; return p->hasRestartFile_m;
} }
void OpalData::setRestartDumpFreq(const int &N) { void OpalData::setRestartDumpFreq(const int &N) {
...@@ -386,7 +377,6 @@ PartBunchBase<double, 3> *OpalData::getPartBunch() { ...@@ -386,7 +377,6 @@ PartBunchBase<double, 3> *OpalData::getPartBunch() {
return p->bunch_m; return p->bunch_m;
} }
bool OpalData::hasDataSinkAllocated() { bool OpalData::hasDataSinkAllocated() {
return p->hasDataSinkAllocated_m; return p->hasDataSinkAllocated_m;
} }
...@@ -463,7 +453,7 @@ double OpalData::getGlobalPhaseShift() { ...@@ -463,7 +453,7 @@ double OpalData::getGlobalPhaseShift() {
return p->gPhaseShift_m; return p->gPhaseShift_m;
} }
void OpalData::setGlobalGeometry(BoundaryGeometry *bg) { void OpalData::setGlobalGeometry(BoundaryGeometry *bg) {
p->bg_m = bg; p->bg_m = bg;
} }
...@@ -475,22 +465,19 @@ bool OpalData::hasGlobalGeometry() { ...@@ -475,22 +465,19 @@ bool OpalData::hasGlobalGeometry() {
return p->bg_m != nullptr; return p->bg_m != nullptr;
} }
void OpalData::apply(const ObjectFunction &fun) { void OpalData::apply(const ObjectFunction &fun) {
for(ObjectDir::iterator i = p->mainDirectory.begin(); for (ObjectDir::iterator i = p->mainDirectory.begin();
i != p->mainDirectory.end(); ++i) { i != p->mainDirectory.end(); ++i) {
fun(&*i->second); fun(&*i->second);
} }
} }
void OpalData::create(Object *newObject) { void OpalData::create(Object *newObject) {
// Test for existing node with same name. // Test for existing node with same name.
const std::string name = newObject->getOpalName(); const std::string name = newObject->getOpalName();
Object *oldObject = p->mainDirectory.find(name); Object *oldObject = p->mainDirectory.find(name);
if(oldObject != nullptr) { if (oldObject != nullptr) {
throw OpalException("OpalData::create()", throw OpalException("OpalData::create()",
"You cannot replace the object \"" + name + "\"."); "You cannot replace the object \"" + name + "\".");
} else { } else {
...@@ -498,19 +485,18 @@ void OpalData::create(Object *newObject) { ...@@ -498,19 +485,18 @@ void OpalData::create(Object *newObject) {
} }
} }
void OpalData::define(Object *newObject) { void OpalData::define(Object *newObject) {
// Test for existing node with same name. // Test for existing node with same name.
const std::string name = newObject->getOpalName(); const std::string name = newObject->getOpalName();
Object *oldObject = p->mainDirectory.find(name); Object *oldObject = p->mainDirectory.find(name);
if(oldObject != nullptr && oldObject != newObject) { if (oldObject != nullptr && oldObject != newObject) {
// Attempt to replace an object. // Attempt to replace an object.
if(oldObject->isBuiltin() || ! oldObject->canReplaceBy(newObject)) { if (oldObject->isBuiltin() || ! oldObject->canReplaceBy(newObject)) {
throw OpalException("OpalData::define()", throw OpalException("OpalData::define()",
"You cannot replace the object \"" + name + "\"."); "You cannot replace the object \"" + name + "\".");
} else { } else {
if(Options::info) { if (Options::info) {
INFOMSG("Replacing the object \"" << name << "\"." << endl); INFOMSG("Replacing the object \"" << name << "\"." << endl);
} }
...@@ -522,8 +508,8 @@ void OpalData::define(Object *newObject) { ...@@ -522,8 +508,8 @@ void OpalData::define(Object *newObject) {
Table *table = *i++; Table *table = *i++;
const std::string &tableName = table->getOpalName(); const std::string &tableName = table->getOpalName();
if(table->isDependent(name)) { if (table->isDependent(name)) {
if(Options::info) { if (Options::info) {
std::cerr << std::endl << "Erasing dependent table \"" std::cerr << std::endl << "Erasing dependent table \""
<< tableName << "\"." << std::endl; << tableName << "\"." << std::endl;
} }
...@@ -536,7 +522,7 @@ void OpalData::define(Object *newObject) { ...@@ -536,7 +522,7 @@ void OpalData::define(Object *newObject) {
} }
// Replace all references to this object. // Replace all references to this object.
for(ObjectDir::iterator i = p->mainDirectory.begin(); for (ObjectDir::iterator i = p->mainDirectory.begin();
i != p->mainDirectory.end(); ++i) { i != p->mainDirectory.end(); ++i) {
(*i).second->replace(oldObject, newObject); (*i).second->replace(oldObject, newObject);
} }
...@@ -552,64 +538,58 @@ void OpalData::define(Object *newObject) { ...@@ -552,64 +538,58 @@ void OpalData::define(Object *newObject) {
p->mainDirectory.insert(name, newObject); p->mainDirectory.insert(name, newObject);
// If this is a new definition of "P0", insert its definition. // If this is a new definition of "P0", insert its definition.
if(name == "P0") { if (name == "P0") {
if(ValueDefinition *p0 = dynamic_cast<ValueDefinition *>(newObject)) { if (ValueDefinition *p0 = dynamic_cast<ValueDefinition *>(newObject)) {
setP0(p0); setP0(p0);
} }
} }
} }
void OpalData::erase(const std::string &name) { void OpalData::erase(const std::string &name) {
Object *oldObject = p->mainDirectory.find(name); Object *oldObject = p->mainDirectory.find(name);
if(oldObject != nullptr) { if (oldObject != nullptr) {
// Relink all children of "this" to "this->getParent()". // Relink all children of "this" to "this->getParent()".
for(ObjectDir::iterator i = p->mainDirectory.begin(); for (ObjectDir::iterator i = p->mainDirectory.begin();
i != p->mainDirectory.end(); ++i) { i != p->mainDirectory.end(); ++i) {
Object *child = &*i->second; Object *child = &*i->second;
if(child->getParent() == oldObject) { if (child->getParent() == oldObject) {
child->setParent(oldObject->getParent()); child->setParent(oldObject->getParent());
} }
} }
// Remove the object. // Remove the object.
p->mainDirectory.erase(name); p->mainDirectory.erase(name);
} }
} }
Object *OpalData::find(const std::string &name) { Object *OpalData::find(const std::string &name) {
return p->mainDirectory.find(name); return p->mainDirectory.find(name);
} }
double OpalData::getP0() const { double OpalData::getP0() const {
static const double energy_scale = 1.0e+9; static const double energy_scale = 1.0e+9;
return p->referenceMomentum->getReal() * energy_scale; return p->referenceMomentum->getReal() * energy_scale;
} }
void OpalData::makeDirty(Object *obj) { void OpalData::makeDirty(Object *obj) {
p->modified = true; p->modified = true;
if(obj) obj->setDirty(true); if (obj) obj->setDirty(true);
} }
void OpalData::printNames(std::ostream &os, const std::string &pattern) { void OpalData::printNames(std::ostream &os, const std::string &pattern) {
int column = 0; int column = 0;
RegularExpression regex(pattern); RegularExpression regex(pattern);
os << std::endl << "Object names matching the pattern \"" os << std::endl << "Object names matching the pattern \""
<< pattern << "\":" << std::endl; << pattern << "\":" << std::endl;
for(ObjectDir::const_iterator index = p->mainDirectory.begin(); for (ObjectDir::const_iterator index = p->mainDirectory.begin();
index != p->mainDirectory.end(); ++index) { index != p->mainDirectory.end(); ++index) {
const std::string name = (*index).first; const std::string name = (*index).first;
if(! name.empty() && regex.match(name)) { if (! name.empty() && regex.match(name)) {
os << name; os << name;
if(column < 80) { if (column < 80) {
column += name.length(); column += name.length();
do { do {
...@@ -623,40 +603,34 @@ void OpalData::printNames(std::ostream &os, const std::string &pattern) { ...@@ -623,40 +603,34 @@ void OpalData::printNames(std::ostream &os, const std::string &pattern) {
} }
} }
if(column) os << std::endl; if (column) os << std::endl;
os << std::endl; os << std::endl;
} }
void OpalData::registerTable(Table *table) { void OpalData::registerTable(Table *table) {
p->tableDirectory.push_back(table); p->tableDirectory.push_back(table);
} }
void OpalData::unregisterTable(Table *table) { void OpalData::unregisterTable(Table *table) {
for(OpalDataImpl::tableIterator i = p->tableDirectory.begin(); for (OpalDataImpl::tableIterator i = p->tableDirectory.begin();
i != p->tableDirectory.end();) { i != p->tableDirectory.end();) {
OpalDataImpl::tableIterator j = i++; OpalDataImpl::tableIterator j = i++;
if(*j == table) p->tableDirectory.erase(j); if (*j == table) p->tableDirectory.erase(j);
} }
} }
void OpalData::registerExpression(AttributeBase *expr) { void OpalData::registerExpression(AttributeBase *expr) {
p->exprDirectory.insert(expr); p->exprDirectory.insert(expr);
} }
void OpalData::unregisterExpression(AttributeBase *expr) { void OpalData::unregisterExpression(AttributeBase *expr) {
p->exprDirectory.erase(expr); p->exprDirectory.erase(expr);
} }
void OpalData::setP0(ValueDefinition *p0) { void OpalData::setP0(ValueDefinition *p0) {
p->referenceMomentum = p0; p->referenceMomentum = p0;
} }
void OpalData::storeTitle(const std::string &title) { void OpalData::storeTitle(const std::string &title) {
p->itsTitle_m = title; p->itsTitle_m = title;
} }
...@@ -665,7 +639,6 @@ void OpalData::storeInputFn(const std::string &fn) { ...@@ -665,7 +639,6 @@ void OpalData::storeInputFn(const std::string &fn) {
p->inputFn_m = fn; p->inputFn_m = fn;
} }
void OpalData::printTitle(std::ostream &os) { void OpalData::printTitle(std::ostream &os) {
os << p->itsTitle_m; os << p->itsTitle_m;
} }
...@@ -688,23 +661,33 @@ std::string OpalData::getInputBasename() { ...@@ -688,23 +661,33 @@ std::string OpalData::getInputBasename() {
return fn.substr(0, pdot); return fn.substr(0, pdot);
} }
void OpalData::checkAndAddOutputFileName(const std::string &outfn) {
if (p->outFiles_m.count(outfn) == 0) {
p->outFiles_m.insert(outfn);
} else {
throw OpalException(
"OpalData::checkAndAddOutputFileName",
"Duplicate file name for output, '" + outfn + "', detected");
}
}
void OpalData::update() { void OpalData::update() {
Inform msg("OpalData "); Inform msg("OpalData ");
if(p->modified) { if (p->modified) {
// Force re-evaluation of expressions. // Force re-evaluation of expressions.
for(OpalDataImpl::exprIterator i = p->exprDirectory.begin(); for (OpalDataImpl::exprIterator i = p->exprDirectory.begin();
i != p->exprDirectory.end(); ++i) { i != p->exprDirectory.end(); ++i) {
(*i)->invalidate(); (*i)->invalidate();
} }
// Force refilling of dynamic tables. // Force refilling of dynamic tables.
for(OpalDataImpl::tableIterator i = p->tableDirectory.begin(); for (OpalDataImpl::tableIterator i = p->tableDirectory.begin();
i != p->tableDirectory.end(); ++i) { i != p->tableDirectory.end(); ++i) {
(*i)->invalidate(); (*i)->invalidate();
} }
// Update all definitions. // Update all definitions.
for(ObjectDir::iterator i = p->mainDirectory.begin(); for (ObjectDir::iterator i = p->mainDirectory.begin();
i != p->mainDirectory.end(); ++i) { i != p->mainDirectory.end(); ++i) {
(*i).second->update(); (*i).second->update();
} }
...@@ -714,7 +697,6 @@ void OpalData::update() { ...@@ -714,7 +697,6 @@ void OpalData::update() {
} }
} }
std::map<std::string, std::string> OpalData::getVariableData() {