Skip to content

Commit 726f4e7

Browse files
committed
one LoadRestart to rule them all
1 parent 30184d3 commit 726f4e7

9 files changed

Lines changed: 258 additions & 660 deletions

File tree

SU2_CFD/include/solvers/CEulerSolver.hpp

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1057,20 +1057,6 @@ class CEulerSolver : public CFVMFlowSolverBase<CEulerVariable, COMPRESSIBLE> {
10571057
*/
10581058
void UpdateCustomBoundaryConditions(CGeometry **geometry_container, CConfig *config) final;
10591059

1060-
/*!
1061-
* \brief Load a solution from a restart file.
1062-
* \param[in] geometry - Geometrical definition of the problem.
1063-
* \param[in] solver - Container vector with all of the solvers.
1064-
* \param[in] config - Definition of the particular problem.
1065-
* \param[in] val_iter - Current external iteration number.
1066-
* \param[in] val_update_geo - Flag for updating coords and grid velocity.
1067-
*/
1068-
void LoadRestart(CGeometry **geometry,
1069-
CSolver ***solver,
1070-
CConfig *config,
1071-
int val_iter,
1072-
bool val_update_geo) final;
1073-
10741060
/*!
10751061
* \brief Set the initial condition for the Euler Equations.
10761062
* \param[in] geometry - Geometrical definition of the problem.

SU2_CFD/include/solvers/CFVMFlowSolverBase.hpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,20 @@ class CFVMFlowSolverBase : public CSolver {
267267
CNumerics *numerics, CConfig *config);
268268
using CSolver::Viscous_Residual; /*--- Silence warning ---*/
269269

270+
/*!
271+
* \brief General implementation to load a flow solution from a restart file.
272+
* \param[in] geometry - Geometrical definition of the problem.
273+
* \param[in] solver - Container vector with all of the solvers.
274+
* \param[in] config - Definition of the particular problem.
275+
* \param[in] iter - Current external iteration number.
276+
* \param[in] update_geo - Flag for updating coords and grid velocity.
277+
* \param[in] RestartSolution - Optional buffer to load restart vars into,
278+
* this allows default values to be given when nVar > nVar_Restart.
279+
* \param[in] nVar_Restart - Number of restart variables, if 0 defaults to nVar.
280+
*/
281+
void LoadRestart_impl(CGeometry **geometry, CSolver ***solver, CConfig *config, int iter, bool update_geo,
282+
su2double* RestartSolution = nullptr, unsigned short nVar_Restart = 0);
283+
270284
/*!
271285
* \brief Generic implementation to compute the time step based on CFL and conv/visc eigenvalues.
272286
* \param[in] geometry - Geometrical definition of the problem.
@@ -1068,6 +1082,17 @@ class CFVMFlowSolverBase : public CSolver {
10681082
~CFVMFlowSolverBase();
10691083

10701084
public:
1085+
1086+
/*!
1087+
* \brief Load a solution from a restart file.
1088+
* \param[in] geometry - Geometrical definition of the problem.
1089+
* \param[in] solver - Container vector with all of the solvers.
1090+
* \param[in] config - Definition of the particular problem.
1091+
* \param[in] iter - Current external iteration number.
1092+
* \param[in] update_geo - Flag for updating coords and grid velocity.
1093+
*/
1094+
void LoadRestart(CGeometry **geometry, CSolver ***solver, CConfig *config, int iter, bool update_geo) override;
1095+
10711096
/*!
10721097
* \brief Compute the gradient of the primitive variables using Green-Gauss method,
10731098
* and stores the result in the <i>Gradient_Primitive</i> variable.

SU2_CFD/include/solvers/CFVMFlowSolverBase.inl

Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -818,6 +818,234 @@ void CFVMFlowSolverBase<V, R>::SetUniformInlet(const CConfig* config, unsigned s
818818
}
819819
}
820820

821+
template <class V, ENUM_REGIME R>
822+
void CFVMFlowSolverBase<V, R>::LoadRestart_impl(CGeometry **geometry, CSolver ***solver, CConfig *config,
823+
int iter, bool update_geo, su2double* SolutionRestart,
824+
unsigned short nVar_Restart) {
825+
826+
/*--- Restart the solution from file information ---*/
827+
828+
unsigned short iDim, iVar, iMesh, iMeshFine;
829+
unsigned long iPoint, index, iChildren, Point_Fine;
830+
unsigned short turb_model = config->GetKind_Turb_Model();
831+
su2double Area_Children, Area_Parent;
832+
const su2double* Solution_Fine = nullptr;
833+
const passivedouble* Coord = nullptr;
834+
bool dual_time = ((config->GetTime_Marching() == DT_STEPPING_1ST) ||
835+
(config->GetTime_Marching() == DT_STEPPING_2ND));
836+
bool static_fsi = ((config->GetTime_Marching() == STEADY) && config->GetFSI_Simulation());
837+
bool steady_restart = config->GetSteadyRestart();
838+
bool turbulent = (config->GetKind_Turb_Model() != NONE);
839+
840+
string restart_filename = config->GetFilename(config->GetSolution_FileName(), "", iter);
841+
842+
/*--- To make this routine safe to call in parallel most of it can only be executed by one thread. ---*/
843+
SU2_OMP_MASTER {
844+
845+
if (nVar_Restart == 0) nVar_Restart = nVar;
846+
847+
/*--- Skip coordinates ---*/
848+
849+
unsigned short skipVars = geometry[MESH_0]->GetnDim();
850+
851+
/*--- Store the number of variables for the turbulence model
852+
(that could appear in the restart file before the grid velocities). ---*/
853+
unsigned short turbVars = 0;
854+
if (turbulent){
855+
if ((turb_model == SST) || (turb_model == SST_SUST)) turbVars = 2;
856+
else turbVars = 1;
857+
}
858+
859+
/*--- Read the restart data from either an ASCII or binary SU2 file. ---*/
860+
861+
if (config->GetRead_Binary_Restart()) {
862+
Read_SU2_Restart_Binary(geometry[MESH_0], config, restart_filename);
863+
} else {
864+
Read_SU2_Restart_ASCII(geometry[MESH_0], config, restart_filename);
865+
}
866+
867+
/*--- Load data from the restart into correct containers. ---*/
868+
869+
unsigned long counter = 0, iPoint_Global = 0;
870+
for (; iPoint_Global < geometry[MESH_0]->GetGlobal_nPointDomain(); iPoint_Global++) {
871+
872+
/*--- Retrieve local index. If this node from the restart file lives
873+
on the current processor, we will load and instantiate the vars. ---*/
874+
875+
auto iPoint_Local = geometry[MESH_0]->GetGlobal_to_Local_Point(iPoint_Global);
876+
877+
if (iPoint_Local > -1) {
878+
879+
/*--- We need to store this point's data, so jump to the correct
880+
offset in the buffer of data from the restart file and load it. ---*/
881+
882+
index = counter*Restart_Vars[1] + skipVars;
883+
884+
if (SolutionRestart == nullptr) {
885+
nodes->SetSolution(iPoint_Local, &Restart_Data[index]);
886+
}
887+
else {
888+
/*--- Used as buffer, allows defaults for nVar > nVar_Restart. ---*/
889+
for (iVar = 0; iVar < nVar_Restart; iVar++)
890+
SolutionRestart[iVar] = Restart_Data[index+iVar];
891+
nodes->SetSolution(iPoint_Local, SolutionRestart);
892+
}
893+
894+
/*--- For dynamic meshes, read in and store the
895+
grid coordinates and grid velocities for each node. ---*/
896+
897+
if (dynamic_grid && update_geo) {
898+
899+
/*--- Read in the next 2 or 3 variables which are the grid velocities ---*/
900+
/*--- If we are restarting the solution from a previously computed static calculation (no grid movement) ---*/
901+
/*--- the grid velocities are set to 0. This is useful for FSI computations ---*/
902+
903+
/*--- Rewind the index to retrieve the Coords. ---*/
904+
index = counter*Restart_Vars[1];
905+
Coord = &Restart_Data[index];
906+
907+
su2double GridVel[MAXNDIM] = {0.0};
908+
if (!steady_restart) {
909+
/*--- Move the index forward to get the grid velocities. ---*/
910+
index += skipVars + nVar_Restart + turbVars;
911+
for (iDim = 0; iDim < nDim; iDim++) { GridVel[iDim] = Restart_Data[index+iDim]; }
912+
}
913+
914+
for (iDim = 0; iDim < nDim; iDim++) {
915+
geometry[MESH_0]->nodes->SetCoord(iPoint_Local, iDim, Coord[iDim]);
916+
geometry[MESH_0]->nodes->SetGridVel(iPoint_Local, iDim, GridVel[iDim]);
917+
}
918+
}
919+
920+
/*--- For static FSI problems, grid_movement is 0 but we need to read in and store the
921+
grid coordinates for each node (but not the grid velocities, as there are none). ---*/
922+
923+
if (static_fsi && update_geo) {
924+
/*--- Rewind the index to retrieve the Coords. ---*/
925+
index = counter*Restart_Vars[1];
926+
Coord = &Restart_Data[index];
927+
928+
for (iDim = 0; iDim < nDim; iDim++) {
929+
geometry[MESH_0]->nodes->SetCoord(iPoint_Local, iDim, Coord[iDim]);
930+
}
931+
}
932+
933+
/*--- Increment the overall counter for how many points have been loaded. ---*/
934+
counter++;
935+
}
936+
937+
}
938+
939+
/*--- Detect a wrong solution file ---*/
940+
941+
if (counter != nPointDomain) {
942+
SU2_MPI::Error(string("The solution file ") + restart_filename + string(" doesn't match with the mesh file!\n") +
943+
string("It could be empty lines at the end of the file."), CURRENT_FUNCTION);
944+
}
945+
} // end SU2_OMP_MASTER
946+
SU2_OMP_BARRIER
947+
948+
/*--- Update the geometry for flows on deforming meshes ---*/
949+
950+
if ((dynamic_grid || static_fsi) && update_geo) {
951+
952+
/*--- Communicate the new coordinates and grid velocities at the halos ---*/
953+
954+
geometry[MESH_0]->InitiateComms(geometry[MESH_0], config, COORDINATES);
955+
geometry[MESH_0]->CompleteComms(geometry[MESH_0], config, COORDINATES);
956+
957+
if (dynamic_grid) {
958+
geometry[MESH_0]->InitiateComms(geometry[MESH_0], config, GRID_VELOCITY);
959+
geometry[MESH_0]->CompleteComms(geometry[MESH_0], config, GRID_VELOCITY);
960+
}
961+
962+
/*--- Recompute the edges and dual mesh control volumes in the
963+
domain and on the boundaries. ---*/
964+
965+
geometry[MESH_0]->SetControlVolume(config, UPDATE);
966+
geometry[MESH_0]->SetBoundControlVolume(config, UPDATE);
967+
geometry[MESH_0]->SetMaxLength(config);
968+
969+
/*--- Update the multigrid structure after setting up the finest grid,
970+
including computing the grid velocities on the coarser levels. ---*/
971+
972+
for (iMesh = 1; iMesh <= config->GetnMGLevels(); iMesh++) {
973+
iMeshFine = iMesh-1;
974+
geometry[iMesh]->SetControlVolume(config, geometry[iMeshFine], UPDATE);
975+
geometry[iMesh]->SetBoundControlVolume(config, geometry[iMeshFine],UPDATE);
976+
geometry[iMesh]->SetCoord(geometry[iMeshFine]);
977+
if (dynamic_grid) {
978+
geometry[iMesh]->SetRestricted_GridVelocity(geometry[iMeshFine], config);
979+
}
980+
geometry[iMesh]->SetMaxLength(config);
981+
}
982+
}
983+
984+
/*--- Communicate the loaded solution on the fine grid before we transfer
985+
it down to the coarse levels. We also call the preprocessing routine
986+
on the fine level in order to have all necessary quantities updated,
987+
especially if this is a turbulent simulation (eddy viscosity). ---*/
988+
989+
solver[MESH_0][FLOW_SOL]->InitiateComms(geometry[MESH_0], config, SOLUTION);
990+
solver[MESH_0][FLOW_SOL]->CompleteComms(geometry[MESH_0], config, SOLUTION);
991+
992+
/*--- For turbulent simulations the flow preprocessing is done by the turbulence solver
993+
* after it loads its variables (they are needed to compute flow primitives). ---*/
994+
if (!turbulent) {
995+
solver[MESH_0][FLOW_SOL]->Preprocessing(geometry[MESH_0], solver[MESH_0], config, MESH_0, NO_RK_ITER, RUNTIME_FLOW_SYS, false);
996+
}
997+
998+
/*--- Interpolate the solution down to the coarse multigrid levels ---*/
999+
1000+
for (iMesh = 1; iMesh <= config->GetnMGLevels(); iMesh++) {
1001+
SU2_OMP_FOR_STAT(omp_chunk_size)
1002+
for (iPoint = 0; iPoint < geometry[iMesh]->GetnPoint(); iPoint++) {
1003+
Area_Parent = geometry[iMesh]->nodes->GetVolume(iPoint);
1004+
su2double Solution_Coarse[MAXNVAR] = {0.0};
1005+
for (iChildren = 0; iChildren < geometry[iMesh]->nodes->GetnChildren_CV(iPoint); iChildren++) {
1006+
Point_Fine = geometry[iMesh]->nodes->GetChildren_CV(iPoint, iChildren);
1007+
Area_Children = geometry[iMesh-1]->nodes->GetVolume(Point_Fine);
1008+
Solution_Fine = solver[iMesh-1][FLOW_SOL]->GetNodes()->GetSolution(Point_Fine);
1009+
for (iVar = 0; iVar < nVar; iVar++) {
1010+
Solution_Coarse[iVar] += Solution_Fine[iVar]*Area_Children/Area_Parent;
1011+
}
1012+
}
1013+
solver[iMesh][FLOW_SOL]->GetNodes()->SetSolution(iPoint,Solution_Coarse);
1014+
}
1015+
1016+
solver[iMesh][FLOW_SOL]->InitiateComms(geometry[iMesh], config, SOLUTION);
1017+
solver[iMesh][FLOW_SOL]->CompleteComms(geometry[iMesh], config, SOLUTION);
1018+
1019+
if (!turbulent) {
1020+
solver[iMesh][FLOW_SOL]->Preprocessing(geometry[iMesh], solver[iMesh], config, iMesh, NO_RK_ITER, RUNTIME_FLOW_SYS, false);
1021+
}
1022+
}
1023+
1024+
/*--- Update the old geometry (coordinates n and n-1) in dual time-stepping strategy. ---*/
1025+
if (dual_time && config->GetGrid_Movement() && !config->GetDeform_Mesh() &&
1026+
(config->GetKind_GridMovement() != RIGID_MOTION)) {
1027+
Restart_OldGeometry(geometry[MESH_0], config);
1028+
}
1029+
1030+
/*--- Go back to single threaded execution. ---*/
1031+
SU2_OMP_MASTER
1032+
{
1033+
/*--- Delete the class memory that is used to load the restart. ---*/
1034+
1035+
delete [] Restart_Vars; Restart_Vars = nullptr;
1036+
delete [] Restart_Data; Restart_Data = nullptr;
1037+
1038+
} // end SU2_OMP_MASTER
1039+
SU2_OMP_BARRIER
1040+
1041+
}
1042+
1043+
template <class V, ENUM_REGIME R>
1044+
void CFVMFlowSolverBase<V, R>::LoadRestart(CGeometry **geometry, CSolver ***solver,
1045+
CConfig *config, int iter, bool update_geo) {
1046+
LoadRestart_impl(geometry, solver, config, iter, update_geo);
1047+
}
1048+
8211049
template <class V, ENUM_REGIME R>
8221050
void CFVMFlowSolverBase<V, R>::PushSolutionBackInTime(unsigned long TimeIter, bool restart, bool rans,
8231051
CSolver*** solver_container, CGeometry** geometry,

SU2_CFD/include/solvers/CNEMOEulerSolver.hpp

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -124,16 +124,6 @@ class CNEMOEulerSolver : public CFVMFlowSolverBase<CNEMOEulerVariable, COMPRESSI
124124
*/
125125
void SetInitialCondition(CGeometry **geometry, CSolver ***solver_container, CConfig *config, unsigned long ExtIter) final;
126126

127-
/*!
128-
* \brief Load a solution from a restart file.
129-
* \param[in] geometry - Geometrical definition of the problem.
130-
* \param[in] solver - Container vector with all of the solvers.
131-
* \param[in] config - Definition of the particular problem.
132-
* \param[in] val_iter - Current external iteration number.
133-
* \param[in] val_update_geo - Flag for updating coords and grid velocity.
134-
*/
135-
void LoadRestart(CGeometry **geometry, CSolver ***solver, CConfig *config, int val_iter, bool val_update_geo) final;
136-
137127
/*!
138128
* \brief Compute the spatial integration using a centered scheme.
139129
* \param[in] geometry - Geometrical definition of the problem.

SU2_CFD/src/drivers/CMultizoneDriver.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ CMultizoneDriver::CMultizoneDriver(char* confFile, unsigned short val_nZone, SU2
8181
break;
8282
case NEMO_EULER: case NEMO_NAVIER_STOKES:
8383
fluid_zone = true;
84-
break;
84+
break;
8585
case FEM_ELASTICITY:
8686
structural_zone = true;
8787
break;
@@ -263,9 +263,7 @@ void CMultizoneDriver::Preprocess(unsigned long TimeIter) {
263263
}
264264
}
265265

266-
#ifdef HAVE_MPI
267266
SU2_MPI::Barrier(MPI_COMM_WORLD);
268-
#endif
269267

270268
/*--- Run a predictor step ---*/
271269
for (iZone = 0; iZone < nZone; iZone++) {

SU2_CFD/src/drivers/CSinglezoneDriver.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,9 +131,7 @@ void CSinglezoneDriver::Preprocess(unsigned long TimeIter) {
131131
config_container[ZONE_0], TimeIter);
132132
}
133133

134-
#ifdef HAVE_MPI
135134
SU2_MPI::Barrier(MPI_COMM_WORLD);
136-
#endif
137135

138136
/*--- Run a predictor step ---*/
139137
if (config_container[ZONE_0]->GetPredictor())

0 commit comments

Comments
 (0)