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;
    
  }
 
}
Exemple #2
0
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);
  
}