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 #ifndef ABSTRACTDYNAMICLINEARPDESOLVER_HPP_
00031 #define ABSTRACTDYNAMICLINEARPDESOLVER_HPP_
00032
00033 #include "Exception.hpp"
00034 #include "TimeStepper.hpp"
00035 #include "AbstractLinearPdeSolver.hpp"
00036 #include "PdeSimulationTime.hpp"
00037 #include "AbstractTimeAdaptivityController.hpp"
00038 #include "Hdf5DataWriter.hpp"
00039 #include "Hdf5ToVtkConverter.hpp"
00040 #include "Hdf5ToTxtConverter.hpp"
00041
00048 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00049 class AbstractDynamicLinearPdeSolver : public AbstractLinearPdeSolver<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>
00050 {
00051 friend class TestSimpleLinearParabolicSolver;
00052 protected:
00053
00055 double mTstart;
00056
00058 double mTend;
00059
00061 bool mTimesSet;
00062
00064 Vec mInitialCondition;
00065
00067 bool mMatrixIsAssembled;
00068
00073 bool mMatrixIsConstant;
00074
00079 double mIdealTimeStep;
00080
00082 double mLastWorkingTimeStep;
00083
00085 AbstractTimeAdaptivityController* mpTimeAdaptivityController;
00086
00091 bool mOutputToVtk;
00092
00097 bool mOutputToParallelVtk;
00098
00103 bool mOutputToTxt;
00104
00106 std::string mOutputDirectory;
00107
00109 std::string mFilenamePrefix;
00110
00116 unsigned mPrintingTimestepMultiple;
00117
00119 Hdf5DataWriter* mpHdf5Writer;
00120
00122 std::vector<int> mVariableColumnIds;
00123
00128 void InitialiseHdf5Writer();
00129
00136 void WriteOneStep(double time, Vec solution);
00137
00138 public:
00139
00145 AbstractDynamicLinearPdeSolver(AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* pMesh);
00146
00153 void SetTimes(double tStart, double tEnd);
00154
00160 void SetTimeStep(double dt);
00161
00170 void SetInitialCondition(Vec initialCondition);
00171
00173 Vec Solve();
00174
00176 void SetMatrixIsNotAssembled();
00177
00183 void SetTimeAdaptivityController(AbstractTimeAdaptivityController* pTimeAdaptivityController);
00184
00188 void SetOutputToVtk(bool output);
00189
00193 void SetOutputToParallelVtk(bool output);
00194
00198 void SetOutputToTxt(bool output);
00199
00204 void SetOutputDirectoryAndPrefix(std::string outputDirectory, std::string prefix);
00205
00210 void SetPrintingTimestepMultiple(unsigned multiple);
00211 };
00212
00213 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00214 void AbstractDynamicLinearPdeSolver<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>::InitialiseHdf5Writer()
00215 {
00216
00217 if ((mOutputDirectory=="") || (mFilenamePrefix==""))
00218 {
00219 EXCEPTION("Output directory or filename prefix has not been set");
00220 }
00221
00222
00223 mpHdf5Writer = new Hdf5DataWriter(*(this->mpMesh)->GetDistributedVectorFactory(),
00224 mOutputDirectory,
00225 mFilenamePrefix);
00226
00227
00228 mpHdf5Writer->DefineFixedDimension((this->mpMesh)->GetNumNodes());
00229
00230
00231 unsigned estimated_num_printing_timesteps = 1u + (unsigned)((mTend - mTstart)/(mIdealTimeStep*mPrintingTimestepMultiple));
00232
00239 assert(mVariableColumnIds.empty());
00240 for (unsigned i=0; i<PROBLEM_DIM; i++)
00241 {
00242 std::stringstream variable_name;
00243 variable_name << "Variable_" << i;
00244 mVariableColumnIds.push_back(mpHdf5Writer->DefineVariable(variable_name.str(),"undefined"));
00245 }
00246 mpHdf5Writer->DefineUnlimitedDimension("Time", "undefined", estimated_num_printing_timesteps);
00247
00248
00249 mpHdf5Writer->EndDefineMode();
00250 }
00251
00252 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00253 AbstractDynamicLinearPdeSolver<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>::AbstractDynamicLinearPdeSolver(AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* pMesh)
00254 : AbstractLinearPdeSolver<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>(pMesh),
00255 mTimesSet(false),
00256 mInitialCondition(NULL),
00257 mMatrixIsAssembled(false),
00258 mMatrixIsConstant(false),
00259 mIdealTimeStep(-1.0),
00260 mLastWorkingTimeStep(-1),
00261 mpTimeAdaptivityController(NULL),
00262 mOutputToVtk(false),
00263 mOutputToParallelVtk(false),
00264 mOutputToTxt(false),
00265 mOutputDirectory(""),
00266 mFilenamePrefix(""),
00267 mPrintingTimestepMultiple(1),
00268 mpHdf5Writer(NULL)
00269 {
00270 }
00271
00272 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00273 void AbstractDynamicLinearPdeSolver<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>::SetTimes(double tStart, double tEnd)
00274 {
00275 mTstart = tStart;
00276 mTend = tEnd;
00277
00278 if (mTstart >= mTend)
00279 {
00280 EXCEPTION("Start time has to be less than end time");
00281 }
00282
00283 mTimesSet = true;
00284 }
00285
00286 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00287 void AbstractDynamicLinearPdeSolver<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>::SetTimeStep(double dt)
00288 {
00289 if (dt <= 0)
00290 {
00291 EXCEPTION("Time step has to be greater than zero");
00292 }
00293
00294 mIdealTimeStep = dt;
00295 }
00296
00297 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00298 void AbstractDynamicLinearPdeSolver<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>::SetInitialCondition(Vec initialCondition)
00299 {
00300 assert(initialCondition != NULL);
00301 mInitialCondition = initialCondition;
00302 }
00303
00304 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00305 void AbstractDynamicLinearPdeSolver<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>::WriteOneStep(double time, Vec solution)
00306 {
00307 mpHdf5Writer->PutUnlimitedVariable(time);
00308 if (PROBLEM_DIM == 1)
00309 {
00310 mpHdf5Writer->PutVector(mVariableColumnIds[0], solution);
00311 }
00312 else
00313 {
00314 mpHdf5Writer->PutStripedVector(mVariableColumnIds, solution);
00315 }
00316 }
00317
00318 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00319 Vec AbstractDynamicLinearPdeSolver<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>::Solve()
00320 {
00321
00322 if (!mTimesSet)
00323 {
00324 EXCEPTION("SetTimes() has not been called");
00325 }
00326 if ((mIdealTimeStep <= 0.0) && (mpTimeAdaptivityController==NULL))
00327 {
00328 EXCEPTION("SetTimeStep() has not been called");
00329 }
00330 if (mInitialCondition == NULL)
00331 {
00332 EXCEPTION("SetInitialCondition() has not been called");
00333 }
00334
00335
00336 bool print_output = (mOutputToVtk || mOutputToParallelVtk || mOutputToTxt);
00337 if (print_output)
00338 {
00339 InitialiseHdf5Writer();
00340 WriteOneStep(mTstart, mInitialCondition);
00341 mpHdf5Writer->AdvanceAlongUnlimitedDimension();
00342 }
00343
00344 this->InitialiseForSolve(mInitialCondition);
00345
00346 if (mIdealTimeStep < 0)
00347 {
00348 mIdealTimeStep = mpTimeAdaptivityController->GetNextTimeStep(mTstart, mInitialCondition);
00349 }
00350
00351
00352
00353
00354
00355
00356
00357
00358 TimeStepper stepper(mTstart, mTend, mIdealTimeStep, mMatrixIsConstant);
00359
00360 Vec solution = mInitialCondition;
00361 Vec next_solution;
00362
00363 while (!stepper.IsTimeAtEnd())
00364 {
00365 bool timestep_changed = false;
00366
00367 PdeSimulationTime::SetTime(stepper.GetTime());
00368
00369
00370 double new_dt;
00371 if (mpTimeAdaptivityController)
00372 {
00373
00374 mIdealTimeStep = mpTimeAdaptivityController->GetNextTimeStep(stepper.GetTime(), solution);
00375
00376
00377 stepper.ResetTimeStep(mIdealTimeStep);
00378
00379
00380
00381 new_dt = stepper.GetNextTimeStep();
00382
00383 timestep_changed = (fabs(new_dt/mLastWorkingTimeStep - 1.0) > 1e-5);
00384 }
00385 else
00386 {
00387 new_dt = stepper.GetNextTimeStep();
00388
00389
00390
00391 if (mMatrixIsConstant && fabs(new_dt/mIdealTimeStep - 1.0) > 1e-5)
00392 {
00393
00394
00395 NEVER_REACHED;
00396 }
00397 }
00398
00399
00400
00401 mLastWorkingTimeStep = new_dt;
00402 PdeSimulationTime::SetPdeTimeStep(new_dt);
00403
00404
00405
00406 this->PrepareForSetupLinearSystem(solution);
00407
00408 bool compute_matrix = (!mMatrixIsConstant || !mMatrixIsAssembled || timestep_changed);
00409
00410 this->SetupLinearSystem(solution, compute_matrix);
00411
00412 this->FinaliseLinearSystem(solution);
00413
00414 if (compute_matrix)
00415 {
00416 this->mpLinearSystem->ResetKspSolver();
00417 }
00418
00419 next_solution = this->mpLinearSystem->Solve(solution);
00420
00421 if (mMatrixIsConstant)
00422 {
00423 mMatrixIsAssembled = true;
00424 }
00425
00426 this->FollowingSolveLinearSystem(next_solution);
00427
00428 stepper.AdvanceOneTimeStep();
00429
00430
00431 if (solution != mInitialCondition)
00432 {
00433 HeartEventHandler::BeginEvent(HeartEventHandler::COMMUNICATION);
00434 VecDestroy(solution);
00435 HeartEventHandler::EndEvent(HeartEventHandler::COMMUNICATION);
00436 }
00437 solution = next_solution;
00438
00439
00440 if (print_output && (stepper.GetTotalTimeStepsTaken()%mPrintingTimestepMultiple == 0) )
00441 {
00442 WriteOneStep(stepper.GetTime(), solution);
00443 mpHdf5Writer->AdvanceAlongUnlimitedDimension();
00444 }
00445 }
00446
00447
00448 if (mpHdf5Writer != NULL)
00449 {
00450 delete mpHdf5Writer;
00451 mpHdf5Writer = NULL;
00452 }
00453
00454
00455
00456 if (mOutputToVtk)
00457 {
00458 Hdf5ToVtkConverter<ELEMENT_DIM,SPACE_DIM> converter(mOutputDirectory, mFilenamePrefix, this->mpMesh, false, false);
00459 }
00460 if (mOutputToParallelVtk)
00461 {
00462 Hdf5ToVtkConverter<ELEMENT_DIM,SPACE_DIM> converter(mOutputDirectory, mFilenamePrefix, this->mpMesh, true, false);
00463 }
00464 if (mOutputToTxt)
00465 {
00466 Hdf5ToTxtConverter<ELEMENT_DIM,SPACE_DIM> converter(mOutputDirectory, mFilenamePrefix, this->mpMesh);
00467 }
00468
00469 return solution;
00470 }
00471
00472 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00473 void AbstractDynamicLinearPdeSolver<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>::SetMatrixIsNotAssembled()
00474 {
00475 mMatrixIsAssembled = false;
00476 }
00477
00478 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00479 void AbstractDynamicLinearPdeSolver<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>::SetTimeAdaptivityController(AbstractTimeAdaptivityController* pTimeAdaptivityController)
00480 {
00481 assert(pTimeAdaptivityController != NULL);
00482 assert(mpTimeAdaptivityController == NULL);
00483 mpTimeAdaptivityController = pTimeAdaptivityController;
00484 }
00485
00486 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00487 void AbstractDynamicLinearPdeSolver<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>::SetOutputToVtk(bool output)
00488 {
00489 mOutputToVtk = output;
00490 }
00491
00492 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00493 void AbstractDynamicLinearPdeSolver<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>::SetOutputToParallelVtk(bool output)
00494 {
00495 mOutputToParallelVtk = output;
00496 }
00497
00498 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00499 void AbstractDynamicLinearPdeSolver<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>::SetOutputToTxt(bool output)
00500 {
00501 mOutputToTxt = output;
00502 }
00503
00504 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00505 void AbstractDynamicLinearPdeSolver<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>::SetOutputDirectoryAndPrefix(std::string outputDirectory, std::string prefix)
00506 {
00507 mOutputDirectory = outputDirectory;
00508 mFilenamePrefix = prefix;
00509 }
00510
00511 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00512 void AbstractDynamicLinearPdeSolver<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>::SetPrintingTimestepMultiple(unsigned multiple)
00513 {
00514 mPrintingTimestepMultiple = multiple;
00515 }
00516
00517 #endif