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 KSPSetOperators(solver, this->mSystemLhsMatrix, this->mPreconditionMatrix, DIFFERENT_NONZERO_PATTERN );
00198 KSPSetType(solver, KSPGMRES);
00199
00200 if (mKspAbsoluteTol < 0)
00201 {
00202 double ksp_rel_tol = 1e-6;
00203 KSPSetTolerances(solver, ksp_rel_tol, PETSC_DEFAULT, PETSC_DEFAULT, 10000 );
00204 }
00205 else
00206 {
00207 KSPSetTolerances(solver, 1e-16, mKspAbsoluteTol, PETSC_DEFAULT, 10000 );
00208 }
00209 unsigned num_restarts = 100;
00210 KSPGMRESSetRestart(solver,num_restarts);
00211
00212 PC pc;
00213 KSPGetPC(solver, &pc);
00214 PCSetType(pc, PCJACOBI);
00215
00216 KSPSetUp(solver);
00217
00218 KSPSetFromOptions(solver);
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240 if(this->mVerbose)
00241 {
00242 Timer::PrintAndReset("KSP Setup");
00243 }
00244
00245 KSPSolve(solver,this->mLinearSystemRhsVector,solution);
00246
00247 KSPConvergedReason reason;
00248 KSPGetConvergedReason(solver,&reason);
00249 KSPEXCEPT(reason);
00250
00251 if(this->mVerbose)
00252 {
00253 Timer::PrintAndReset("KSP Solve");
00254 int num_iters;
00255 KSPGetIterationNumber(solver, &num_iters);
00256 std::cout << "[" << PetscTools::GetMyRank() << "]: Num iterations = " << num_iters << "\n" << std::flush;
00257 }
00258
00259 MechanicsEventHandler::EndEvent(MechanicsEventHandler::SOLVE);
00260
00261
00262 ReplicatableVector solution_repl(solution);
00263 for (unsigned i=0; i<this->mNumDofs; i++)
00264 {
00265 this->mCurrentSolution[i] = solution_repl[i];
00266 }
00267
00268
00269
00270
00271 this->RemovePressureDummyValuesThroughLinearInterpolation();
00272
00273 PetscTools::Destroy(solution);
00274 KSPDestroy(PETSC_DESTROY_PARAM(solver));
00275
00276 this->WriteCurrentSpatialSolution("flow_solution", "nodes");
00277 this->WriteCurrentPressureSolution();
00278 }
00279
00280
00281
00282 template<unsigned DIM>
00283 void StokesFlowSolver<DIM>::AssembleSystem()
00284 {
00285
00286 mpStokesFlowAssembler->SetMatrixToAssemble(this->mSystemLhsMatrix, true);
00287 mpStokesFlowAssembler->SetVectorToAssemble(this->mLinearSystemRhsVector, true);
00288 mpStokesFlowAssembler->Assemble();
00289
00290 mpStokesFlowPreconditionerAssembler->SetMatrixToAssemble(this->mPreconditionMatrix, true);
00291 mpStokesFlowPreconditionerAssembler->AssembleMatrix();
00292
00293 mpNeumannBcsAssembler->SetVectorToAssemble(this->mLinearSystemRhsVector, false );
00294 mpNeumannBcsAssembler->AssembleVector();
00295
00296 PetscVecTools::Finalise(this->mLinearSystemRhsVector);
00297 PetscMatTools::SwitchWriteMode(this->mSystemLhsMatrix);
00298 PetscMatTools::SwitchWriteMode(this->mPreconditionMatrix);
00299
00300
00301
00302
00303
00304
00305
00306
00307 this->AddIdentityBlockForDummyPressureVariables(LINEAR_PROBLEM);
00308 this->ApplyDirichletBoundaryConditions(LINEAR_PROBLEM, true);
00309
00310 PetscVecTools::Finalise(this->mLinearSystemRhsVector);
00311 PetscMatTools::Finalise(this->mSystemLhsMatrix);
00312 PetscMatTools::Finalise(this->mPreconditionMatrix);
00313 }
00314
00315 template<unsigned DIM>
00316 void StokesFlowSolver<DIM>::SetKspAbsoluteTolerance(double kspAbsoluteTolerance)
00317 {
00318 assert(kspAbsoluteTolerance > 0);
00319 mKspAbsoluteTol = kspAbsoluteTolerance;
00320 }
00321
00322 template<unsigned DIM>
00323 std::vector<c_vector<double,DIM> >& StokesFlowSolver<DIM>::rGetSpatialSolution()
00324 {
00325 this->mSpatialSolution.resize(this->mrQuadMesh.GetNumNodes(), zero_vector<double>(DIM));
00326 for (unsigned i=0; i<this->mrQuadMesh.GetNumNodes(); i++)
00327 {
00328 for (unsigned j=0; j<DIM; j++)
00329 {
00330
00331 this->mSpatialSolution[i](j) = this->mCurrentSolution[(DIM+1)*i+j];
00332 }
00333 }
00334 return this->mSpatialSolution;
00335 }
00336
00337 template<unsigned DIM>
00338 std::vector<c_vector<double,DIM> >& StokesFlowSolver<DIM>::rGetVelocities()
00339 {
00340 return rGetSpatialSolution();
00341 }
00342
00343
00344
00345 #endif