diff --git a/Common/include/CConfig.hpp b/Common/include/CConfig.hpp
index b5407e71eeb..0afaff13ddc 100644
--- a/Common/include/CConfig.hpp
+++ b/Common/include/CConfig.hpp
@@ -700,6 +700,7 @@ class CConfig {
unsigned long StartConv_Iter; /*!< \brief Start convergence criteria at iteration. */
su2double Cauchy_Eps; /*!< \brief Epsilon used for the convergence. */
bool Restart, /*!< \brief Restart solution (for direct, adjoint, and linearized problems).*/
+ Wrt_Restart_Compact, /*!< \brief Write compact restart files with minimum nr. of variables. */
Read_Binary_Restart, /*!< \brief Read binary SU2 native restart files.*/
Wrt_Restart_Overwrite, /*!< \brief Overwrite restart files or append iteration number.*/
Wrt_Surface_Overwrite, /*!< \brief Overwrite surface output files or append iteration number.*/
@@ -5503,6 +5504,12 @@ class CConfig {
*/
bool GetRead_Binary_Restart(void) const { return Read_Binary_Restart; }
+ /*!
+ * \brief Flag for whether restart files contain only necessary variables.
+ * \return Flag TRUE
then the code will write compact restart files.
+ */
+ bool GetWrt_Restart_Compact(void) const { return Wrt_Restart_Compact; }
+
/*!
* \brief Flag for whether restart solution files are overwritten.
* \return Flag for overwriting. If Flag=false, iteration nr is appended to filename
diff --git a/Common/src/CConfig.cpp b/Common/src/CConfig.cpp
index 757388c9cc8..1ec938832e2 100644
--- a/Common/src/CConfig.cpp
+++ b/Common/src/CConfig.cpp
@@ -1172,6 +1172,8 @@ void CConfig::SetConfig_Options() {
/*!\brief RESTART_SOL \n DESCRIPTION: Restart solution from native solution file \n Options: NO, YES \ingroup Config */
addBoolOption("RESTART_SOL", Restart, false);
+ /*!\brief WRT_RESTART_COMPACT \n DESCRIPTION: Minimize the size of restart files \n Options: NO, YES \ingroup Config */
+ addBoolOption("WRT_RESTART_COMPACT", Wrt_Restart_Compact, true);
/*!\brief BINARY_RESTART \n DESCRIPTION: Read binary SU2 native restart files. \n Options: YES, NO \ingroup Config */
addBoolOption("READ_BINARY_RESTART", Read_Binary_Restart, true);
/*!\brief WRT_RESTART_OVERWRITE \n DESCRIPTION: overwrite restart files or append iteration number. \n Options: YES, NO \ingroup Config */
diff --git a/SU2_CFD/include/output/COutput.hpp b/SU2_CFD/include/output/COutput.hpp
index a549a6c5541..14b0bbec9b6 100644
--- a/SU2_CFD/include/output/COutput.hpp
+++ b/SU2_CFD/include/output/COutput.hpp
@@ -241,15 +241,16 @@ class COutput {
/*----------------------------- Volume output ----------------------------*/
- CParallelDataSorter* volumeDataSorter; //!< Volume data sorter
- CParallelDataSorter* surfaceDataSorter; //!< Surface data sorter
+ CParallelDataSorter* volumeDataSorter; //!< Volume data sorter.
+ CParallelDataSorter* volumeDataSorterCompact; //!< Volume data sorter for compact files.
+ CParallelDataSorter* surfaceDataSorter; //!< Surface data sorter.
- vector volumeFieldNames; //!< Vector containing the volume field names
- unsigned short nVolumeFields; //!< Number of fields in the volume output
+ vector volumeFieldNames; //!< Vector containing the volume field names.
+ vector requiredVolumeFieldNames; //!< Vector containing the minimum required volume field names.
- string volumeFilename, //!< Volume output filename
- surfaceFilename, //!< Surface output filename
- restartFilename; //!< Restart output filename
+ string volumeFilename, //!< Volume output filename.
+ surfaceFilename, //!< Surface output filename.
+ restartFilename; //!< Restart output filename.
/** \brief Structure to store information for a volume output field.
*
@@ -259,40 +260,48 @@ class COutput {
/*! \brief The name of the field, i.e. the name that is printed in the file header.*/
string fieldName;
/*! \brief This value identifies the position of the values of this field at each node in the ::Local_Data array. */
- short offset;
+ short offset = -1;
+ /*! \brief This offset is used for the compact formulation. */
+ short offsetCompact = -1;
/*! \brief The group this field belongs to. */
string outputGroup;
- /*! \brief String containing the description of the field */
+ /*! \brief String containing the description of the field. */
string description;
/*! \brief Default constructor. */
- VolumeOutputField () {}
+ VolumeOutputField() = default;
/*! \brief Constructor to initialize all members. */
- VolumeOutputField(string fieldName_, int offset_, string volumeOutputGroup_, string description_):
- fieldName(std::move(fieldName_)), offset(std::move(offset_)),
- outputGroup(std::move(volumeOutputGroup_)), description(std::move(description_)){}
+ VolumeOutputField(string fieldName_, string volumeOutputGroup_, string description_):
+ fieldName(std::move(fieldName_)),
+ outputGroup(std::move(volumeOutputGroup_)),
+ description(std::move(description_)) {}
};
/*! \brief Associative map to access data stored in the volume output fields by a string identifier. */
- std::map volumeOutput_Map;
+ std::map volumeOutput_Map;
/*! \brief Vector that contains the keys of the ::volumeOutput_Map in the order of their insertion. */
- std::vector volumeOutput_List;
-
- /*! \brief Vector to cache the positions of the field in the data array */
- std::vector fieldIndexCache;
- /*! \brief Current value of the cache index */
- unsigned short cachePosition;
- /*! \brief Boolean to store whether the field index cache should be build. */
- bool buildFieldIndexCache;
- /*! \brief Vector to cache the positions of the field in the data array */
- std::vector fieldGetIndexCache;
- /*! \brief Current value of the cache index */
- unsigned short curGetFieldIndex;
+ std::vector volumeOutput_List;
+
+ /*! \brief Whether the field index caches should be build. */
+ bool buildFieldIndexCache;
+
+ /*! \brief Vectors to cache the positions of the fields in the data array. */
+ std::vector fieldIndexCache, fieldIndexCacheCompact;
+ /*! \brief Current value of the cache indices. */
+ unsigned short cachePosition;
+
+ /*! \brief Vector to cache the positions of the field in the data array. */
+ std::vector fieldGetIndexCache;
+ /*! \brief Current value of the cache index. */
+ unsigned short curGetFieldIndex;
/*! \brief Requested volume field names in the config file. */
std::vector requestedVolumeFields;
/*! \brief Number of requested volume field names in the config file. */
unsigned short nRequestedVolumeFields;
+ /*! \brief Minimum required volume fields for restart file. */
+ const std::vector restartVolumeFields = {"COORDINATES", "SOLUTION", "SENSITIVITY", "GRID_VELOCITY"};
+
/*----------------------------- Convergence monitoring ----------------------------*/
su2double cauchyValue, /*!< \brief Summed value of the convergence indicator. */
@@ -736,8 +745,9 @@ class COutput {
* \param[in] groupname - The name of the group this field belongs to.
* \param[in] description - Description of the volume field.
*/
- inline void AddVolumeOutput(string name, string field_name, string groupname, string description){
- volumeOutput_Map[name] = VolumeOutputField(field_name, -1, groupname, description);
+ inline void AddVolumeOutput(const string& name, const string& field_name,
+ const string& group_name, const string& description) {
+ volumeOutput_Map[name] = VolumeOutputField(field_name, group_name, description);
volumeOutput_List.push_back(name);
}
@@ -959,14 +969,14 @@ class COutput {
/*!
* \brief Sets the turboperformance screen output
- * \param[in] TurboPerf - Turboperformance class
+ * \param[in] TurboPerf - Turboperformance class
* \param[in] config - Definition of the particular problem
* \param[in] TimeIter - Index of the current time-step
* \param[in] OuterIter - Index of current outer iteration
* \param[in] InnerIter - Index of current inner iteration
*/
inline virtual void SetTurboPerformance_Output(std::shared_ptr TurboPerf, CConfig *config, unsigned long TimeIter, unsigned long OuterIter, unsigned long InnerIter) {}
-
+
/*!
* \brief Sets the multizone turboperformacne screen output
* \param[in] TurboStagePerf - Stage turboperformance class
@@ -982,7 +992,7 @@ class COutput {
* \param[in] config - Definition of the particular problem
*/
inline virtual void LoadTurboHistoryData(std::shared_ptr TurboStagePerf, std::shared_ptr TurboPerf, CConfig *config) {}
-
+
/*!
* \brief Write the kinematic and thermodynamic variables at each spanwise division
* \param[in] solver - The container hold all solution data
diff --git a/SU2_CFD/include/output/filewriter/CParallelDataSorter.hpp b/SU2_CFD/include/output/filewriter/CParallelDataSorter.hpp
index da2f6a1f3bf..4882165a770 100644
--- a/SU2_CFD/include/output/filewriter/CParallelDataSorter.hpp
+++ b/SU2_CFD/include/output/filewriter/CParallelDataSorter.hpp
@@ -108,7 +108,8 @@ class CParallelDataSorter{
int nSends, //!< Number of sends
nRecvs; //!< Number of receives
- vector fieldNames; //!< Vector with names of the output fields
+ vector fieldNames; //!< Vector with names of all the output fields
+ vector requiredFieldNames; //!< Vector with names of the required output fields that we write to file
unsigned short nDim; //!< Spatial dimension of the data
@@ -340,6 +341,22 @@ class CParallelDataSorter{
return fieldNames;
}
+ /*!
+ * \brief Get the vector containing the names of the required output fields
+ * \return Vector of strings containing the required field names
+ */
+ const vector& GetRequiredFieldNames() const{
+ return requiredFieldNames;
+ }
+
+ /*!
+ * \brief Set the vector of required output fields.
+ * \return None.
+ */
+ void SetRequiredFieldNames(const vector& req_field_names) {
+ requiredFieldNames = req_field_names;
+ }
+
/*!
* \brief Get the spatial dimension
* \return The spatial dimension
diff --git a/SU2_CFD/src/output/CAdjFlowCompOutput.cpp b/SU2_CFD/src/output/CAdjFlowCompOutput.cpp
index 108856156e7..f1e492e1a37 100644
--- a/SU2_CFD/src/output/CAdjFlowCompOutput.cpp
+++ b/SU2_CFD/src/output/CAdjFlowCompOutput.cpp
@@ -61,7 +61,7 @@ CAdjFlowCompOutput::CAdjFlowCompOutput(CConfig *config, unsigned short nDim) : C
if (find(requestedVolumeFields.begin(), requestedVolumeFields.end(), string("SENSITIVITY")) == requestedVolumeFields.end()) {
requestedVolumeFields.emplace_back("SENSITIVITY");
- nRequestedVolumeFields ++;
+ nRequestedVolumeFields++;
}
stringstream ss;
diff --git a/SU2_CFD/src/output/CAdjFlowIncOutput.cpp b/SU2_CFD/src/output/CAdjFlowIncOutput.cpp
index be86c12a494..3fff6de99e5 100644
--- a/SU2_CFD/src/output/CAdjFlowIncOutput.cpp
+++ b/SU2_CFD/src/output/CAdjFlowIncOutput.cpp
@@ -67,7 +67,7 @@ CAdjFlowIncOutput::CAdjFlowIncOutput(CConfig *config, unsigned short nDim) : CAd
if (find(requestedVolumeFields.begin(), requestedVolumeFields.end(), string("SENSITIVITY")) == requestedVolumeFields.end()) {
requestedVolumeFields.emplace_back("SENSITIVITY");
- nRequestedVolumeFields ++;
+ nRequestedVolumeFields++;
}
stringstream ss;
diff --git a/SU2_CFD/src/output/CAdjHeatOutput.cpp b/SU2_CFD/src/output/CAdjHeatOutput.cpp
index 578175fccad..9c8a85e2f5d 100644
--- a/SU2_CFD/src/output/CAdjHeatOutput.cpp
+++ b/SU2_CFD/src/output/CAdjHeatOutput.cpp
@@ -58,7 +58,7 @@ CAdjHeatOutput::CAdjHeatOutput(CConfig *config, unsigned short nDim) : COutput(c
if (find(requestedVolumeFields.begin(), requestedVolumeFields.end(), string("SENSITIVITY")) == requestedVolumeFields.end()) {
requestedVolumeFields.emplace_back("SENSITIVITY");
- nRequestedVolumeFields ++;
+ nRequestedVolumeFields++;
}
stringstream ss;
diff --git a/SU2_CFD/src/output/CElasticityOutput.cpp b/SU2_CFD/src/output/CElasticityOutput.cpp
index a2abc4e6d12..1af62426cce 100644
--- a/SU2_CFD/src/output/CElasticityOutput.cpp
+++ b/SU2_CFD/src/output/CElasticityOutput.cpp
@@ -235,21 +235,20 @@ void CElasticityOutput::SetVolumeOutputFields(CConfig *config){
// Grid coordinates
AddVolumeOutput("COORD-X", "x", "COORDINATES", "x-component of the coordinate vector");
AddVolumeOutput("COORD-Y", "y", "COORDINATES", "y-component of the coordinate vector");
- if (nDim == 3)
- AddVolumeOutput("COORD-Z", "z", "COORDINATES", "z-component of the coordinate vector");
+ if (nDim == 3) AddVolumeOutput("COORD-Z", "z", "COORDINATES", "z-component of the coordinate vector");
AddVolumeOutput("DISPLACEMENT-X", "Displacement_x", "SOLUTION", "x-component of the displacement vector");
AddVolumeOutput("DISPLACEMENT-Y", "Displacement_y", "SOLUTION", "y-component of the displacement vector");
if (nDim == 3) AddVolumeOutput("DISPLACEMENT-Z", "Displacement_z", "SOLUTION", "z-component of the displacement vector");
- if(dynamic){
- AddVolumeOutput("VELOCITY-X", "Velocity_x", "VELOCITY", "x-component of the velocity vector");
- AddVolumeOutput("VELOCITY-Y", "Velocity_y", "VELOCITY", "y-component of the velocity vector");
- if (nDim == 3) AddVolumeOutput("VELOCITY-Z", "Velocity_z", "VELOCITY", "z-component of the velocity vector");
+ if (dynamic) {
+ AddVolumeOutput("VELOCITY-X", "Velocity_x", "SOLUTION", "x-component of the velocity vector");
+ AddVolumeOutput("VELOCITY-Y", "Velocity_y", "SOLUTION", "y-component of the velocity vector");
+ if (nDim == 3) AddVolumeOutput("VELOCITY-Z", "Velocity_z", "SOLUTION", "z-component of the velocity vector");
- AddVolumeOutput("ACCELERATION-X", "Acceleration_x", "ACCELERATION", "x-component of the acceleration vector");
- AddVolumeOutput("ACCELERATION-Y", "Acceleration_y", "ACCELERATION", "y-component of the acceleration vector");
- if (nDim == 3) AddVolumeOutput("ACCELERATION-Z", "Acceleration_z", "ACCELERATION", "z-component of the acceleration vector");
+ AddVolumeOutput("ACCELERATION-X", "Acceleration_x", "SOLUTION", "x-component of the acceleration vector");
+ AddVolumeOutput("ACCELERATION-Y", "Acceleration_y", "SOLUTION", "y-component of the acceleration vector");
+ if (nDim == 3) AddVolumeOutput("ACCELERATION-Z", "Acceleration_z", "SOLUTION", "z-component of the acceleration vector");
}
AddVolumeOutput("STRESS-XX", "Sxx", "STRESS", "x-component of the normal stress vector");
diff --git a/SU2_CFD/src/output/CFlowCompOutput.cpp b/SU2_CFD/src/output/CFlowCompOutput.cpp
index e460109c8b5..d3c76e75a36 100644
--- a/SU2_CFD/src/output/CFlowCompOutput.cpp
+++ b/SU2_CFD/src/output/CFlowCompOutput.cpp
@@ -61,7 +61,7 @@ CFlowCompOutput::CFlowCompOutput(const CConfig *config, unsigned short nDim) : C
auto notFound = requestedVolumeFields.end();
if (find(requestedVolumeFields.begin(), notFound, string("GRID_VELOCITY")) == notFound) {
requestedVolumeFields.emplace_back("GRID_VELOCITY");
- nRequestedVolumeFields ++;
+ nRequestedVolumeFields++;
}
}
@@ -219,7 +219,7 @@ void CFlowCompOutput::SetVolumeOutputFields(CConfig *config){
AddVolumeOutput("DENSITY", "Density", "SOLUTION", "Density");
AddVolumeOutput("MOMENTUM-X", "Momentum_x", "SOLUTION", "x-component of the momentum vector");
AddVolumeOutput("MOMENTUM-Y", "Momentum_y", "SOLUTION", "y-component of the momentum vector");
-
+
if (nDim == 3)
AddVolumeOutput("MOMENTUM-Z", "Momentum_z", "SOLUTION", "z-component of the momentum vector");
AddVolumeOutput("ENERGY", "Energy", "SOLUTION", "Energy");
@@ -241,7 +241,7 @@ void CFlowCompOutput::SetVolumeOutputFields(CConfig *config){
AddVolumeOutput("PRESSURE_COEFF", "Pressure_Coefficient", "PRIMITIVE", "Pressure coefficient");
AddVolumeOutput("VELOCITY-X", "Velocity_x", "PRIMITIVE", "x-component of the velocity vector");
AddVolumeOutput("VELOCITY-Y", "Velocity_y", "PRIMITIVE", "y-component of the velocity vector");
-
+
if (nDim == 3)
AddVolumeOutput("VELOCITY-Z", "Velocity_z", "PRIMITIVE", "z-component of the velocity vector");
@@ -525,7 +525,7 @@ void CFlowCompOutput::SetTurboPerformance_Output(std::shared_ptr T
for (unsigned short iZone = 0; iZone <= config->GetnZone()-1; iZone++) {
auto nSpan = config->GetnSpan_iZones(iZone);
- const auto& BladePerf = BladePerformance.at(iZone).at(nSpan);
+ const auto& BladePerf = BladePerformance.at(iZone).at(nSpan);
TurboInOut<<" BLADE ROW INDEX "<GetInletState().GetVelocity()[iDim]*config[ZONE_0]->GetVelocity_Ref();
}
file.width(30); file << BladePerf->GetInletState().GetVelocityValue()*config[ZONE_0]->GetVelocity_Ref();
- // This captures NaNs
+ // This captures NaNs
if(isnan(BladePerf->GetInletState().GetAbsFlowAngle())){
file.width(30); file << "0.0000";
}
@@ -792,11 +792,11 @@ void CFlowCompOutput::WriteTurboSpanwisePerformance(std::shared_ptr 1) {
- spanwise_performance_filename.append("_" + std::to_string(val_iZone) + ".dat");
- } else {
- spanwise_performance_filename.append(".dat");
- }
+ if (nZone > 1) {
+ spanwise_performance_filename.append("_" + std::to_string(val_iZone) + ".dat");
+ } else {
+ spanwise_performance_filename.append(".dat");
+ }
file.open (spanwise_performance_filename.data(), ios::out | ios::trunc);
file.setf(ios::scientific);
file.precision(12);
diff --git a/SU2_CFD/src/output/CFlowIncOutput.cpp b/SU2_CFD/src/output/CFlowIncOutput.cpp
index eeffb6a3486..1f4c0809d1b 100644
--- a/SU2_CFD/src/output/CFlowIncOutput.cpp
+++ b/SU2_CFD/src/output/CFlowIncOutput.cpp
@@ -70,7 +70,7 @@ CFlowIncOutput::CFlowIncOutput(CConfig *config, unsigned short nDim) : CFlowOutp
auto notFound = requestedVolumeFields.end();
if (find(requestedVolumeFields.begin(), notFound, string("GRID_VELOCITY")) == notFound) {
requestedVolumeFields.emplace_back("GRID_VELOCITY");
- nRequestedVolumeFields ++;
+ nRequestedVolumeFields++;
}
}
diff --git a/SU2_CFD/src/output/CNEMOCompOutput.cpp b/SU2_CFD/src/output/CNEMOCompOutput.cpp
index 7b75ac646d2..2994dd4345e 100644
--- a/SU2_CFD/src/output/CNEMOCompOutput.cpp
+++ b/SU2_CFD/src/output/CNEMOCompOutput.cpp
@@ -65,7 +65,7 @@ CNEMOCompOutput::CNEMOCompOutput(const CConfig *config, unsigned short nDim) : C
auto notFound = requestedVolumeFields.end();
if (find(requestedVolumeFields.begin(), notFound, string("GRID_VELOCITY")) == notFound) {
requestedVolumeFields.emplace_back("GRID_VELOCITY");
- nRequestedVolumeFields ++;
+ nRequestedVolumeFields++;
}
}
diff --git a/SU2_CFD/src/output/COutput.cpp b/SU2_CFD/src/output/COutput.cpp
index adc6f942145..016b5d35ec0 100644
--- a/SU2_CFD/src/output/COutput.cpp
+++ b/SU2_CFD/src/output/COutput.cpp
@@ -173,12 +173,12 @@ COutput::COutput(const CConfig *config, unsigned short ndim, bool fem_output):
convergence = false;
buildFieldIndexCache = false;
-
curInnerIter = 0;
curOuterIter = 0;
curTimeIter = 0;
volumeDataSorter = nullptr;
+ volumeDataSorterCompact = nullptr;
surfaceDataSorter = nullptr;
headerNeeded = false;
@@ -195,6 +195,7 @@ COutput::~COutput() {
delete fileWritingTable;
delete historyFileTable;
delete volumeDataSorter;
+ delete volumeDataSorterCompact;
delete surfaceDataSorter;
}
@@ -343,6 +344,9 @@ void COutput::AllocateDataSorters(CConfig *config, CGeometry *geometry){
if (volumeDataSorter == nullptr)
volumeDataSorter = new CFEMDataSorter(config, geometry, volumeFieldNames);
+ if (config->GetWrt_Restart_Compact() && volumeDataSorterCompact == nullptr)
+ volumeDataSorterCompact = new CFEMDataSorter(config, geometry, requiredVolumeFieldNames);
+
if (surfaceDataSorter == nullptr)
surfaceDataSorter = new CSurfaceFEMDataSorter(config, geometry,
dynamic_cast(volumeDataSorter));
@@ -352,6 +356,9 @@ void COutput::AllocateDataSorters(CConfig *config, CGeometry *geometry){
if (volumeDataSorter == nullptr)
volumeDataSorter = new CFVMDataSorter(config, geometry, volumeFieldNames);
+ if (config->GetWrt_Restart_Compact() && volumeDataSorterCompact == nullptr)
+ volumeDataSorterCompact = new CFVMDataSorter(config, geometry, requiredVolumeFieldNames);
+
if (surfaceDataSorter == nullptr)
surfaceDataSorter = new CSurfaceFVMDataSorter(config, geometry,
dynamic_cast(volumeDataSorter));
@@ -373,6 +380,7 @@ void COutput::LoadData(CGeometry *geometry, CConfig *config, CSolver** solver_co
/*--- Partition and sort the volume output data -- */
volumeDataSorter->SortOutputData();
+ if (volumeDataSorterCompact != nullptr) volumeDataSorterCompact->SortOutputData();
}
@@ -412,6 +420,10 @@ void COutput::WriteToFile(CConfig *config, CGeometry *geometry, OUTPUT_TYPE form
if (!config->GetWrt_Surface_Overwrite())
filename_iter = config->GetFilename_Iter(fileName, curInnerIter, curOuterIter);
+ /*--- If we have compact restarts, we use only the required fields. ---*/
+ if (config->GetWrt_Restart_Compact())
+ surfaceDataSorter->SetRequiredFieldNames(requiredVolumeFieldNames);
+
surfaceDataSorter->SortConnectivity(config, geometry);
surfaceDataSorter->SortOutputData();
@@ -430,6 +442,10 @@ void COutput::WriteToFile(CConfig *config, CGeometry *geometry, OUTPUT_TYPE form
if (!config->GetWrt_Restart_Overwrite())
filename_iter = config->GetFilename_Iter(fileName, curInnerIter, curOuterIter);
+ /*--- If we have compact restarts, we use only the required fields. ---*/
+ if (config->GetWrt_Restart_Compact())
+ volumeDataSorter->SetRequiredFieldNames(requiredVolumeFieldNames);
+
LogOutputFiles("SU2 ASCII restart");
fileWriter = new CSU2FileWriter(volumeDataSorter);
@@ -446,8 +462,13 @@ void COutput::WriteToFile(CConfig *config, CGeometry *geometry, OUTPUT_TYPE form
filename_iter = config->GetFilename_Iter(fileName, curInnerIter, curOuterIter);
LogOutputFiles("SU2 binary restart");
- fileWriter = new CSU2BinaryFileWriter(volumeDataSorter);
-
+ if (config->GetWrt_Restart_Compact()) {
+ /*--- If we have compact restarts, we use only the required fields. ---*/
+ volumeDataSorterCompact->SetRequiredFieldNames(requiredVolumeFieldNames);
+ fileWriter = new CSU2BinaryFileWriter(volumeDataSorterCompact);
+ } else {
+ fileWriter = new CSU2BinaryFileWriter(volumeDataSorter);
+ }
break;
case OUTPUT_TYPE::MESH:
@@ -826,6 +847,7 @@ bool COutput::SetResultFiles(CGeometry *geometry, CConfig *config, CSolver** sol
/*--- Partition and sort the data --- */
volumeDataSorter->SortOutputData();
+ if (volumeDataSorterCompact != nullptr) volumeDataSorterCompact->SortOutputData();
if (rank == MASTER_NODE && !isFileWrite) {
fileWritingTable->SetAlign(PrintingToolbox::CTablePrinter::CENTER);
@@ -1504,58 +1526,64 @@ void COutput::PreprocessVolumeOutput(CConfig *config){
SetVolumeOutputFields(config);
- /*---Coordinates and solution groups must be always in the output.
- * If they are not requested, add them here. ---*/
-
- auto itCoord = std::find(requestedVolumeFields.begin(),
- requestedVolumeFields.end(), "COORDINATES");
- if (itCoord == requestedVolumeFields.end()){
+ /*--- Coordinates must be always in the output. If they are not requested, add them here. ---*/
+ auto itCoord = std::find(requestedVolumeFields.begin(), requestedVolumeFields.end(), "COORDINATES");
+ if (itCoord == requestedVolumeFields.end()) {
requestedVolumeFields.emplace_back("COORDINATES");
nRequestedVolumeFields++;
}
- auto itSol = std::find(requestedVolumeFields.begin(),
- requestedVolumeFields.end(), "SOLUTION");
- if (itSol == requestedVolumeFields.end()){
- requestedVolumeFields.emplace_back("SOLUTION");
- nRequestedVolumeFields++;
- }
- nVolumeFields = 0;
+ /*--- Add the solution if it was not requested for backwards compatibility, unless the COMPACT keyword was used to request exclusively the specified fields. ---*/
+ auto itSol = std::find(requestedVolumeFields.begin(), requestedVolumeFields.end(), "SOLUTION");
+ if (itSol == requestedVolumeFields.end()) {
+ auto itCompact = std::find(requestedVolumeFields.begin(), requestedVolumeFields.end(), "COMPACT");
+ if (itCompact == requestedVolumeFields.end()) {
+ requestedVolumeFields.emplace_back("SOLUTION");
+ nRequestedVolumeFields++;
+ }
+ }
- string RequestedField;
std::vector FoundField(nRequestedVolumeFields, false);
vector FieldsToRemove;
-
/*--- Loop through all fields defined in the corresponding SetVolumeOutputFields().
- * If it is also defined in the config (either as part of a group or a single field), the field
- * object gets an offset so that we know where to find the data in the Local_Data() array.
- * Note that the default offset is -1. An index !=-1 defines this field as part of the output. ---*/
+ * If it is also defined in the config (either as part of a group or a single field), the field
+ * object gets an offset so that we know where to find the data in the Local_Data() array.
+ * Note that the default offset is -1. An index !=-1 defines this field as part of the output. ---*/
+
+ unsigned short nVolumeFields = 0, nVolumeFieldsCompact = 0;
- for (unsigned short iField_Output = 0; iField_Output < volumeOutput_List.size(); iField_Output++){
+ for (size_t iField_Output = 0; iField_Output < volumeOutput_List.size(); iField_Output++) {
const string &fieldReference = volumeOutput_List[iField_Output];
- if (volumeOutput_Map.count(fieldReference) > 0){
- VolumeOutputField &Field = volumeOutput_Map.at(fieldReference);
+ const auto it = volumeOutput_Map.find(fieldReference);
+ if (it != volumeOutput_Map.end()) {
+ VolumeOutputField &Field = it->second;
+
+ /*--- Loop through the minimum required fields for restarts. ---*/
- /*--- Loop through all fields specified in the config ---*/
+ for (const auto& RequiredField : restartVolumeFields) {
+ if ((RequiredField == Field.outputGroup || RequiredField == fieldReference) && Field.offsetCompact == -1) {
+ Field.offsetCompact = nVolumeFieldsCompact++;
+ requiredVolumeFieldNames.push_back(Field.fieldName);
+ }
+ }
- for (unsigned short iReqField = 0; iReqField < nRequestedVolumeFields; iReqField++){
+ /*--- Loop through all fields specified in the config. ---*/
- RequestedField = requestedVolumeFields[iReqField];
+ for (size_t iReqField = 0; iReqField < nRequestedVolumeFields; iReqField++) {
+ const auto &RequestedField = requestedVolumeFields[iReqField];
- if (((RequestedField == Field.outputGroup) || (RequestedField == fieldReference)) && (Field.offset == -1)){
- Field.offset = nVolumeFields;
+ if ((RequestedField == Field.outputGroup || RequestedField == fieldReference) && Field.offset == -1) {
+ Field.offset = nVolumeFields++;
volumeFieldNames.push_back(Field.fieldName);
- nVolumeFields++;
-
FoundField[iReqField] = true;
}
}
}
}
- for (unsigned short iReqField = 0; iReqField < nRequestedVolumeFields; iReqField++){
+ for (size_t iReqField = 0; iReqField < nRequestedVolumeFields; iReqField++){
if (!FoundField[iReqField]){
FieldsToRemove.push_back(requestedVolumeFields[iReqField]);
}
@@ -1563,7 +1591,7 @@ void COutput::PreprocessVolumeOutput(CConfig *config){
/*--- Remove fields which are not defined --- */
- for (unsigned short iReqField = 0; iReqField < FieldsToRemove.size(); iReqField++){
+ for (size_t iReqField = 0; iReqField < FieldsToRemove.size(); iReqField++){
if (rank == MASTER_NODE) {
if (iReqField == 0){
cout << " Info: Ignoring the following volume output fields/groups:" << endl;
@@ -1585,7 +1613,6 @@ void COutput::PreprocessVolumeOutput(CConfig *config){
if (rank == MASTER_NODE){
cout <<"Volume output fields: ";
for (unsigned short iReqField = 0; iReqField < nRequestedVolumeFields; iReqField++){
- RequestedField = requestedVolumeFields[iReqField];
cout << requestedVolumeFields[iReqField];
if (iReqField != nRequestedVolumeFields - 1) cout << ", ";
}
@@ -1602,10 +1629,11 @@ void COutput::LoadDataIntoSorter(CConfig* config, CGeometry* geometry, CSolver**
/*--- Reset the offset cache and index --- */
cachePosition = 0;
fieldIndexCache.clear();
+ fieldIndexCacheCompact.clear();
curGetFieldIndex = 0;
fieldGetIndexCache.clear();
- if (femOutput){
+ if (femOutput) {
/*--- Create an object of the class CMeshFEM_DG and retrieve the necessary
geometrical information for the FEM DG solver. ---*/
@@ -1619,33 +1647,24 @@ void COutput::LoadDataIntoSorter(CConfig* config, CGeometry* geometry, CSolver**
/*--- Access the solution by looping over the owned volume elements. ---*/
for(unsigned long l=0; lGetnPointDomain(); iPoint++) {
-
- /*--- Load the volume data into the data sorter. --- */
-
buildFieldIndexCache = fieldIndexCache.empty();
-
LoadVolumeData(config, geometry, solver, iPoint);
-
}
/*--- Reset the offset cache and index --- */
cachePosition = 0;
fieldIndexCache.clear();
+ fieldIndexCacheCompact.clear();
curGetFieldIndex = 0;
fieldGetIndexCache.clear();
@@ -1653,19 +1672,16 @@ void COutput::LoadDataIntoSorter(CConfig* config, CGeometry* geometry, CSolver**
/*--- We only want to have surface values on solid walls ---*/
- if (config->GetSolid_Wall(iMarker)){
- for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++){
+ if (config->GetSolid_Wall(iMarker)) {
+ for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) {
iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
/*--- Load the surface data into the data sorter. --- */
- if(geometry->nodes->GetDomain(iPoint)){
-
+ if (geometry->nodes->GetDomain(iPoint)) {
buildFieldIndexCache = fieldIndexCache.empty();
-
LoadSurfaceData(config, geometry, solver, iPoint, iMarker, iVertex);
-
}
}
}
@@ -1675,67 +1691,73 @@ void COutput::LoadDataIntoSorter(CConfig* config, CGeometry* geometry, CSolver**
void COutput::SetVolumeOutputValue(const string& name, unsigned long iPoint, su2double value){
- if (buildFieldIndexCache){
-
+ if (buildFieldIndexCache) {
/*--- Build up the offset cache to speed up subsequent
* calls of this routine since the order of calls is
- * the same for every value of iPoint --- */
+ * the same for every value of iPoint. ---*/
- if (volumeOutput_Map.count(name) > 0){
- const short Offset = volumeOutput_Map.at(name).offset;
+ const auto it = volumeOutput_Map.find(name);
+ if (it != volumeOutput_Map.end()) {
+ const short Offset = it->second.offset;
fieldIndexCache.push_back(Offset);
- if (Offset != -1){
+ if (Offset != -1) {
volumeDataSorter->SetUnsortedData(iPoint, Offset, value);
}
+ /*--- Note that the compact fields are a subset of the full fields. ---*/
+ const short OffsetCompact = it->second.offsetCompact;
+ fieldIndexCacheCompact.push_back(OffsetCompact);
+ if (volumeDataSorterCompact != nullptr && OffsetCompact != -1) {
+ volumeDataSorterCompact->SetUnsortedData(iPoint, OffsetCompact, value);
+ }
} else {
- SU2_MPI::Error(string("Cannot find output field with name ") + name, CURRENT_FUNCTION);
+ SU2_MPI::Error("Cannot find output field with name " + name, CURRENT_FUNCTION);
}
} else {
-
- /*--- Use the offset cache for the access ---*/
-
- const short Offset = fieldIndexCache[cachePosition++];
- if (Offset != -1){
+ /*--- Use the offset caches for the access. ---*/
+ const short Offset = fieldIndexCache[cachePosition];
+ const short OffsetCompact = fieldIndexCacheCompact[cachePosition++];
+ if (cachePosition == fieldIndexCache.size()) {
+ cachePosition = 0;
+ }
+ if (Offset != -1) {
volumeDataSorter->SetUnsortedData(iPoint, Offset, value);
}
- if (cachePosition == fieldIndexCache.size()){
- cachePosition = 0;
+ if (volumeDataSorterCompact != nullptr && OffsetCompact != -1) {
+ volumeDataSorterCompact->SetUnsortedData(iPoint, OffsetCompact, value);
}
}
}
-su2double COutput::GetVolumeOutputValue(const string& name, unsigned long iPoint){
-
- if (buildFieldIndexCache){
+su2double COutput::GetVolumeOutputValue(const string& name, unsigned long iPoint) {
+ if (buildFieldIndexCache) {
/*--- Build up the offset cache to speed up subsequent
* calls of this routine since the order of calls is
- * the same for every value of iPoint --- */
+ * the same for every value of iPoint. ---*/
- if (volumeOutput_Map.count(name) > 0){
- const short Offset = volumeOutput_Map.at(name).offset;
+ const auto it = volumeOutput_Map.find(name);
+ if (it != volumeOutput_Map.end()) {
+ const short Offset = it->second.offset;
fieldGetIndexCache.push_back(Offset);
- if (Offset != -1){
+ if (Offset != -1) {
return volumeDataSorter->GetUnsortedData(iPoint, Offset);
}
} else {
- SU2_MPI::Error(string("Cannot find output field with name ") + name, CURRENT_FUNCTION);
+ SU2_MPI::Error("Cannot find output field with name " + name, CURRENT_FUNCTION);
}
} else {
-
- /*--- Use the offset cache for the access ---*/
+ /*--- Use the offset cache for the access, ---*/
const short Offset = fieldGetIndexCache[curGetFieldIndex++];
- if (curGetFieldIndex == fieldGetIndexCache.size()){
+ if (curGetFieldIndex == fieldGetIndexCache.size()) {
curGetFieldIndex = 0;
}
- if (Offset != -1){
+ if (Offset != -1) {
return volumeDataSorter->GetUnsortedData(iPoint, Offset);
}
}
-
return 0.0;
}
@@ -1743,38 +1765,39 @@ void COutput::SetAvgVolumeOutputValue(const string& name, unsigned long iPoint,
const su2double scaling = 1.0 / su2double(curAbsTimeIter + 1);
- if (buildFieldIndexCache){
-
+ if (buildFieldIndexCache) {
/*--- Build up the offset cache to speed up subsequent
* calls of this routine since the order of calls is
- * the same for every value of iPoint --- */
+ * the same for every value of iPoint. ---*/
- if (volumeOutput_Map.count(name) > 0){
- const short Offset = volumeOutput_Map.at(name).offset;
+ const auto it = volumeOutput_Map.find(name);
+ if (it != volumeOutput_Map.end()) {
+ const short Offset = it->second.offset;
fieldIndexCache.push_back(Offset);
- if (Offset != -1){
-
+ /*--- This function is used for time-averaged fields and we know
+ * those are not part of the compact restart fields. ---*/
+ fieldIndexCacheCompact.push_back(-1);
+ if (Offset != -1) {
const su2double old_value = volumeDataSorter->GetUnsortedData(iPoint, Offset);
- const su2double new_value = value * scaling + old_value *( 1.0 - scaling);
+ const su2double new_value = value * scaling + old_value * (1.0 - scaling);
volumeDataSorter->SetUnsortedData(iPoint, Offset, new_value);
}
} else {
- SU2_MPI::Error(string("Cannot find output field with name ") + name, CURRENT_FUNCTION);
+ SU2_MPI::Error("Cannot find output field with name " + name, CURRENT_FUNCTION);
}
} else {
/*--- Use the offset cache for the access ---*/
const short Offset = fieldIndexCache[cachePosition++];
- if (Offset != -1){
-
+ if (Offset != -1) {
const su2double old_value = volumeDataSorter->GetUnsortedData(iPoint, Offset);
- const su2double new_value = value * scaling + old_value *( 1.0 - scaling);
+ const su2double new_value = value * scaling + old_value * (1.0 - scaling);
volumeDataSorter->SetUnsortedData(iPoint, Offset, new_value);
}
- if (cachePosition == fieldIndexCache.size()){
+ if (cachePosition == fieldIndexCache.size()) {
cachePosition = 0;
}
}
@@ -2414,7 +2437,7 @@ void COutput::PrintVolumeFields(){
}
cout << "Available volume output fields for the current configuration in " << multiZoneHeaderString << ":" << endl;
- cout << "Note: COORDINATES and SOLUTION groups are always in the volume output." << endl;
+ cout << "Note: COORDINATES are always included, and so is SOLUTION unless you add the keyword COMPACT to the list of fields." << endl;
VolumeFieldTable.AddColumn("Name", NameSize);
VolumeFieldTable.AddColumn("Group Name", GroupSize);
VolumeFieldTable.AddColumn("Description", DescrSize);
diff --git a/SU2_CFD/src/output/filewriter/CParallelDataSorter.cpp b/SU2_CFD/src/output/filewriter/CParallelDataSorter.cpp
index 0290c20b025..2bc2778ec24 100644
--- a/SU2_CFD/src/output/filewriter/CParallelDataSorter.cpp
+++ b/SU2_CFD/src/output/filewriter/CParallelDataSorter.cpp
@@ -32,7 +32,8 @@
CParallelDataSorter::CParallelDataSorter(CConfig *config, const vector &valFieldNames) :
rank(SU2_MPI::GetRank()),
size(SU2_MPI::GetSize()),
- fieldNames(valFieldNames) {
+ fieldNames(valFieldNames),
+ requiredFieldNames(valFieldNames) {
GlobalField_Counter = fieldNames.size();
diff --git a/SU2_CFD/src/output/filewriter/CSU2BinaryFileWriter.cpp b/SU2_CFD/src/output/filewriter/CSU2BinaryFileWriter.cpp
index 8e7a869f1bf..fb8c660c740 100644
--- a/SU2_CFD/src/output/filewriter/CSU2BinaryFileWriter.cpp
+++ b/SU2_CFD/src/output/filewriter/CSU2BinaryFileWriter.cpp
@@ -41,7 +41,7 @@ void CSU2BinaryFileWriter::WriteData(string val_filename){
unsigned short iVar;
- const vector& fieldNames = dataSorter->GetFieldNames();
+ const vector& fieldNames = dataSorter->GetRequiredFieldNames();
unsigned short nVar = fieldNames.size();
unsigned long nParallel_Poin = dataSorter->GetnPoints();
unsigned long nPoint_Global = dataSorter->GetnPointsGlobal();
diff --git a/SU2_CFD/src/output/filewriter/CSU2FileWriter.cpp b/SU2_CFD/src/output/filewriter/CSU2FileWriter.cpp
index 4c04cf0e70d..ff498b1d357 100644
--- a/SU2_CFD/src/output/filewriter/CSU2FileWriter.cpp
+++ b/SU2_CFD/src/output/filewriter/CSU2FileWriter.cpp
@@ -35,7 +35,8 @@ CSU2FileWriter::CSU2FileWriter(CParallelDataSorter *valDataSorter) :
void CSU2FileWriter::WriteData(string val_filename){
ofstream restart_file;
- const vector fieldNames = dataSorter->GetFieldNames();
+ const vector fieldNames = dataSorter->GetRequiredFieldNames();
+
/*--- We append the pre-defined suffix (extension) to the filename (prefix) ---*/
val_filename.append(fileExt);
diff --git a/TestCases/flamelet/02_laminar_premixed_ch4_flame_hx_ad/lam_prem_ch4_hx_ad.cfg b/TestCases/flamelet/02_laminar_premixed_ch4_flame_hx_ad/lam_prem_ch4_hx_ad.cfg
index ff52e8d58b6..b79c1f3b367 100644
--- a/TestCases/flamelet/02_laminar_premixed_ch4_flame_hx_ad/lam_prem_ch4_hx_ad.cfg
+++ b/TestCases/flamelet/02_laminar_premixed_ch4_flame_hx_ad/lam_prem_ch4_hx_ad.cfg
@@ -128,7 +128,7 @@ MARKER_ANALYZE_AVERAGE= MASSFLUX
OUTPUT_FILES= RESTART, RESTART_ASCII, PARAVIEW
VOLUME_OUTPUT= RESIDUAL, PRIMITIVE
VOLUME_ADJ_FILENAME= ch4_flame_hx_ad
-
+WRT_RESTART_COMPACT = NO
OUTPUT_WRT_FREQ= 100
%
GRAD_OBJFUNC_FILENAME= of_grad.csv
diff --git a/TestCases/flamelet/03_laminar_premixed_ch4_flame_cht_cfd/lam_prem_ch4_cht_cfd_fluid.cfg b/TestCases/flamelet/03_laminar_premixed_ch4_flame_cht_cfd/lam_prem_ch4_cht_cfd_fluid.cfg
index adf9a65020f..af8e562b0cd 100644
--- a/TestCases/flamelet/03_laminar_premixed_ch4_flame_cht_cfd/lam_prem_ch4_cht_cfd_fluid.cfg
+++ b/TestCases/flamelet/03_laminar_premixed_ch4_flame_cht_cfd/lam_prem_ch4_cht_cfd_fluid.cfg
@@ -19,6 +19,8 @@ HISTORY_OUTPUT= RMS_RES AERO_COEFF FLOW_COEFF FLOW_COEFF_SURF
VOLUME_OUTPUT= SOLUTION PRIMITIVE SOURCE RESIDUAL LOOKUP
+WRT_RESTART_COMPACT = NO
+
OUTPUT_FILES= (RESTART_ASCII, PARAVIEW)
INNER_ITER= 1
diff --git a/TestCases/flamelet/04_laminar_premixed_ch4_flame_cht_ad/lam_prem_ch4_cht_ad_fluid.cfg b/TestCases/flamelet/04_laminar_premixed_ch4_flame_cht_ad/lam_prem_ch4_cht_ad_fluid.cfg
index 7824d6780fd..b251e54182a 100644
--- a/TestCases/flamelet/04_laminar_premixed_ch4_flame_cht_ad/lam_prem_ch4_cht_ad_fluid.cfg
+++ b/TestCases/flamelet/04_laminar_premixed_ch4_flame_cht_ad/lam_prem_ch4_cht_ad_fluid.cfg
@@ -23,6 +23,8 @@ VOLUME_OUTPUT= SOLUTION PRIMITIVE SOURCE RESIDUAL LOOKUP
OUTPUT_FILES= ( RESTART_ASCII)
+WRT_RESTART_COMPACT= NO
+
INNER_ITER= 1
% -------------------- BOUNDARY CONDITION DEFINITION --------------------------%
diff --git a/TestCases/py_wrapper/custom_load_fea/run_ad.py b/TestCases/py_wrapper/custom_load_fea/run_ad.py
index dfb9fab4fab..dc643ad67a1 100644
--- a/TestCases/py_wrapper/custom_load_fea/run_ad.py
+++ b/TestCases/py_wrapper/custom_load_fea/run_ad.py
@@ -61,6 +61,7 @@
OUTPUT_WRT_FREQ= 1
OBJECTIVE_FUNCTION= STRESS_PENALTY
STRESS_PENALTY_PARAM= ( 500, 20 )
+WRT_RESTART_COMPACT= NO
INNER_ITER= 20
CONV_RESIDUAL_MINVAL= -4
diff --git a/config_template.cfg b/config_template.cfg
index 49cca43332b..0acf538f856 100644
--- a/config_template.cfg
+++ b/config_template.cfg
@@ -51,7 +51,7 @@ KIND_VERIFICATION_SOLUTION= NO_VERIFICATION_SOLUTION
% Defaults to DISCRETE_ADJOINT for the SU2_*_AD codes, and to DIRECT otherwise.
MATH_PROBLEM= DIRECT
%
-% Axisymmetric simulation, only compressible flows (NO, YES)
+% Axisymmetric simulation for 2D problems. (NO, YES)
AXISYMMETRIC= NO
%
% Gravity force
@@ -60,6 +60,12 @@ GRAVITY_FORCE= NO
% Restart solution (NO, YES)
RESTART_SOL= NO
%
+% Only save the minimum required variables for restarting to restart files (NO, YES).
+% If this option is set to NO, then all fields will be written to all output files.
+% To minimize the size of other output files (e.g. paraview, tecplot) by not including
+% default restart fields in them, add the keyword COMPACT to VOLUME_OUTPUT.
+WRT_RESTART_COMPACT= YES
+%
% Discard the data storaged in the solution and geometry files
% e.g. AOA, dCL/dAoA, dCD/dCL, iter, etc.
% Note that AoA in the solution and geometry files is critical