00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #ifndef STOKESFLOWSOLVER_HPP_
00037 #define STOKESFLOWSOLVER_HPP_
00038
00039 #include "AbstractContinuumMechanicsSolver.hpp"
00040 #include "LinearSystem.hpp"
00041 #include "LinearBasisFunction.hpp"
00042 #include "QuadraticBasisFunction.hpp"
00043 #include "Timer.hpp"
00044 #include "PetscMatTools.hpp"
00045 #include "PetscVecTools.hpp"
00046 #include "StokesFlowProblemDefinition.hpp"
00047 #include "StokesFlowAssembler.hpp"
00048 #include "StokesFlowPreconditionerAssembler.hpp"
00049 #include "ContinuumMechanicsNeumannBcsAssembler.hpp"
00050
00054 template<unsigned DIM>
00055 class StokesFlowSolver : public AbstractContinuumMechanicsSolver<DIM>
00056 {
00057 friend class TestStokesFlowSolver;
00058
00059 private:
00061 StokesFlowProblemDefinition<DIM>& mrProblemDefinition;
00062
00064 StokesFlowAssembler<DIM>* mpStokesFlowAssembler;
00065
00070 StokesFlowPreconditionerAssembler<DIM>* mpStokesFlowPreconditionerAssembler;
00071
00076 ContinuumMechanicsNeumannBcsAssembler<DIM>* mpNeumannBcsAssembler;
00077
00083 double mKspAbsoluteTol;
00084
00088 void AssembleSystem();
00089
00090 public:
00091
00099 StokesFlowSolver(AbstractTetrahedralMesh<DIM,DIM>& rQuadMesh,
00100 StokesFlowProblemDefinition<DIM>& rProblemDefinition,
00101 std::string outputDirectory);
00102
00106 virtual ~StokesFlowSolver();
00107
00111 void Solve();
00112
00119 void SetKspAbsoluteTolerance(double kspAbsoluteTolerance);
00120
00121
00126 std::vector<c_vector<double,DIM> >& rGetSpatialSolution();
00127
00132 std::vector<c_vector<double,DIM> >& rGetVelocities();
00133 };
00134
00136
00138
00139
00140 template<unsigned DIM>
00141 StokesFlowSolver<DIM>::StokesFlowSolver(AbstractTetrahedralMesh<DIM,DIM>& rQuadMesh,
00142 StokesFlowProblemDefinition<DIM>& rProblemDefinition,
00143 std::string outputDirectory)
00144 : AbstractContinuumMechanicsSolver<DIM>(rQuadMesh, rProblemDefinition, outputDirectory, INCOMPRESSIBLE),
00145 mrProblemDefinition(rProblemDefinition),
00146 mKspAbsoluteTol(-1)
00147 {
00148 assert(DIM==2 || DIM==3);
00149 assert(!mrProblemDefinition.rGetDirichletNodes().empty());
00150
00151 mpStokesFlowAssembler = new StokesFlowAssembler<DIM>(&this->mrQuadMesh, &mrProblemDefinition);
00152 mpStokesFlowPreconditionerAssembler = new StokesFlowPreconditionerAssembler<DIM>(&this->mrQuadMesh, &mrProblemDefinition);
00153 mpNeumannBcsAssembler = new ContinuumMechanicsNeumannBcsAssembler<DIM>(&this->mrQuadMesh, &mrProblemDefinition);
00154 }
00155
00156 template<unsigned DIM>
00157 StokesFlowSolver<DIM>::~StokesFlowSolver()
00158 {
00159 delete mpStokesFlowAssembler;
00160 delete mpStokesFlowPreconditionerAssembler;
00161 delete mpNeumannBcsAssembler;
00162 }
00163
00164 template<unsigned DIM>
00165 void StokesFlowSolver<DIM>::Solve()
00166 {
00167 mrProblemDefinition.Validate();
00168
00169 if(this->mVerbose)
00170 {
00171 Timer::Reset();
00172 }
00173
00174
00175 MechanicsEventHandler::BeginEvent(MechanicsEventHandler::ASSEMBLE);
00176 AssembleSystem();
00177 MechanicsEventHandler::EndEvent(MechanicsEventHandler::ASSEMBLE);
00178
00179 if(this->mVerbose)
00180 {
00181 Timer::PrintAndReset("AssembleSystem");
00182 }
00183
00184
00185
00186
00187
00188
00189 MechanicsEventHandler::BeginEvent(MechanicsEventHandler::SOLVE);
00190
00191 Vec solution;
00192 VecDuplicate(this->mLinearSystemRhsVector,&solution);
00193 PetscVecTools::Zero(solution);
00194
00195 KSP solver;
00196 KSPCreate(PETSC_COMM_WORLD,&solver);
00197 #if ( PETSC_VERSION_MAJOR==3 && PETSC_VERSION_MINOR>=5 )
00198 KSPSetOperators(solver, this->mSystemLhsMatrix, this->mPreconditionMatrix);
00199 #else
00200 KSPSetOperators(solver, this->mSystemLhsMatrix, this->mPreconditionMatrix, DIFFERENT_NONZERO_PATTERN );
00201 #endif
00202 KSPSetType(solver, KSPGMRES);
00203
00204 if (mKspAbsoluteTol < 0)
00205 {
00206 double ksp_rel_tol = 1e-6;
00207 KSPSetTolerances(solver, ksp_rel_tol, PETSC_DEFAULT, PETSC_DEFAULT, 10000 );
00208 }
00209 else
00210 {
00211 KSPSetTolerances(solver, 1e-16, mKspAbsoluteTol, PETSC_DEFAULT, 10000 );
00212 }
00213 unsigned num_restarts = 100;
00214 KSPGMRESSetRestart(solver,num_restarts);
00215
00216 PC pc;
00217 KSPGetPC(solver, &pc);
00218 PCSetType(pc, PCJACOBI);
00219
00220 KSPSetUp(solver);
00221
00222 KSPSetFromOptions(solver);
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244 if(this->mVerbose)
00245 {
00246 Timer::PrintAndReset("KSP Setup");
00247 }
00248
00249 KSPSolve(solver,this->mLinearSystemRhsVector,solution);
00250
00251 KSPConvergedReason reason;
00252 KSPGetConvergedReason(solver,&reason);
00253 KSPEXCEPT(reason);
00254
00255 if(this->mVerbose)
00256 {
00257 Timer::PrintAndReset("KSP Solve");
00258 int num_iters;
00259 KSPGetIterationNumber(solver, &num_iters);
00260 std::cout << "[" << PetscTools::GetMyRank() << "]: Num iterations = " << num_iters << "\n" << std::flush;
00261 }
00262
00263 MechanicsEventHandler::EndEvent(MechanicsEventHandler::SOLVE);
00264
00265
00266 ReplicatableVector solution_repl(solution);
00267 for (unsigned i=0; i<this->mNumDofs; i++)
00268 {
00269 this->mCurrentSolution[i] = solution_repl[i];
00270 }
00271
00272
00273
00274
00275 this->RemovePressureDummyValuesThroughLinearInterpolation();
00276
00277 PetscTools::Destroy(solution);
00278 KSPDestroy(PETSC_DESTROY_PARAM(solver));
00279
00280 this->WriteCurrentSpatialSolution("flow_solution", "nodes");
00281 this->WriteCurrentPressureSolution();
00282 }
00283
00284
00285
00286 template<unsigned DIM>
00287 void StokesFlowSolver<DIM>::AssembleSystem()
00288 {
00289
00290 mpStokesFlowAssembler->SetMatrixToAssemble(this->mSystemLhsMatrix, true);
00291 mpStokesFlowAssembler->SetVectorToAssemble(this->mLinearSystemRhsVector, true);
00292 mpStokesFlowAssembler->Assemble();
00293
00294 mpStokesFlowPreconditionerAssembler->SetMatrixToAssemble(this->mPreconditionMatrix, true);
00295 mpStokesFlowPreconditionerAssembler->AssembleMatrix();
00296
00297 mpNeumannBcsAssembler->SetVectorToAssemble(this->mLinearSystemRhsVector, false );
00298 mpNeumannBcsAssembler->AssembleVector();
00299
00300 PetscVecTools::Finalise(this->mLinearSystemRhsVector);
00301 PetscMatTools::SwitchWriteMode(this->mSystemLhsMatrix);
00302 PetscMatTools::SwitchWriteMode(this->mPreconditionMatrix);
00303
00304
00305
00306
00307
00308
00309
00310
00311 this->AddIdentityBlockForDummyPressureVariables(LINEAR_PROBLEM);
00312 this->ApplyDirichletBoundaryConditions(LINEAR_PROBLEM, true);
00313
00314 PetscVecTools::Finalise(this->mLinearSystemRhsVector);
00315 PetscMatTools::Finalise(this->mSystemLhsMatrix);
00316 PetscMatTools::Finalise(this->mPreconditionMatrix);
00317 }
00318
00319 template<unsigned DIM>
00320 void StokesFlowSolver<DIM>::SetKspAbsoluteTolerance(double kspAbsoluteTolerance)
00321 {
00322 assert(kspAbsoluteTolerance > 0);
00323 mKspAbsoluteTol = kspAbsoluteTolerance;
00324 }
00325
00326 template<unsigned DIM>
00327 std::vector<c_vector<double,DIM> >& StokesFlowSolver<DIM>::rGetSpatialSolution()
00328 {
00329 this->mSpatialSolution.resize(this->mrQuadMesh.GetNumNodes(), zero_vector<double>(DIM));
00330 for (unsigned i=0; i<this->mrQuadMesh.GetNumNodes(); i++)
00331 {
00332 for (unsigned j=0; j<DIM; j++)
00333 {
00334
00335 this->mSpatialSolution[i](j) = this->mCurrentSolution[(DIM+1)*i+j];
00336 }
00337 }
00338 return this->mSpatialSolution;
00339 }
00340
00341 template<unsigned DIM>
00342 std::vector<c_vector<double,DIM> >& StokesFlowSolver<DIM>::rGetVelocities()
00343 {
00344 return rGetSpatialSolution();
00345 }
00346
00347
00348
00349 #endif