@@ -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+
209328void 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