void Problem::readLastVectorALETimeAdvance ( vectorPtr_Type fluidDisp, const std::string loadInitSol) { using namespace LifeV; typedef FSIOperator::mesh_Type mesh_Type; //We still need to load the last vector for ALE std::string iterationString = loadInitSol; fluidDisp.reset (new vector_Type (M_fsi->FSIOper()->mmFESpace().map(), LifeV::Unique) ); //Setting the exporterData to read: ALE problem LifeV::ExporterData<mesh_Type> initSolFluidDisp (LifeV::ExporterData<mesh_Type>::VectorField, "f-displacement." + iterationString, M_fsi->FSIOper()->mmFESpacePtr(), fluidDisp, UInt (0), LifeV::ExporterData<mesh_Type>::UnsteadyRegime ); //Initializing *fluidDisp *= 0.0; //Reading M_importerFluid->readVariable (initSolFluidDisp); //Fluid df //Output std::cout << "Norm of the df " << fluidDisp->norm2() << std::endl; //This is ugly but it's the only way I have figured out at the moment if ( M_data->method().compare ("monolithicGI") == 0 ) { //Don't be scared by the ten. The goal of 10 is just to make the first if fail M_fsi->FSIOper()->setALEVectorInStencil ( fluidDisp, 10, true ); } //Setting the vector in the stencil M_fsi->FSIOper()->ALETimeAdvance()->shiftRight ( *fluidDisp ); }
void TimeIterationPolicyLinear<mesh_Type, AssemblyPolicy, SolverPolicy>:: iterate ( vectorPtr_Type solution, bcContainerPtr_Type bchandler, const Real& currentTime ) { Real rhsIterNorm ( 0.0 ); // // STEP 1: Updating the system // displayer().leaderPrint ( "Updating the system... " ); *M_rhs = 0.0; M_systemMatrix.reset ( new matrix_Type ( *M_solutionMap ) ); AssemblyPolicy::assembleSystem ( M_systemMatrix, M_rhs, solution, SolverPolicy::preconditioner() ); displayer().leaderPrint ( "done\n" ); // // STEP 2: Applying the boundary conditions // displayer().leaderPrint ( "Applying BC... " ); bcManage ( *M_systemMatrix, *M_rhs, *uFESpace()->mesh(), uFESpace()->dof(), *bchandler, uFESpace()->feBd(), 1.0, currentTime ); M_systemMatrix->globalAssemble(); displayer().leaderPrint ( "done\n" ); // Extra information if we want to know the exact residual if ( M_computeResidual ) { rhsIterNorm = M_rhs->norm2(); } // // STEP 3: Solving the system // displayer().leaderPrint ( "Solving the system... \n" ); SolverPolicy::solve ( M_systemMatrix, M_rhs, solution ); if ( M_computeResidual ) { vector_Type Ax ( solution->map() ); vector_Type res ( *M_rhs ); M_systemMatrix->matrixPtr()->Apply ( solution->epetraVector(), Ax.epetraVector() ); res.epetraVector().Update ( -1, Ax.epetraVector(), 1 ); Real residual; res.norm2 ( &residual ); residual /= rhsIterNorm; displayer().leaderPrint ( "Scaled residual: ", residual, "\n" ); } }
void InitPolicyInterpolation< mesh_Type >:: initSimulation ( bcContainerPtr_Type /*bchandler*/, vectorPtr_Type solution ) { ASSERT ( problem()->hasExactSolution(), "Error: You cannot use the interpolation method if the problem has not an analytical solution." ); Real currentTime = initialTime() - timestep() * bdf()->order(); UInt pressureOffset = uFESpace()->fieldDim() * uFESpace()->dof().numTotalDof(); vectorPtr_Type velocity; velocity.reset ( new vector_Type ( uFESpace()->map(), Unique ) ); vectorPtr_Type pressure; pressure.reset ( new vector_Type ( pFESpace()->map(), Unique ) ); *solution = 0.0; uFESpace()->interpolate ( problem()->uexact(), *velocity, currentTime ); pFESpace()->interpolate ( problem()->pexact(), *pressure, currentTime ); solution->add ( *velocity ); solution->add ( *pressure, pressureOffset ); bdf()->setInitialCondition ( *solution ); currentTime += timestep(); for ( ; currentTime <= initialTime() + timestep() / 2.0; currentTime += timestep() ) { *solution = 0.0; *velocity = 0.0; *pressure = 0.0; uFESpace()->interpolate ( problem()->uexact(), *velocity, currentTime ); pFESpace()->interpolate ( problem()->pexact(), *pressure, currentTime ); solution->add ( *velocity ); solution->add ( *pressure, pressureOffset ); // Updating bdf bdf()->shiftRight ( *solution ); } }
Real LinearSolver::computeResidual ( vectorPtr_Type solutionPtr ) { if ( !M_operator || !M_rhs ) { M_displayer->leaderPrint ( "SLV- WARNING: LinearSolver can not compute the residual if the operator and the RHS are not set!\n" ); return -1; } vector_Type Ax ( solutionPtr->map() ); vector_Type residual ( *M_rhs ); M_operator->Apply ( solutionPtr->epetraVector(), Ax.epetraVector() ); residual.epetraVector().Update ( 1, Ax.epetraVector(), -1 ); Real residualNorm; residual.norm2 ( &residualNorm ); return residualNorm; }
void FSISolver::initialize(vectorPtr_Type u0, vectorPtr_Type v0) { if (!u0.get()) { u0.reset(new vector_Type(*M_oper->couplingVariableMap())); M_oper->initialize(*u0); // couplingVariableMap() M_oper->initializeBDF(*u0); } else { M_oper->initialize(*u0); // couplingVariableMap()//copy M_oper->initializeBDF(*u0); } if (!v0.get()) M_oper->setSolutionDerivative(*u0); // couplingVariableMap()//copy // M_oper->setSolutionDerivative(u0); // couplingVariableMap()//copy else M_oper->setSolutionDerivative(*v0); //M_oper->setSolutionDerivative(v0); //M_oper->setupBDF(*M_lambda); }
void Problem::readLastVectorSolidTimeAdvance ( vectorPtr_Type solidDisp, LifeV::UInt iterInit, std::string iterationString) { using namespace LifeV; typedef FSIOperator::mesh_Type mesh_Type; //Reading another vector for the solidTimeAdvance since its BDF has the same order //as the other ones but since the orderDerivative = 2, the size of the stencil is //orderBDF + 1 solidDisp.reset (new vector_Type (M_fsi->FSIOper()->dFESpace().map(), LifeV::Unique) ); *solidDisp *= 0.0; LifeV::ExporterData<mesh_Type> initSolSolidDisp (LifeV::ExporterData<mesh_Type>::VectorField, "s-displacement." + iterationString, M_fsi->FSIOper()->dFESpacePtr(), solidDisp, UInt (0), LifeV::ExporterData<mesh_Type>::UnsteadyRegime ); M_importerSolid->readVariable (initSolSolidDisp); //Solid d M_fsi->FSIOper()->setSolidVectorInStencil ( solidDisp, iterInit ); }
void MonolithicBlockComposedDN::coupler (mapPtr_Type& map, const std::map<ID, ID>& locDofMap, const vectorPtr_Type& numerationInterface, const Real& timeStep, const Real& coefficient, const Real& rescaleFactor) { UInt totalDofs ( map->map (Unique)->NumGlobalElements() ); UInt solidAndFluid (M_offset[solid] + M_FESpace[solid]->map().map (Unique)->NumGlobalElements() ); matrixPtr_Type coupling (new matrix_Type (*map) ); couplingMatrix ( coupling, (*M_couplingFlags) [solid], M_FESpace, M_offset, locDofMap, numerationInterface, timeStep, 1., coefficient, rescaleFactor); coupling->insertValueDiagonal ( 1., M_offset[fluid], M_offset[solid] ); coupling->insertValueDiagonal ( 1., solidAndFluid, totalDofs ); M_coupling.push_back (coupling); coupling.reset (new matrix_Type (*map) ); couplingMatrix ( coupling, (*M_couplingFlags) [fluid], M_FESpace, M_offset, locDofMap, numerationInterface, timeStep, 1., coefficient, rescaleFactor); coupling->insertValueDiagonal ( 1. , M_offset[solid], solidAndFluid ); coupling->insertValueDiagonal ( 1. , solidAndFluid + nDimensions * numerationInterface->map().map (Unique)->NumGlobalElements(), totalDofs ); M_coupling.push_back (coupling); }
void Problem::restartFSI ( GetPot const& data_file) { using namespace LifeV; typedef FSIOperator::mesh_Type mesh_Type; //Creating the pointer to the filter std::string const importerType = data_file ( "importer/type", "ensight"); std::string const fluidName = data_file ( "importer/fluid/filename", "fluid"); std::string const solidName = data_file ( "importer/solid/filename", "solid"); std::string const loadInitSol = data_file ( "importer/initSol", "00000"); std::string const loadInitSolFD = data_file ("importer/initSolFD", "-1"); std::string iterationString; M_Tstart = data_file ( "fluid/time_discretization/initialtime", 0.); std::cout << "The file for fluid is : " << fluidName << std::endl; std::cout << "The file for solid is : " << solidName << std::endl; std::cout << "The importerType is : " << importerType << std::endl; std::cout << "The iteration is : " << loadInitSol << std::endl; std::cout << "For the fluid disp is : " << loadInitSolFD << std::endl; std::cout << "Starting time : " << M_Tstart << std::endl; //At the moment the restart works only if BDF methods are used in time. // For Newmark method a almost new implementation is needed std::string methodFluid = data_file ( "fluid/time_discretization/method", "Newmark"); std::string methodSolid = data_file ( "solid/time_discretization/method", "Newmark"); std::string methodALE = data_file ( "mesh_motion/time_discretization/method", "Newmark"); #ifdef HAVE_HDF5 if (importerType.compare ("hdf5") == 0) { M_importerFluid.reset ( new hdf5Filter_Type ( data_file, fluidName) ); M_importerSolid.reset ( new hdf5Filter_Type ( data_file, solidName) ); } else #endif { if (importerType.compare ("none") == 0) { M_importerFluid.reset ( new ExporterEmpty<mesh_Type > ( data_file, M_fsi->FSIOper()->uFESpace().mesh(), "fluid", M_fsi->FSIOper()->uFESpace().map().comm().MyPID() ) ); M_importerSolid.reset ( new ExporterEmpty<mesh_Type > ( data_file, M_fsi->FSIOper()->dFESpace().mesh(), "solid", M_fsi->FSIOper()->uFESpace().map().comm().MyPID() ) ); } else { M_importerFluid.reset ( new ensightFilter_Type ( data_file, fluidName) ); M_importerSolid.reset ( new ensightFilter_Type ( data_file, solidName) ); } } M_importerFluid->setMeshProcId (M_fsi->FSIOper()->uFESpace().mesh(), M_fsi->FSIOper()->uFESpace().map().comm().MyPID() ); M_importerSolid->setMeshProcId (M_fsi->FSIOper()->dFESpace().mesh(), M_fsi->FSIOper()->dFESpace().map().comm().MyPID() ); //Each of the vectors of the stencils has the dimension of the big vector //Performing a cycle of the size of the timeAdvance classes for each problem //The size of TimeAdvanceClass depends on the order of the BDF (data file) //The hypothesis used for this method is that the three TimeAdvance classes have the same size iterationString = loadInitSol; UInt iterInit; vectorPtr_Type vel; vectorPtr_Type pressure; vectorPtr_Type solidDisp; vectorPtr_Type fluidDisp; for (iterInit = 0; iterInit < M_fsi->FSIOper()->fluidTimeAdvance()->size(); iterInit++ ) { //It should work just initializing the timeAdvance classes //Three stencils are needed (Fluid-Structure-Geometric) vel.reset (new vector_Type (M_fsi->FSIOper()->uFESpace().map(), LifeV::Unique) ); pressure.reset (new vector_Type (M_fsi->FSIOper()->pFESpace().map(), LifeV::Unique) ); solidDisp.reset (new vector_Type (M_fsi->FSIOper()->dFESpace().map(), LifeV::Unique) ); //First the three fields are read at the same time //Creating the exporter data for the fields //Fluid LifeV::ExporterData<mesh_Type> initSolFluidVel (LifeV::ExporterData<mesh_Type>::VectorField, std::string ("f-velocity." + iterationString), M_fsi->FSIOper()->uFESpacePtr(), vel, UInt (0), LifeV::ExporterData<mesh_Type>::UnsteadyRegime ); LifeV::ExporterData<mesh_Type> initSolFluidPress (LifeV::ExporterData<mesh_Type>::ScalarField, std::string ("f-pressure." + iterationString), M_fsi->FSIOper()->pFESpacePtr(), pressure, UInt (0), LifeV::ExporterData<mesh_Type>::UnsteadyRegime ); //Structure LifeV::ExporterData<mesh_Type> initSolSolidDisp (LifeV::ExporterData<mesh_Type>::VectorField, "s-displacement." + iterationString, M_fsi->FSIOper()->dFESpacePtr(), solidDisp, UInt (0), LifeV::ExporterData<mesh_Type>::UnsteadyRegime ); //Initialization of the vectors used to read *vel *= 0.0; *pressure *= 0.0; *solidDisp *= 0.0; //load of the solutions M_importerFluid->readVariable (initSolFluidVel); //Fluid u M_importerFluid->readVariable (initSolFluidPress); //Fluid p M_importerSolid->readVariable (initSolSolidDisp); //Solid d std::cout << "Norm of the vel " << vel->norm2() << std::endl; std::cout << "Norm of the pressure " << pressure->norm2() << std::endl; std::cout << "Norm of the solid " << solidDisp->norm2() << std::endl; //We send the vectors to the FSIMonolithic class using the interface of FSIOper M_fsi->FSIOper()->setVectorInStencils (vel, pressure, solidDisp, iterInit ) ; //Updating string name int iterations = std::atoi (iterationString.c_str() ); iterations--; std::ostringstream iter; iter.fill ( '0' ); iter << std::setw (5) << ( iterations ); iterationString = iter.str(); } readLastVectorSolidTimeAdvance ( solidDisp, iterInit, iterationString ); //For the ALE timeAdvance, one should be careful on the vectors that are used //to compute the RHSFirstDerivative. That is why we first load the stencil using previous //vectors and then we read the last one iterationString = loadInitSol; int iterationStartALE = std::atoi (iterationString.c_str() ); iterationStartALE--; std::ostringstream iter; iter.fill ( '0' ); iter << std::setw (5) << ( iterationStartALE ); iterationString = iter.str(); std::cout << "The load init sol is: " << loadInitSol << std::endl; std::cout << "The first read sol is: " << iterationString << std::endl; for (iterInit = 0; iterInit < M_fsi->FSIOper()->ALETimeAdvance()->size(); iterInit++ ) { //Reset the pointer fluidDisp.reset (new vector_Type (M_fsi->FSIOper()->mmFESpace().map(), LifeV::Unique) ); //Setting the exporterData to read: ALE problem LifeV::ExporterData<mesh_Type> initSolFluidDisp (LifeV::ExporterData<mesh_Type>::VectorField, "f-displacement." + iterationString, M_fsi->FSIOper()->mmFESpacePtr(), fluidDisp, UInt (0), LifeV::ExporterData<mesh_Type>::UnsteadyRegime ); //Initializing *fluidDisp *= 0.0; //Reading M_importerFluid->readVariable (initSolFluidDisp); //Fluid df //Output std::cout << "Norm of the df " << fluidDisp->norm2() << std::endl; //Setting the vector in the stencil M_fsi->FSIOper()->setALEVectorInStencil ( fluidDisp, iterInit, false ); //Updating string name int iterations = std::atoi (iterationString.c_str() ); iterations--; std::ostringstream iter; iter.fill ( '0' ); iter << std::setw (5) << ( iterations ); iterationString = iter.str(); } //Initializing the vector for the RHS terms of the formulas M_fsi->FSIOper()->finalizeRestart(); //Need to read still one vector and shiftright it. readLastVectorALETimeAdvance ( fluidDisp, loadInitSol ); //This are used to export the loaded solution to check it is correct. vel.reset (new vector_Type (M_fsi->FSIOper()->uFESpace().map(), LifeV::Unique) ); pressure.reset (new vector_Type (M_fsi->FSIOper()->pFESpace().map(), LifeV::Unique) ); fluidDisp.reset (new vector_Type (M_fsi->FSIOper()->mmFESpace().map(), LifeV::Unique) ); M_velAndPressure.reset ( new vector_Type ( M_fsi->FSIOper()->fluid().getMap(), M_importerFluid->mapType() ) ); M_velAndPressure->subset (*pressure, pressure->map(), UInt (0), (UInt) 3 * M_fsi->FSIOper()->uFESpace().dof().numTotalDof() ); *M_velAndPressure += *vel; M_fluidDisp.reset ( new vector_Type ( *fluidDisp, M_importerFluid->mapType() ) ); M_solidDisp.reset ( new vector_Type ( *solidDisp, M_importerSolid->mapType() ) ); }
void TimeIterationPolicyNonlinear<mesh_Type, AssemblyPolicy, SolverPolicy>:: iterate ( vectorPtr_Type solution, bcContainerPtr_Type bchandler, const Real& currentTime ) { int subiter = 0; Real normRhs ( 0.0 ); Real nonLinearResidual ( 0.0 ); Real rhsIterNorm ( 0.0 ); do { // // STEP 1: Updating the system // displayer().leaderPrint ( "Updating the system... " ); *M_rhs = 0.0; M_systemMatrix.reset ( new matrix_Type ( *M_solutionMap ) ); AssemblyPolicy::assembleSystem ( M_systemMatrix, M_rhs, solution, SolverPolicy::preconditioner() ); displayer().leaderPrint ( "done\n" ); // // STEP 2: Applying the boundary conditions // displayer().leaderPrint ( "Applying BC... " ); bcManage ( *M_systemMatrix, *M_rhs, *uFESpace()->mesh(), uFESpace()->dof(), *bchandler, uFESpace()->feBd(), 1.0, currentTime ); M_systemMatrix->globalAssemble(); displayer().leaderPrint ( "done\n" ); // Norm of the rhs needed for the nonlinear convergence test if ( subiter == 0 ) { normRhs = M_rhs->norm2(); } // // STEP 3: Computing the residual // // Computing the RHS as RHS=b-Ax_k vector_Type Ax ( solution->map() ); M_systemMatrix->matrixPtr()->Apply ( solution->epetraVector(), Ax.epetraVector() ); Ax.epetraVector().Update (-1, M_rhs->epetraVector(), 1); nonLinearResidual = Ax.norm2(); displayer().leaderPrint ( "Nonlinear residual : ", nonLinearResidual, "\n" ); displayer().leaderPrint ( "Nonlinear residual (scaled) : ", nonLinearResidual / normRhs, "\n" ); if ( nonLinearResidual > M_nonLinearTolerance * normRhs ) { displayer().leaderPrint ( "---\nSubiteration [", ++subiter, "]\n" ); // Extra information if we want to know the exact residual if ( M_computeResidual ) { rhsIterNorm = M_rhs->norm2(); } // // Solving the system // displayer().leaderPrint ( "Solving the system... \n" ); *solution = 0.0; SolverPolicy::solve ( M_systemMatrix, M_rhs, solution ); // int numIter = SolverPolicy::solve( M_systemMatrix, M_rhs, solution ); // numIterSum += numIter; // if ( M_computeResidual ) { vector_Type Ax ( solution->map() ); vector_Type res ( *M_rhs ); M_systemMatrix->matrixPtr()->Apply ( solution->epetraVector(), Ax.epetraVector() ); res.epetraVector().Update ( -1, Ax.epetraVector(), 1 ); Real residual; res.norm2 ( &residual ); residual /= rhsIterNorm; displayer().leaderPrint ( "Scaled residual: ", residual, "\n" ); } } } while ( nonLinearResidual > M_nonLinearTolerance * normRhs ); displayer().leaderPrint ( "Nonlinear iterations : ", subiter, "\n" ); }
// =================================================== // Methods // =================================================== Int LinearSolver::solve ( vectorPtr_Type solutionPtr ) { // Build preconditioners if needed bool retry ( true ); if ( !isPreconditionerSet() || !M_reusePreconditioner ) { buildPreconditioner(); // There will be no retry if the preconditioner is recomputed retry = false; } else { if ( !M_silent ) { M_displayer->leaderPrint ( "SLV- Reusing precond ...\n" ); } } if ( M_rhs.get() == 0 || M_operator == 0 ) { M_displayer->leaderPrint ( "SLV- ERROR: LinearSolver failed to set up correctly!\n" ); return -1; } // Setup the Solver Operator setupSolverOperator(); // Reset status informations bool failure = false; this->resetStatus(); M_solverOperator->resetStatus(); // Solve the linear system LifeChrono chrono; chrono.start(); M_solverOperator->ApplyInverse ( M_rhs->epetraVector(), solutionPtr->epetraVector() ); M_converged = M_solverOperator->hasConverged(); M_lossOfPrecision = M_solverOperator->isLossOfAccuracyDetected(); chrono.stop(); if ( !M_silent ) { M_displayer->leaderPrintMax ( "SLV- Solution time: " , chrono.diff(), " s." ); } // Getting informations post-solve Int numIters = M_solverOperator->numIterations(); // Second run recomputing the preconditioner // This is done only if the preconditioner has not been // already recomputed and if it is a LifeV preconditioner. if ( M_converged != SolverOperator_Type::yes && retry && M_preconditioner ) { M_displayer->leaderPrint ( "SLV- Iterative solver failed, numiter = " , numIters, "\n" ); M_displayer->leaderPrint ( "SLV- retrying:\n" ); buildPreconditioner(); // Solving again, but only once (retry = false) chrono.start(); M_solverOperator->ApplyInverse ( M_rhs->epetraVector(), solutionPtr->epetraVector() ); M_converged = M_solverOperator->hasConverged(); M_lossOfPrecision = M_solverOperator->isLossOfAccuracyDetected(); chrono.stop(); if ( !M_silent ) { M_displayer->leaderPrintMax ( "SLV- Solution time: " , chrono.diff(), " s." ); } } if ( M_lossOfPrecision == SolverOperator_Type::yes ) { M_displayer->leaderPrint ( "SLV- WARNING: Loss of accuracy detected!\n" ); failure = true; } if ( M_converged == SolverOperator_Type::yes ) { if ( !M_silent ) { M_displayer->leaderPrint ( "SLV- Convergence in " , numIters, " iterations\n" ); } M_maxNumItersReached = SolverOperator_Type::no; } else { M_displayer->leaderPrint ( "SLV- WARNING: Solver failed to converged to the desired precision!\n" ); M_maxNumItersReached = SolverOperator_Type::yes; failure = true; } // If quitOnFailure is enabled and if some problems occur // the simulation is stopped if ( M_quitOnFailure && failure ) { exit ( -1 ); } // Reset the solver to free the internal pointers M_solverOperator->resetSolver(); // If the number of iterations reaches the threshold of maxIterForReuse // we reset the preconditioners to force to solver to recompute it next // time if ( numIters > M_maxItersForReuse ) { resetPreconditioner(); } return numIters; }