Skip to content

Commit 58d3df3

Browse files
committed
Make Scalar LoadRestart pure virtual.
And move current Turb specific impl to CTurbSolver. I.e. each Child of CscalarSolver has to implement its own LoadRestart. One has to make sure the correct Pre/Postprocessign routines are called in there which are consistent with the repective C(Fluid)Iteration.
1 parent 811d581 commit 58d3df3

4 files changed

Lines changed: 130 additions & 121 deletions

File tree

SU2_CFD/include/solvers/CScalarSolver.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ class CScalarSolver : public CSolver {
292292
* \param[in] val_iter - Current external iteration number.
293293
* \param[in] val_update_geo - Flag for updating coords and grid velocity.
294294
*/
295-
void LoadRestart(CGeometry** geometry, CSolver*** solver, CConfig* config, int val_iter, bool val_update_geo) final;
295+
virtual void LoadRestart(CGeometry** geometry, CSolver*** solver, CConfig* config, int val_iter, bool val_update_geo) override = 0;
296296

297297
/*!
298298
* \brief Scalar solvers support OpenMP+MPI.

SU2_CFD/include/solvers/CScalarSolver.inl

Lines changed: 0 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -645,123 +645,3 @@ void CScalarSolver<TVariable>::SetResidual_DualTime(CGeometry* geometry, CSolver
645645

646646
} // end dynamic grid
647647
}
648-
649-
template <class TVariable>
650-
void CScalarSolver<TVariable>::LoadRestart(CGeometry** geometry, CSolver*** solver, CConfig* config, int val_iter,
651-
bool val_update_geo) {
652-
/*--- Restart the solution from file information ---*/
653-
654-
unsigned short iVar, iMesh;
655-
unsigned long iPoint, index, iChildren, Point_Fine;
656-
su2double Area_Children, Area_Parent;
657-
const su2double* Solution_Fine = nullptr;
658-
659-
string restart_filename = config->GetFilename(config->GetSolution_FileName(), "", val_iter);
660-
661-
/*--- To make this routine safe to call in parallel most of it can only be executed by one thread. ---*/
662-
SU2_OMP_MASTER {
663-
/*--- Read the restart data from either an ASCII or binary SU2 file. ---*/
664-
665-
if (config->GetRead_Binary_Restart()) {
666-
Read_SU2_Restart_Binary(geometry[MESH_0], config, restart_filename);
667-
} else {
668-
Read_SU2_Restart_ASCII(geometry[MESH_0], config, restart_filename);
669-
}
670-
671-
/*--- Skip flow variables ---*/
672-
673-
unsigned short skipVars = nDim + solver[MESH_0][FLOW_SOL]->GetnVar();
674-
675-
/*--- Adjust the number of solution variables in the incompressible
676-
restart. We always carry a space in nVar for the energy equation in the
677-
mean flow solver, but we only write it to the restart if it is active.
678-
Therefore, we must reduce skipVars here if energy is inactive so that
679-
the turbulent variables are read correctly. ---*/
680-
681-
bool incompressible = (config->GetKind_Regime() == ENUM_REGIME::INCOMPRESSIBLE);
682-
bool energy = config->GetEnergy_Equation();
683-
bool weakly_coupled_heat = config->GetWeakly_Coupled_Heat();
684-
685-
if (incompressible && ((!energy) && (!weakly_coupled_heat))) skipVars--;
686-
687-
/*--- Load data from the restart into correct containers. ---*/
688-
689-
unsigned long counter = 0, iPoint_Global = 0;
690-
for (; iPoint_Global < geometry[MESH_0]->GetGlobal_nPointDomain(); iPoint_Global++) {
691-
/*--- Retrieve local index. If this node from the restart file lives
692-
on the current processor, we will load and instantiate the vars. ---*/
693-
694-
auto iPoint_Local = geometry[MESH_0]->GetGlobal_to_Local_Point(iPoint_Global);
695-
696-
if (iPoint_Local > -1) {
697-
/*--- We need to store this point's data, so jump to the correct
698-
offset in the buffer of data from the restart file and load it. ---*/
699-
700-
index = counter * Restart_Vars[1] + skipVars;
701-
for (iVar = 0; iVar < nVar; ++iVar) nodes->SetSolution(iPoint_Local, iVar, Restart_Data[index + iVar]);
702-
703-
/*--- Increment the overall counter for how many points have been loaded. ---*/
704-
counter++;
705-
}
706-
}
707-
708-
/*--- Detect a wrong solution file ---*/
709-
710-
if (counter != nPointDomain) {
711-
SU2_MPI::Error(string("The solution file ") + restart_filename + string(" doesn't match with the mesh file!\n") +
712-
string("It could be empty lines at the end of the file."),
713-
CURRENT_FUNCTION);
714-
}
715-
716-
} // end SU2_OMP_MASTER, pre and postprocessing are thread-safe.
717-
END_SU2_OMP_MASTER
718-
SU2_OMP_BARRIER
719-
720-
/*--- MPI solution and compute the eddy viscosity ---*/
721-
722-
solver[MESH_0][TURB_SOL]->InitiateComms(geometry[MESH_0], config, SOLUTION);
723-
solver[MESH_0][TURB_SOL]->CompleteComms(geometry[MESH_0], config, SOLUTION);
724-
725-
solver[MESH_0][FLOW_SOL]->Preprocessing(geometry[MESH_0], solver[MESH_0], config, MESH_0, NO_RK_ITER,
726-
RUNTIME_FLOW_SYS, false);
727-
solver[MESH_0][TURB_SOL]->Postprocessing(geometry[MESH_0], solver[MESH_0], config, MESH_0);
728-
729-
/*--- Interpolate the solution down to the coarse multigrid levels ---*/
730-
731-
for (iMesh = 1; iMesh <= config->GetnMGLevels(); iMesh++) {
732-
SU2_OMP_FOR_STAT(omp_chunk_size)
733-
for (iPoint = 0; iPoint < geometry[iMesh]->GetnPoint(); iPoint++) {
734-
Area_Parent = geometry[iMesh]->nodes->GetVolume(iPoint);
735-
su2double Solution_Coarse[MAXNVAR] = {0.0};
736-
for (iChildren = 0; iChildren < geometry[iMesh]->nodes->GetnChildren_CV(iPoint); iChildren++) {
737-
Point_Fine = geometry[iMesh]->nodes->GetChildren_CV(iPoint, iChildren);
738-
Area_Children = geometry[iMesh - 1]->nodes->GetVolume(Point_Fine);
739-
Solution_Fine = solver[iMesh - 1][TURB_SOL]->GetNodes()->GetSolution(Point_Fine);
740-
for (iVar = 0; iVar < nVar; iVar++) {
741-
Solution_Coarse[iVar] += Solution_Fine[iVar] * Area_Children / Area_Parent;
742-
}
743-
}
744-
solver[iMesh][TURB_SOL]->GetNodes()->SetSolution(iPoint, Solution_Coarse);
745-
}
746-
END_SU2_OMP_FOR
747-
748-
solver[iMesh][TURB_SOL]->InitiateComms(geometry[iMesh], config, SOLUTION);
749-
solver[iMesh][TURB_SOL]->CompleteComms(geometry[iMesh], config, SOLUTION);
750-
751-
solver[iMesh][FLOW_SOL]->Preprocessing(geometry[iMesh], solver[iMesh], config, iMesh, NO_RK_ITER, RUNTIME_FLOW_SYS,
752-
false);
753-
solver[iMesh][TURB_SOL]->Postprocessing(geometry[iMesh], solver[iMesh], config, iMesh);
754-
}
755-
756-
/*--- Go back to single threaded execution. ---*/
757-
SU2_OMP_MASTER {
758-
/*--- Delete the class memory that is used to load the restart. ---*/
759-
760-
delete[] Restart_Vars;
761-
Restart_Vars = nullptr;
762-
delete[] Restart_Data;
763-
Restart_Data = nullptr;
764-
}
765-
END_SU2_OMP_MASTER
766-
SU2_OMP_BARRIER
767-
}

SU2_CFD/include/solvers/CTurbSolver.hpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,16 @@ class CTurbSolver : public CScalarSolver<CTurbVariable> {
126126
CNumerics *visc_numerics,
127127
CConfig *config) final;
128128

129+
/*!
130+
* \brief Load a solution from a restart file.
131+
* \param[in] geometry - Geometrical definition of the problem.
132+
* \param[in] solver - Container vector with all of the solvers.
133+
* \param[in] config - Definition of the particular problem.
134+
* \param[in] val_iter - Current external iteration number.
135+
* \param[in] val_update_geo - Flag for updating coords and grid velocity.
136+
*/
137+
void LoadRestart(CGeometry** geometry, CSolver*** solver, CConfig* config, int val_iter, bool val_update_geo) final;
138+
129139
/*!
130140
* \brief Impose fixed values to turbulence quantities.
131141
* \details Turbulence quantities are set to far-field values in an upstream half-plane

SU2_CFD/src/solvers/CTurbSolver.cpp

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,125 @@ void CTurbSolver::BC_Fluid_Interface(CGeometry *geometry, CSolver **solver_conta
206206

207207
}
208208

209+
void CTurbSolver::LoadRestart(CGeometry** geometry, CSolver*** solver, CConfig* config, int val_iter,
210+
bool val_update_geo) {
211+
/*--- Restart the solution from file information ---*/
212+
213+
unsigned short iVar, iMesh;
214+
unsigned long iPoint, index, iChildren, Point_Fine;
215+
su2double Area_Children, Area_Parent;
216+
const su2double* Solution_Fine = nullptr;
217+
218+
string restart_filename = config->GetFilename(config->GetSolution_FileName(), "", val_iter);
219+
220+
/*--- To make this routine safe to call in parallel most of it can only be executed by one thread. ---*/
221+
SU2_OMP_MASTER {
222+
/*--- Read the restart data from either an ASCII or binary SU2 file. ---*/
223+
224+
if (config->GetRead_Binary_Restart()) {
225+
Read_SU2_Restart_Binary(geometry[MESH_0], config, restart_filename);
226+
} else {
227+
Read_SU2_Restart_ASCII(geometry[MESH_0], config, restart_filename);
228+
}
229+
230+
/*--- Skip flow variables ---*/
231+
232+
unsigned short skipVars = nDim + solver[MESH_0][FLOW_SOL]->GetnVar();
233+
234+
/*--- Adjust the number of solution variables in the incompressible
235+
restart. We always carry a space in nVar for the energy equation in the
236+
mean flow solver, but we only write it to the restart if it is active.
237+
Therefore, we must reduce skipVars here if energy is inactive so that
238+
the turbulent variables are read correctly. ---*/
239+
240+
bool incompressible = (config->GetKind_Regime() == ENUM_REGIME::INCOMPRESSIBLE);
241+
bool energy = config->GetEnergy_Equation();
242+
bool weakly_coupled_heat = config->GetWeakly_Coupled_Heat();
243+
244+
if (incompressible && ((!energy) && (!weakly_coupled_heat))) skipVars--;
245+
246+
/*--- Load data from the restart into correct containers. ---*/
247+
248+
unsigned long counter = 0, iPoint_Global = 0;
249+
for (; iPoint_Global < geometry[MESH_0]->GetGlobal_nPointDomain(); iPoint_Global++) {
250+
/*--- Retrieve local index. If this node from the restart file lives
251+
on the current processor, we will load and instantiate the vars. ---*/
252+
253+
auto iPoint_Local = geometry[MESH_0]->GetGlobal_to_Local_Point(iPoint_Global);
254+
255+
if (iPoint_Local > -1) {
256+
/*--- We need to store this point's data, so jump to the correct
257+
offset in the buffer of data from the restart file and load it. ---*/
258+
259+
index = counter * Restart_Vars[1] + skipVars;
260+
for (iVar = 0; iVar < nVar; ++iVar) nodes->SetSolution(iPoint_Local, iVar, Restart_Data[index + iVar]);
261+
262+
/*--- Increment the overall counter for how many points have been loaded. ---*/
263+
counter++;
264+
}
265+
}
266+
267+
/*--- Detect a wrong solution file ---*/
268+
269+
if (counter != nPointDomain) {
270+
SU2_MPI::Error(string("The solution file ") + restart_filename + string(" doesn't match with the mesh file!\n") +
271+
string("It could be empty lines at the end of the file."),
272+
CURRENT_FUNCTION);
273+
}
274+
275+
} // end SU2_OMP_MASTER, pre and postprocessing are thread-safe.
276+
END_SU2_OMP_MASTER
277+
SU2_OMP_BARRIER
278+
279+
/*--- MPI solution and compute the eddy viscosity ---*/
280+
281+
solver[MESH_0][TURB_SOL]->InitiateComms(geometry[MESH_0], config, SOLUTION);
282+
solver[MESH_0][TURB_SOL]->CompleteComms(geometry[MESH_0], config, SOLUTION);
283+
284+
solver[MESH_0][FLOW_SOL]->Preprocessing(geometry[MESH_0], solver[MESH_0], config, MESH_0, NO_RK_ITER,
285+
RUNTIME_FLOW_SYS, false);
286+
solver[MESH_0][TURB_SOL]->Postprocessing(geometry[MESH_0], solver[MESH_0], config, MESH_0);
287+
288+
/*--- Interpolate the solution down to the coarse multigrid levels ---*/
289+
290+
for (iMesh = 1; iMesh <= config->GetnMGLevels(); iMesh++) {
291+
SU2_OMP_FOR_STAT(omp_chunk_size)
292+
for (iPoint = 0; iPoint < geometry[iMesh]->GetnPoint(); iPoint++) {
293+
Area_Parent = geometry[iMesh]->nodes->GetVolume(iPoint);
294+
su2double Solution_Coarse[MAXNVAR] = {0.0};
295+
for (iChildren = 0; iChildren < geometry[iMesh]->nodes->GetnChildren_CV(iPoint); iChildren++) {
296+
Point_Fine = geometry[iMesh]->nodes->GetChildren_CV(iPoint, iChildren);
297+
Area_Children = geometry[iMesh - 1]->nodes->GetVolume(Point_Fine);
298+
Solution_Fine = solver[iMesh - 1][TURB_SOL]->GetNodes()->GetSolution(Point_Fine);
299+
for (iVar = 0; iVar < nVar; iVar++) {
300+
Solution_Coarse[iVar] += Solution_Fine[iVar] * Area_Children / Area_Parent;
301+
}
302+
}
303+
solver[iMesh][TURB_SOL]->GetNodes()->SetSolution(iPoint, Solution_Coarse);
304+
}
305+
END_SU2_OMP_FOR
306+
307+
solver[iMesh][TURB_SOL]->InitiateComms(geometry[iMesh], config, SOLUTION);
308+
solver[iMesh][TURB_SOL]->CompleteComms(geometry[iMesh], config, SOLUTION);
309+
310+
solver[iMesh][FLOW_SOL]->Preprocessing(geometry[iMesh], solver[iMesh], config, iMesh, NO_RK_ITER, RUNTIME_FLOW_SYS,
311+
false);
312+
solver[iMesh][TURB_SOL]->Postprocessing(geometry[iMesh], solver[iMesh], config, iMesh);
313+
}
314+
315+
/*--- Go back to single threaded execution. ---*/
316+
SU2_OMP_MASTER {
317+
/*--- Delete the class memory that is used to load the restart. ---*/
318+
319+
delete[] Restart_Vars;
320+
Restart_Vars = nullptr;
321+
delete[] Restart_Data;
322+
Restart_Data = nullptr;
323+
}
324+
END_SU2_OMP_MASTER
325+
SU2_OMP_BARRIER
326+
}
327+
209328
void CTurbSolver::Impose_Fixed_Values(const CGeometry *geometry, const CConfig *config){
210329

211330
/*--- Check whether turbulence quantities are fixed to far-field values on a half-plane. ---*/

0 commit comments

Comments
 (0)