void CSysSolve::MultiGrid_LinSolver(CSysMatrix **Jacobian, CSysVector **LinSysRes, CSysVector **LinSysSol, CMatrixVectorProduct & mat_vec, CGeometry **geometry, CConfig *config, unsigned short iMesh, unsigned short mu, double tol, unsigned long m, bool monitoring) { CSysVector A_x(*LinSysRes[iMesh]); CSysVector ResAux(*LinSysRes[iMesh]); CSysVector SolAux(*LinSysSol[iMesh]); unsigned short Smoother = config->GetKind_Linear_Solver_Prec(); /*--- Smooth the solution in the fine grid Jac_h Sol_h = Res_h, because the implementation (assumes that the initial guess is 0)... it is only possible to perform one smoothing ---*/ switch (Smoother) { case LU_SGS: Jacobian[iMesh]->ComputeLU_SGSPreconditioner(*LinSysRes[iMesh], *LinSysSol[iMesh], geometry[iMesh], config); break; case JACOBI: Jacobian[iMesh]->BuildJacobiPreconditioner(); Jacobian[iMesh]->ComputeJacobiPreconditioner(*LinSysRes[iMesh], *LinSysSol[iMesh], geometry[iMesh], config); break; case ILU: Jacobian[iMesh]->BuildILUPreconditioner(); Jacobian[iMesh]->ComputeILUPreconditioner(*LinSysRes[iMesh], *LinSysSol[iMesh], geometry[iMesh], config); break; case LINELET: Jacobian[iMesh]->BuildJacobiPreconditioner(); Jacobian[iMesh]->ComputeLineletPreconditioner(*LinSysRes[iMesh], *LinSysSol[iMesh], geometry[iMesh], config); break; } if (iMesh < config->GetMGLevels()) { /*--- Compute the residual in the finesh grid ResAux_h = Jac_h.Sol_h - Res_h ---*/ Jacobian[iMesh]->MatrixVectorProduct(*LinSysSol[iMesh], A_x, geometry[iMesh], config); ResAux -= A_x; /*--- Restrict the residual to the coarse grid Res_H = I^H_h.ResAux_h ---*/ SetRestricted_Residual(&ResAux, LinSysRes[iMesh+1], geometry[iMesh+1], config); /*--- Recursive call to MultiGrid_Cycle ---*/ for (unsigned short imu = 0; imu <= mu; imu++) { if (iMesh == config->GetMGLevels()-2) MultiGrid_LinSolver(Jacobian, LinSysRes, LinSysSol, mat_vec, geometry, config, iMesh+1, 0, tol, m, monitoring); else MultiGrid_LinSolver(Jacobian, LinSysRes, LinSysSol, mat_vec, geometry, config, iMesh+1, mu, tol, m, monitoring); } /*--- Prolongate solution to the fine grid solution SolAux_h = I^h_H.Sol_H ---*/ SetProlongated_Solution(&SolAux, LinSysSol[iMesh+1], geometry[iMesh+1], config); /*--- Update the fine grid solution Sol_h += SolAux_h ---*/ *LinSysSol[iMesh] += config->GetDamp_Correc_Prolong()*SolAux; } }
void CMultiGridIntegration::MultiGrid_Iteration(CGeometry ***geometry, CSolver ****solver_container, CNumerics *****numerics_container, CConfig **config, unsigned short RunTime_EqSystem, unsigned long Iteration, unsigned short iZone) { unsigned short FinestMesh, iMGLevel; double monitor = 1.0; const bool restart = (config[iZone]->GetRestart() || config[iZone]->GetRestart_Flow()); const bool startup_multigrid = ((config[iZone]->GetRestart_Flow()) && (RunTime_EqSystem == RUNTIME_FLOW_SYS) && (Iteration == 0)); const bool direct = ((config[iZone]->GetKind_Solver() == EULER) || (config[iZone]->GetKind_Solver() == NAVIER_STOKES) || (config[iZone]->GetKind_Solver() == RANS) || (config[iZone]->GetKind_Solver() == TNE2_EULER) || (config[iZone]->GetKind_Solver() == TNE2_NAVIER_STOKES) || (config[iZone]->GetKind_Solver() == FLUID_STRUCTURE_EULER) || (config[iZone]->GetKind_Solver() == FLUID_STRUCTURE_NAVIER_STOKES) || (config[iZone]->GetKind_Solver() == FLUID_STRUCTURE_RANS)); const unsigned short SolContainer_Position = config[iZone]->GetContainerPosition(RunTime_EqSystem); /*--- If low fidelity simulation ---*/ if (config[iZone]->GetLowFidelitySim()) config[iZone]->SetFinestMesh(MESH_1); /*--- If restart, update multigrid levels at the first multigrid iteration ---*/ if ((restart && (Iteration == config[iZone]->GetnStartUpIter())) || startup_multigrid) { for (iMGLevel = 0; iMGLevel < config[iZone]->GetMGLevels(); iMGLevel++) { SetRestricted_Solution(RunTime_EqSystem, solver_container[iZone][iMGLevel][SolContainer_Position], solver_container[iZone][iMGLevel+1][SolContainer_Position], geometry[iZone][iMGLevel], geometry[iZone][iMGLevel+1], config[iZone]); } } /*--- Full multigrid strategy and start up with fine grid only works with the direct problem ---*/ if (!config[iZone]->GetRestart() && config[iZone]->GetFullMG() && direct && ( GetConvergence_FullMG() && (config[iZone]->GetFinestMesh() != MESH_0 ))) { SetProlongated_Solution(RunTime_EqSystem, solver_container[iZone][config[iZone]->GetFinestMesh()-1][SolContainer_Position], solver_container[iZone][config[iZone]->GetFinestMesh()][SolContainer_Position], geometry[iZone][config[iZone]->GetFinestMesh()-1], geometry[iZone][config[iZone]->GetFinestMesh()], config[iZone]); config[iZone]->SubtractFinestMesh(); } /*--- Set the current finest grid (full multigrid strategy) ---*/ FinestMesh = config[iZone]->GetFinestMesh(); /*--- Perform the Full Approximation Scheme multigrid ---*/ MultiGrid_Cycle(geometry, solver_container, numerics_container, config, FinestMesh, config[iZone]->GetMGCycle(), RunTime_EqSystem, Iteration, iZone); /*--- Computes primitive variables and gradients in the finest mesh (useful for the next solver (turbulence) and output ---*/ solver_container[iZone][MESH_0][SolContainer_Position]->Preprocessing(geometry[iZone][MESH_0], solver_container[iZone][MESH_0], config[iZone], MESH_0, NO_RK_ITER, RunTime_EqSystem, true); /*--- Compute non-dimensional parameters and the convergence monitor ---*/ NonDimensional_Parameters(geometry[iZone], solver_container[iZone], numerics_container[iZone], config[iZone], FinestMesh, RunTime_EqSystem, Iteration, &monitor); /*--- Convergence strategy ---*/ Convergence_Monitoring(geometry[iZone][FinestMesh], config[iZone], Iteration, monitor); }