Commit c6f4883c authored by ext-calvo_p's avatar ext-calvo_p
Browse files

Resolve "Element output files must not be overwritten"

parent 759529cb
// ------------------------------------------------------------------------
// $RCSfile: OpalData.cpp,v $
// ------------------------------------------------------------------------
// $Revision: 1.1.1.1.4.2 $
// ------------------------------------------------------------------------
// Copyright: see Copyright.readme
// ------------------------------------------------------------------------
//
// Class: OpalData
// Class OpalData
// The global OPAL structure.
// 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 $
// $Author: adelmann $
// This file is part of OPAL.
//
// 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 "Structure/DataSink.h"
#include "Structure/BoundaryGeometry.h"
#include "AbstractObjects/Attribute.h"
#include "AbstractObjects/Directory.h"
#include "AbstractObjects/Expressions.h"
#include "AbstractObjects/Object.h"
#include "AbstractObjects/ObjectFunction.h"
#include "AbstractObjects/Table.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/Options.h"
#include "Utilities/RegularExpression.h"
#include "ValueDefinitions/RealVariable.h"
#include "ValueDefinitions/StringConstant.h"
#include <iostream>
#include <list>
#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
// Class OpalData::ClearReference
// ------------------------------------------------------------------------
void OpalData::ClearReference::operator()(Object *object) const {
object->clear();
}
......@@ -57,7 +57,6 @@ void OpalData::ClearReference::operator()(Object *object) const {
// Struct OpalDataImpl.
// ------------------------------------------------------------------------
struct OpalDataImpl {
OpalDataImpl();
~OpalDataImpl();
......@@ -87,9 +86,6 @@ struct OpalDataImpl {
// true if we restart a simulation
bool isRestart_m;
// Input file name
std::string inputFn_m;
// Where to resume in a restart run
int restartStep_m;
......@@ -102,6 +98,11 @@ struct OpalDataImpl {
// dump frequency as found in restart file
int restart_dump_freq_m;
// Input file name
std::string inputFn_m;
std::set<std::string> outFiles_m;
/// Mode for writing files
OpalData::OPENMODE openMode_m = OpalData::OPENMODE::WRITE;
......@@ -182,22 +183,17 @@ OpalDataImpl::~OpalDataImpl() {
delete bg_m;
delete dataSink_m;
mainDirectory.erase();
tableDirectory.clear();
exprDirectory.clear();
}
// Class OpalData
// ------------------------------------------------------------------------
bool OpalData::isInstantiated = false;
OpalData *OpalData::instance = nullptr;
std::stack<OpalData*> OpalData::stashedInstances;
OpalData *OpalData::getInstance() {
if(!isInstantiated) {
if (!isInstantiated) {
instance = new OpalData();
isInstantiated = true;
return instance;
......@@ -248,7 +244,6 @@ void OpalData::incMaxTrackSteps(unsigned long long s) {
p->maxTrackSteps_m += s;
}
OpalData::OpalData() {
p = new OpalDataImpl();
}
......@@ -321,7 +316,6 @@ void OpalData::setRestartRun(const bool &value) {
p->isRestart_m = value;
}
void OpalData::setRestartStep(int s) {
p->restartStep_m = s;
}
......@@ -330,12 +324,10 @@ int OpalData::getRestartStep() {
return p->restartStep_m;
}
std::string OpalData::getRestartFileName() {
return p->restartFn_m;
}
void OpalData::setRestartFileName(std::string s) {
p->restartFn_m = s;
p->hasRestartFile_m = true;
......@@ -343,7 +335,6 @@ void OpalData::setRestartFileName(std::string s) {
bool OpalData::hasRestartFile() {
return p->hasRestartFile_m;
}
void OpalData::setRestartDumpFreq(const int &N) {
......@@ -386,7 +377,6 @@ PartBunchBase<double, 3> *OpalData::getPartBunch() {
return p->bunch_m;
}
bool OpalData::hasDataSinkAllocated() {
return p->hasDataSinkAllocated_m;
}
......@@ -463,7 +453,7 @@ double OpalData::getGlobalPhaseShift() {
return p->gPhaseShift_m;
}
void OpalData::setGlobalGeometry(BoundaryGeometry *bg) {
void OpalData::setGlobalGeometry(BoundaryGeometry *bg) {
p->bg_m = bg;
}
......@@ -475,22 +465,19 @@ bool OpalData::hasGlobalGeometry() {
return p->bg_m != nullptr;
}
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) {
fun(&*i->second);
}
}
void OpalData::create(Object *newObject) {
// Test for existing node with same name.
const std::string name = newObject->getOpalName();
Object *oldObject = p->mainDirectory.find(name);
if(oldObject != nullptr) {
if (oldObject != nullptr) {
throw OpalException("OpalData::create()",
"You cannot replace the object \"" + name + "\".");
} else {
......@@ -498,19 +485,18 @@ void OpalData::create(Object *newObject) {
}
}
void OpalData::define(Object *newObject) {
// Test for existing node with same name.
const std::string name = newObject->getOpalName();
Object *oldObject = p->mainDirectory.find(name);
if(oldObject != nullptr && oldObject != newObject) {
if (oldObject != nullptr && oldObject != newObject) {
// Attempt to replace an object.
if(oldObject->isBuiltin() || ! oldObject->canReplaceBy(newObject)) {
if (oldObject->isBuiltin() || ! oldObject->canReplaceBy(newObject)) {
throw OpalException("OpalData::define()",
"You cannot replace the object \"" + name + "\".");
} else {
if(Options::info) {
if (Options::info) {
INFOMSG("Replacing the object \"" << name << "\"." << endl);
}
......@@ -522,8 +508,8 @@ void OpalData::define(Object *newObject) {
Table *table = *i++;
const std::string &tableName = table->getOpalName();
if(table->isDependent(name)) {
if(Options::info) {
if (table->isDependent(name)) {
if (Options::info) {
std::cerr << std::endl << "Erasing dependent table \""
<< tableName << "\"." << std::endl;
}
......@@ -536,7 +522,7 @@ void OpalData::define(Object *newObject) {
}
// 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).second->replace(oldObject, newObject);
}
......@@ -552,64 +538,58 @@ void OpalData::define(Object *newObject) {
p->mainDirectory.insert(name, newObject);
// If this is a new definition of "P0", insert its definition.
if(name == "P0") {
if(ValueDefinition *p0 = dynamic_cast<ValueDefinition *>(newObject)) {
if (name == "P0") {
if (ValueDefinition *p0 = dynamic_cast<ValueDefinition *>(newObject)) {
setP0(p0);
}
}
}
void OpalData::erase(const std::string &name) {
Object *oldObject = p->mainDirectory.find(name);
if(oldObject != nullptr) {
if (oldObject != nullptr) {
// 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) {
Object *child = &*i->second;
if(child->getParent() == oldObject) {
if (child->getParent() == oldObject) {
child->setParent(oldObject->getParent());
}
}
// Remove the object.
p->mainDirectory.erase(name);
}
}
Object *OpalData::find(const std::string &name) {
return p->mainDirectory.find(name);
}
double OpalData::getP0() const {
static const double energy_scale = 1.0e+9;
return p->referenceMomentum->getReal() * energy_scale;
}
void OpalData::makeDirty(Object *obj) {
p->modified = true;
if(obj) obj->setDirty(true);
if (obj) obj->setDirty(true);
}
void OpalData::printNames(std::ostream &os, const std::string &pattern) {
int column = 0;
RegularExpression regex(pattern);
os << std::endl << "Object names matching the pattern \""
<< pattern << "\":" << std::endl;
for(ObjectDir::const_iterator index = p->mainDirectory.begin();
for (ObjectDir::const_iterator index = p->mainDirectory.begin();
index != p->mainDirectory.end(); ++index) {
const std::string name = (*index).first;
if(! name.empty() && regex.match(name)) {
if (! name.empty() && regex.match(name)) {
os << name;
if(column < 80) {
if (column < 80) {
column += name.length();
do {
......@@ -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;
}
void OpalData::registerTable(Table *table) {
p->tableDirectory.push_back(table);
}
void OpalData::unregisterTable(Table *table) {
for(OpalDataImpl::tableIterator i = p->tableDirectory.begin();
for (OpalDataImpl::tableIterator i = p->tableDirectory.begin();
i != p->tableDirectory.end();) {
OpalDataImpl::tableIterator j = i++;
if(*j == table) p->tableDirectory.erase(j);
if (*j == table) p->tableDirectory.erase(j);
}
}
void OpalData::registerExpression(AttributeBase *expr) {
p->exprDirectory.insert(expr);
}
void OpalData::unregisterExpression(AttributeBase *expr) {
p->exprDirectory.erase(expr);
}
void OpalData::setP0(ValueDefinition *p0) {
p->referenceMomentum = p0;
}
void OpalData::storeTitle(const std::string &title) {
p->itsTitle_m = title;
}
......@@ -665,7 +639,6 @@ void OpalData::storeInputFn(const std::string &fn) {
p->inputFn_m = fn;
}
void OpalData::printTitle(std::ostream &os) {
os << p->itsTitle_m;
}
......@@ -688,23 +661,33 @@ std::string OpalData::getInputBasename() {
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() {
Inform msg("OpalData ");
if(p->modified) {
if (p->modified) {
// 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)->invalidate();
}
// 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)->invalidate();
}
// Update all definitions.
for(ObjectDir::iterator i = p->mainDirectory.begin();
for (ObjectDir::iterator i = p->mainDirectory.begin();
i != p->mainDirectory.end(); ++i) {
(*i).second->update();
}
......@@ -714,7 +697,6 @@ void OpalData::update() {
}
}
std::map<std::string, std::string> OpalData::getVariableData() {
std::map<std::string, std::string> udata;
std::vector<std::string> uvars = this->getVariableNames();
......@@ -738,7 +720,7 @@ std::map<std::string, std::string> OpalData::getVariableData() {
std::vector<std::string> OpalData::getVariableNames() {
std::vector<std::string> result;
for(ObjectDir::const_iterator index = p->mainDirectory.begin();
for (ObjectDir::const_iterator index = p->mainDirectory.begin();
index != p->mainDirectory.end(); ++index) {
std::string tmpName = (*index).first;
if (!tmpName.empty()) {
......@@ -776,4 +758,4 @@ void OpalData::storeArguments(int argc, char *argv[]) {
std::vector<std::string> OpalData::getArguments() {
return p->arguments_m;
}
\ No newline at end of file
}
#ifndef OPAL_OpalData_HH
#define OPAL_OpalData_HH
// ------------------------------------------------------------------------
// $RCSfile: OpalData.h,v $
// ------------------------------------------------------------------------
// $Revision: 1.1.1.1.4.2 $
// ------------------------------------------------------------------------
// Copyright: see Copyright.readme
// ------------------------------------------------------------------------
//
// Class: OpalData
// Class OpalData
// The global OPAL structure.
// 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 $
// $Author: adelmann $
// This file is part of OPAL.
//
// ------------------------------------------------------------------------
// 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/>.
//
#ifndef OPAL_OpalData_HH
#define OPAL_OpalData_HH
#include "AbstractObjects/ObjectFunction.h"
#include <iosfwd>
......@@ -39,14 +44,8 @@ class BoundaryGeometry;
typedef std::pair<std::string, double > MaxPhasesT;
typedef std::map<double, double> energyEvolution_t;
// Class OpalData
// ------------------------------------------------------------------------
/// The global OPAL structure.
// The OPAL object holds all global data required for an 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.
/// The global OPAL structure.
class OpalData {
public:
......@@ -191,6 +190,9 @@ public:
/// store opals input filename
void storeInputFn(const std::string &fn);
/// checks the output file names of all items to avoid duplicates
void checkAndAddOutputFileName(const std::string &outfn);
/// get opals restart h5 format filename
std::string getRestartFileName();
......@@ -241,7 +243,6 @@ public:
///
BoundaryGeometry *getGlobalGeometry();
bool hasGlobalGeometry();
void setMaxPhase(std::string elName, double phi);
......
......@@ -136,6 +136,20 @@ void ElementBase::setName(const std::string &name) {
}
void ElementBase::setOutputFN(const std::string fn) {
outputfn_m = fn;
}
std::string ElementBase::getOutputFN() const {
if (outputfn_m.empty()) {
return getName();
} else {
return outputfn_m.substr(0, outputfn_m.rfind("."));
}
}
double ElementBase::getAttribute(const std::string &aKey) const {
const ConstChannel *aChannel = getConstChannel(aKey);
......
......@@ -621,18 +621,4 @@ int ElementBase::getRequiredNumberOfTimeSteps() const {
return 10;
}
inline
void ElementBase::setOutputFN(const std::string fn) {
outputfn_m = fn;
}
inline
std::string ElementBase::getOutputFN() const {
if (outputfn_m.empty()) {
return getName();
} else {
return outputfn_m.substr(0, outputfn_m.rfind("."));
}
}
#endif // CLASSIC_ElementBase_HH
......@@ -17,9 +17,7 @@
//
#include "Structure/LossDataSink.h"
#include <boost/filesystem.hpp>
#include <cmath>
#include "AbstractObjects/OpalData.h"
#include "Algorithms/DistributionMoments.h"
#include "Message/GlobalComm.h"
#include "OPALconfig.h"
......@@ -28,6 +26,10 @@
#include "Utilities/Util.h"
#include "Utility/IpplInfo.h"
#include <boost/filesystem.hpp>
#include <cmath>
extern Inform* gmsg;
#define WRITE_FILEATTRIB_STRING( attribute, value ) { \
......@@ -176,6 +178,15 @@ LossDataSink::LossDataSink(std::string outfn, bool hdf5Save, CollectionType coll
particles_m.clear();
turnNumber_m.clear();
bunchNumber_m.clear();
if (h5hut_mode_m && !Options::enableHDF5) {
throw GeneralClassicException(
"LossDataSink::LossDataSink",
"You must select an OPTION to save Loss data files\n"
"Please, choose 'ENABLEHDF5=TRUE' or 'ASCIIDUMP=TRUE'");
}
OpalData::getInstance()->checkAndAddOutputFileName(outputName_m);
}
LossDataSink::LossDataSink(const LossDataSink &rhs):
......@@ -309,7 +320,6 @@ void LossDataSink::save(unsigned int numSets, OpalData::OPENMODE openMode) {
namespace fs = boost::filesystem;
if (h5hut_mode_m) {
if (!Options::enableHDF5) return;
fn_m = outputName_m + std::string(".h5");
*gmsg << level2 << "Save " << fn_m << endl;
......
#include "PeakFinder.h"
#include <algorithm>
#include <cmath>
#include <iterator>
//
// Class PeakFinder
// Find peaks of radial profile.
// It computes a histogram based on the radial distribution of the particle
// bunch. After that all peaks of the histogram are searched.
// The radii are written in ASCII format to a file.
// This class is used for the cyclotron probe element.
//
// Copyright (c) 2017 - 2021, Matthias Frey, Jochem Snuverink, Paul Scherrer Institut, Villigen PSI, Switzerland
// All rights reserved
//
// This file is part of OPAL.
//
// 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 "Structure/PeakFinder.h"
#include "AbstractObjects/OpalData.h"