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 #include "AbstractCardiacProblem.hpp"
00037
00038 #include "GenericMeshReader.hpp"
00039 #include "Exception.hpp"
00040 #include "HeartConfig.hpp"
00041 #include "HeartEventHandler.hpp"
00042 #include "TimeStepper.hpp"
00043 #include "PetscTools.hpp"
00044 #include "DistributedVector.hpp"
00045 #include "ProgressReporter.hpp"
00046 #include "LinearSystem.hpp"
00047 #include "PostProcessingWriter.hpp"
00048 #include "Hdf5ToMeshalyzerConverter.hpp"
00049 #include "Hdf5ToCmguiConverter.hpp"
00050 #include "Hdf5ToVtkConverter.hpp"
00051
00052
00053 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00054 AbstractCardiacProblem<ELEMENT_DIM,SPACE_DIM,PROBLEM_DIM>::AbstractCardiacProblem(
00055 AbstractCardiacCellFactory<ELEMENT_DIM,SPACE_DIM>* pCellFactory)
00056 : mMeshFilename(""),
00057 mAllocatedMemoryForMesh(false),
00058 mWriteInfo(false),
00059 mPrintOutput(true),
00060 mpCardiacTissue(NULL),
00061 mpSolver(NULL),
00062 mpCellFactory(pCellFactory),
00063 mpMesh(NULL),
00064 mSolution(NULL),
00065 mCurrentTime(0.0),
00066 mpTimeAdaptivityController(NULL),
00067 mpWriter(NULL)
00068 {
00069 assert(mNodesToOutput.empty());
00070 if (!mpCellFactory)
00071 {
00072 EXCEPTION("AbstractCardiacProblem: Please supply a cell factory pointer to your cardiac problem constructor.");
00073 }
00074 HeartEventHandler::BeginEvent(HeartEventHandler::EVERYTHING);
00075 }
00076
00077 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00078 AbstractCardiacProblem<ELEMENT_DIM,SPACE_DIM,PROBLEM_DIM>::AbstractCardiacProblem()
00079
00080
00081 : mMeshFilename(""),
00082 mAllocatedMemoryForMesh(false),
00083 mWriteInfo(false),
00084 mPrintOutput(true),
00085 mVoltageColumnId(UINT_MAX),
00086 mTimeColumnId(UINT_MAX),
00087 mNodeColumnId(UINT_MAX),
00088 mpCardiacTissue(NULL),
00089 mpSolver(NULL),
00090 mpCellFactory(NULL),
00091 mpMesh(NULL),
00092 mSolution(NULL),
00093 mCurrentTime(0.0),
00094 mpTimeAdaptivityController(NULL),
00095 mpWriter(NULL)
00096 {
00097 }
00098
00099 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00100 AbstractCardiacProblem<ELEMENT_DIM,SPACE_DIM,PROBLEM_DIM>::~AbstractCardiacProblem()
00101 {
00102 delete mpCardiacTissue;
00103 if (mSolution)
00104 {
00105 PetscTools::Destroy(mSolution);
00106 }
00107
00108 if (mAllocatedMemoryForMesh)
00109 {
00110 delete mpMesh;
00111 }
00112 }
00113
00114 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00115 void AbstractCardiacProblem<ELEMENT_DIM,SPACE_DIM,PROBLEM_DIM>::Initialise()
00116 {
00117 HeartEventHandler::BeginEvent(HeartEventHandler::READ_MESH);
00118 if (mpMesh)
00119 {
00120 if (PetscTools::IsParallel() && !dynamic_cast<DistributedTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>*>(mpMesh))
00121 {
00122 WARNING("Using a non-distributed mesh in a parallel simulation is not a good idea.");
00123 }
00124 }
00125 else
00126 {
00127
00128 try
00129 {
00130 if (HeartConfig::Instance()->GetLoadMesh())
00131 {
00132 CreateMeshFromHeartConfig();
00133 std::auto_ptr<AbstractMeshReader<ELEMENT_DIM, SPACE_DIM> > p_mesh_reader
00134 = GenericMeshReader<ELEMENT_DIM, SPACE_DIM>(HeartConfig::Instance()->GetMeshName());
00135 mpMesh->ConstructFromMeshReader(*p_mesh_reader);
00136 }
00137 else if (HeartConfig::Instance()->GetCreateMesh())
00138 {
00139 CreateMeshFromHeartConfig();
00140 assert(HeartConfig::Instance()->GetSpaceDimension()==SPACE_DIM);
00141 double inter_node_space = HeartConfig::Instance()->GetInterNodeSpace();
00142
00143 switch(HeartConfig::Instance()->GetSpaceDimension())
00144 {
00145 case 1:
00146 {
00147 c_vector<double, 1> fibre_length;
00148 HeartConfig::Instance()->GetFibreLength(fibre_length);
00149 mpMesh->ConstructRegularSlabMesh(inter_node_space, fibre_length[0]);
00150 break;
00151 }
00152 case 2:
00153 {
00154 c_vector<double, 2> sheet_dimensions;
00155 HeartConfig::Instance()->GetSheetDimensions(sheet_dimensions);
00156 mpMesh->ConstructRegularSlabMesh(inter_node_space, sheet_dimensions[0], sheet_dimensions[1]);
00157 break;
00158 }
00159 case 3:
00160 {
00161 c_vector<double, 3> slab_dimensions;
00162 HeartConfig::Instance()->GetSlabDimensions(slab_dimensions);
00163 mpMesh->ConstructRegularSlabMesh(inter_node_space, slab_dimensions[0], slab_dimensions[1], slab_dimensions[2]);
00164 break;
00165 }
00166 default:
00167 NEVER_REACHED;
00168 }
00169 }
00170 else
00171 {
00172 NEVER_REACHED;
00173 }
00174
00175 mAllocatedMemoryForMesh = true;
00176 }
00177 catch (Exception& e)
00178 {
00179 EXCEPTION(std::string("No mesh given: define it in XML parameters file or call SetMesh()\n") + e.GetShortMessage());
00180 }
00181 }
00182 mpCellFactory->SetMesh( mpMesh );
00183 HeartEventHandler::EndEvent(HeartEventHandler::READ_MESH);
00184
00185 HeartEventHandler::BeginEvent(HeartEventHandler::INITIALISE);
00186
00187
00188 if (HeartConfig::Instance()->AreCellularTransmuralHeterogeneitiesRequested())
00189 {
00190 mpCellFactory->FillInCellularTransmuralAreas();
00191 }
00192
00193 delete mpCardiacTissue;
00194 mpCardiacTissue = CreateCardiacTissue();
00195
00196 HeartEventHandler::EndEvent(HeartEventHandler::INITIALISE);
00197
00198
00199 if (mSolution)
00200 {
00201 HeartEventHandler::BeginEvent(HeartEventHandler::COMMUNICATION);
00202 PetscTools::Destroy(mSolution);
00203 mSolution = NULL;
00204 HeartEventHandler::EndEvent(HeartEventHandler::COMMUNICATION);
00205 }
00206
00207
00208 mCurrentTime = 0.0;
00209
00210
00211 SetElectrodes();
00212 }
00213
00214 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00215 void AbstractCardiacProblem<ELEMENT_DIM,SPACE_DIM,PROBLEM_DIM>::CreateMeshFromHeartConfig()
00216 {
00217 mpMesh = new DistributedTetrahedralMesh<ELEMENT_DIM, SPACE_DIM>(HeartConfig::Instance()->GetMeshPartitioning());
00218 }
00219
00220 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00221 void AbstractCardiacProblem<ELEMENT_DIM,SPACE_DIM,PROBLEM_DIM>::SetBoundaryConditionsContainer(boost::shared_ptr<BoundaryConditionsContainer<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM> > pBcc)
00222 {
00223 this->mpBoundaryConditionsContainer = pBcc;
00224 }
00225
00226 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00227 void AbstractCardiacProblem<ELEMENT_DIM,SPACE_DIM,PROBLEM_DIM>::PreSolveChecks()
00228 {
00229 if ( mpCardiacTissue == NULL )
00230 {
00231 EXCEPTION("Cardiac tissue is null, Initialise() probably hasn't been called");
00232 }
00233 if ( HeartConfig::Instance()->GetSimulationDuration() <= mCurrentTime)
00234 {
00235 EXCEPTION("End time should be in the future");
00236 }
00237 if (mPrintOutput)
00238 {
00239 if( (HeartConfig::Instance()->GetOutputDirectory()=="") || (HeartConfig::Instance()->GetOutputFilenamePrefix()==""))
00240 {
00241 EXCEPTION("Either explicitly specify not to print output (call PrintOutput(false)) or specify the output directory and filename prefix");
00242 }
00243 }
00244
00245 double end_time = HeartConfig::Instance()->GetSimulationDuration();
00246 double pde_time = HeartConfig::Instance()->GetPdeTimeStep();
00247
00248
00249
00250
00251
00252
00253
00254
00256 if( fabs(end_time - pde_time*round(end_time/pde_time)) > 1e-10 )
00257 {
00258 EXCEPTION("PDE timestep does not seem to divide end time - check parameters");
00259 }
00260 }
00261
00262 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00263 Vec AbstractCardiacProblem<ELEMENT_DIM,SPACE_DIM,PROBLEM_DIM>::CreateInitialCondition()
00264 {
00265 DistributedVectorFactory* p_factory = mpMesh->GetDistributedVectorFactory();
00266 Vec initial_condition = p_factory->CreateVec(PROBLEM_DIM);
00267 DistributedVector ic = p_factory->CreateDistributedVector(initial_condition);
00268 std::vector<DistributedVector::Stripe> stripe;
00269 stripe.reserve(PROBLEM_DIM);
00270
00271 for (unsigned i=0; i<PROBLEM_DIM; i++)
00272 {
00273 stripe.push_back(DistributedVector::Stripe(ic, i));
00274 }
00275
00276 for (DistributedVector::Iterator index = ic.Begin();
00277 index != ic.End();
00278 ++index)
00279 {
00280 stripe[0][index] = mpCardiacTissue->GetCardiacCell(index.Global)->GetVoltage();
00281 if (PROBLEM_DIM==2)
00282 {
00283 stripe[1][index] = 0;
00284 }
00285 }
00286
00287 ic.Restore();
00288
00289 return initial_condition;
00290 }
00291
00292 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00293 void AbstractCardiacProblem<ELEMENT_DIM,SPACE_DIM,PROBLEM_DIM>::SetMesh(AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM>* pMesh)
00294 {
00295
00296
00297
00298
00299 assert(mpMesh == NULL);
00300 assert(pMesh != NULL);
00301 mAllocatedMemoryForMesh = false;
00302 mpMesh = pMesh;
00303 }
00304
00305 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00306 void AbstractCardiacProblem<ELEMENT_DIM,SPACE_DIM,PROBLEM_DIM>::PrintOutput(bool printOutput)
00307 {
00308 mPrintOutput = printOutput;
00309 }
00310
00311 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00312 void AbstractCardiacProblem<ELEMENT_DIM,SPACE_DIM,PROBLEM_DIM>::SetWriteInfo(bool writeInfo)
00313 {
00314 mWriteInfo = writeInfo;
00315 }
00316
00317 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00318 Vec AbstractCardiacProblem<ELEMENT_DIM,SPACE_DIM,PROBLEM_DIM>::GetSolution()
00319 {
00320 return mSolution;
00321 }
00322
00323 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00324 DistributedVector AbstractCardiacProblem<ELEMENT_DIM,SPACE_DIM,PROBLEM_DIM>::GetSolutionDistributedVector()
00325 {
00326 return mpMesh->GetDistributedVectorFactory()->CreateDistributedVector(mSolution);
00327 }
00328
00329 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00330 double AbstractCardiacProblem<ELEMENT_DIM,SPACE_DIM,PROBLEM_DIM>::GetCurrentTime()
00331 {
00332 return mCurrentTime;
00333 }
00334
00335 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00336 AbstractTetrahedralMesh<ELEMENT_DIM,SPACE_DIM> & AbstractCardiacProblem<ELEMENT_DIM,SPACE_DIM,PROBLEM_DIM>::rGetMesh()
00337 {
00338 assert (mpMesh);
00339 return *mpMesh;
00340 }
00341
00342 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00343 AbstractCardiacTissue<ELEMENT_DIM,SPACE_DIM>* AbstractCardiacProblem<ELEMENT_DIM,SPACE_DIM,PROBLEM_DIM>::GetTissue()
00344 {
00345 if (mpCardiacTissue == NULL)
00346 {
00347 EXCEPTION("Tissue not yet set up, you may need to call Initialise() before GetTissue().");
00348 }
00349 return mpCardiacTissue;
00350 }
00351
00352 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00353 void AbstractCardiacProblem<ELEMENT_DIM,SPACE_DIM,PROBLEM_DIM>::SetUseTimeAdaptivityController(
00354 bool useAdaptivity,
00355 AbstractTimeAdaptivityController* pController)
00356 {
00357 if (useAdaptivity)
00358 {
00359 assert(pController);
00360 mpTimeAdaptivityController = pController;
00361 }
00362 else
00363 {
00364 mpTimeAdaptivityController = NULL;
00365 }
00366 }
00367
00368
00369 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00370 void AbstractCardiacProblem<ELEMENT_DIM,SPACE_DIM,PROBLEM_DIM>::Solve()
00371 {
00372 PreSolveChecks();
00373
00374 std::vector<double> additional_stopping_times;
00375 SetUpAdditionalStoppingTimes(additional_stopping_times);
00376
00377 TimeStepper stepper(mCurrentTime,
00378 HeartConfig::Instance()->GetSimulationDuration(),
00379 HeartConfig::Instance()->GetPrintingTimeStep(),
00380 false,
00381 additional_stopping_times);
00382
00383
00384
00385
00386 if (!mpBoundaryConditionsContainer)
00387 {
00388
00389 mpDefaultBoundaryConditionsContainer.reset(new BoundaryConditionsContainer<ELEMENT_DIM, SPACE_DIM, PROBLEM_DIM>);
00390 for (unsigned problem_index=0; problem_index<PROBLEM_DIM; problem_index++)
00391 {
00392 mpDefaultBoundaryConditionsContainer->DefineZeroNeumannOnMeshBoundary(mpMesh, problem_index);
00393 }
00394 mpBoundaryConditionsContainer = mpDefaultBoundaryConditionsContainer;
00395 }
00396
00397 assert(mpSolver==NULL);
00398 mpSolver = CreateSolver();
00399
00400
00401 Vec initial_condition;
00402 if (mSolution)
00403 {
00404 initial_condition = mSolution;
00405 }
00406 else
00407 {
00408 initial_condition = CreateInitialCondition();
00409 }
00410
00411 std::string progress_reporter_dir;
00412
00413 if (mPrintOutput)
00414 {
00415 HeartEventHandler::BeginEvent(HeartEventHandler::WRITE_OUTPUT);
00416 bool extending_file = false;
00417 try
00418 {
00419 extending_file = InitialiseWriter();
00420 }
00421 catch (Exception& e)
00422 {
00423 delete mpWriter;
00424 mpWriter = NULL;
00425 delete mpSolver;
00426 if (mSolution != initial_condition)
00427 {
00428
00429
00430
00431
00432
00433
00434
00435 PetscTools::Destroy(initial_condition);
00436 }
00437 throw e;
00438 }
00439
00440
00441
00442
00443
00444
00445
00446 if (!(mSolution && extending_file))
00447 {
00448 WriteOneStep(stepper.GetTime(), initial_condition);
00449 mpWriter->AdvanceAlongUnlimitedDimension();
00450 }
00451 HeartEventHandler::EndEvent(HeartEventHandler::WRITE_OUTPUT);
00452
00453 progress_reporter_dir = HeartConfig::Instance()->GetOutputDirectory();
00454 }
00455 else
00456 {
00457 progress_reporter_dir = "";
00458 }
00459 BOOST_FOREACH(boost::shared_ptr<AbstractOutputModifier> p_output_modifier, mOutputModifiers)
00460 {
00461 p_output_modifier->InitialiseAtStart(this->mpMesh->GetDistributedVectorFactory());
00462 p_output_modifier->ProcessSolutionAtTimeStep(stepper.GetTime(), initial_condition, PROBLEM_DIM);
00463 }
00464
00465
00466
00467
00468
00469
00470
00471 ProgressReporter progress_reporter(progress_reporter_dir,
00472 mCurrentTime,
00473 HeartConfig::Instance()->GetSimulationDuration());
00474 progress_reporter.Update(mCurrentTime);
00475
00476 mpSolver->SetTimeStep(HeartConfig::Instance()->GetPdeTimeStep());
00477 if (mpTimeAdaptivityController)
00478 {
00479 mpSolver->SetTimeAdaptivityController(mpTimeAdaptivityController);
00480 }
00481
00482 while (!stepper.IsTimeAtEnd())
00483 {
00484
00485 mpSolver->SetTimes(stepper.GetTime(), stepper.GetNextTime());
00486 mpSolver->SetInitialCondition( initial_condition );
00487
00488 AtBeginningOfTimestep(stepper.GetTime());
00489
00490 try
00491 {
00492 try
00493 {
00494 mSolution = mpSolver->Solve();
00495 }
00496 catch (const Exception &e)
00497 {
00498 #ifndef NDEBUG
00499 PetscTools::ReplicateException(true);
00500 #endif
00501 throw e;
00502 }
00503 #ifndef NDEBUG
00504 PetscTools::ReplicateException(false);
00505 #endif
00506 }
00507 catch (const Exception& e)
00508 {
00509
00510 delete mpSolver;
00511 mpSolver = NULL;
00512 if (initial_condition != mSolution)
00513 {
00514
00515
00516
00517
00518
00519
00520
00521
00522 PetscTools::Destroy(initial_condition);
00523 }
00524
00525
00526 HeartEventHandler::Reset();
00527 CloseFilesAndPostProcess();
00528
00529 throw e;
00530 }
00531
00532
00533 HeartEventHandler::BeginEvent(HeartEventHandler::COMMUNICATION);
00534 PetscTools::Destroy(initial_condition);
00535 HeartEventHandler::EndEvent(HeartEventHandler::COMMUNICATION);
00536
00537
00538 initial_condition = mSolution;
00539
00540
00541 stepper.AdvanceOneTimeStep();
00542 mCurrentTime = stepper.GetTime();
00543
00544
00545 if (mWriteInfo)
00546 {
00547 HeartEventHandler::BeginEvent(HeartEventHandler::WRITE_OUTPUT);
00548 WriteInfo(stepper.GetTime());
00549 HeartEventHandler::EndEvent(HeartEventHandler::WRITE_OUTPUT);
00550 }
00551
00552 BOOST_FOREACH(boost::shared_ptr<AbstractOutputModifier> p_output_modifier, mOutputModifiers)
00553 {
00554 p_output_modifier->ProcessSolutionAtTimeStep(stepper.GetTime(), mSolution, PROBLEM_DIM);
00555 }
00556 if (mPrintOutput)
00557 {
00558
00559 HeartEventHandler::BeginEvent(HeartEventHandler::WRITE_OUTPUT);
00560 WriteOneStep(stepper.GetTime(), mSolution);
00561
00562 mpWriter->AdvanceAlongUnlimitedDimension();
00563
00564 HeartEventHandler::EndEvent(HeartEventHandler::WRITE_OUTPUT);
00565 }
00566
00567 progress_reporter.Update(stepper.GetTime());
00568
00569 OnEndOfTimestep(stepper.GetTime());
00570 }
00571
00572
00573 delete mpSolver;
00574 mpSolver = NULL;
00575
00576
00577 progress_reporter.PrintFinalising();
00578 BOOST_FOREACH(boost::shared_ptr<AbstractOutputModifier> p_output_modifier, mOutputModifiers)
00579 {
00580 p_output_modifier->FinaliseAtEnd();
00581 }
00582 CloseFilesAndPostProcess();
00583 HeartEventHandler::EndEvent(HeartEventHandler::EVERYTHING);
00584 }
00585
00586 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00587 void AbstractCardiacProblem<ELEMENT_DIM,SPACE_DIM,PROBLEM_DIM>::CloseFilesAndPostProcess()
00588 {
00589
00590 if (!mPrintOutput)
00591 {
00592
00593 return;
00594 }
00595 delete mpWriter;
00596 mpWriter = NULL;
00597
00598 FileFinder test_output(HeartConfig::Instance()->GetOutputDirectory(), RelativeTo::ChasteTestOutput);
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609 HeartEventHandler::BeginEvent(HeartEventHandler::POST_PROC);
00610 if(HeartConfig::Instance()->IsPostProcessingRequested())
00611 {
00612 PostProcessingWriter<ELEMENT_DIM, SPACE_DIM> post_writer(*mpMesh,
00613 test_output,
00614 HeartConfig::Instance()->GetOutputFilenamePrefix());
00615 post_writer.WritePostProcessingFiles();
00616 }
00617 HeartEventHandler::EndEvent(HeartEventHandler::POST_PROC);
00618
00619
00620
00621
00622
00623 HeartEventHandler::BeginEvent(HeartEventHandler::DATA_CONVERSION);
00624
00625 if (mNodesToOutput.empty())
00626 {
00627 if (HeartConfig::Instance()->GetVisualizeWithMeshalyzer())
00628 {
00629
00630 Hdf5ToMeshalyzerConverter<ELEMENT_DIM,SPACE_DIM> converter(test_output,
00631 HeartConfig::Instance()->GetOutputFilenamePrefix(),
00632 mpMesh,
00633 HeartConfig::Instance()->GetOutputUsingOriginalNodeOrdering(),
00634 HeartConfig::Instance()->GetVisualizerOutputPrecision() );
00635 std::string subdirectory_name = converter.GetSubdirectory();
00636 HeartConfig::Instance()->Write(false, subdirectory_name);
00637 }
00638
00639 if (HeartConfig::Instance()->GetVisualizeWithCmgui())
00640 {
00641
00642 Hdf5ToCmguiConverter<ELEMENT_DIM,SPACE_DIM> converter(test_output,
00643 HeartConfig::Instance()->GetOutputFilenamePrefix(),
00644 mpMesh,
00645 GetHasBath(),
00646 HeartConfig::Instance()->GetVisualizerOutputPrecision() );
00647 std::string subdirectory_name = converter.GetSubdirectory();
00648 HeartConfig::Instance()->Write(false, subdirectory_name);
00649 }
00650
00651 if (HeartConfig::Instance()->GetVisualizeWithVtk())
00652 {
00653
00654 Hdf5ToVtkConverter<ELEMENT_DIM,SPACE_DIM> converter(test_output,
00655 HeartConfig::Instance()->GetOutputFilenamePrefix(),
00656 mpMesh,
00657 false,
00658 HeartConfig::Instance()->GetOutputUsingOriginalNodeOrdering());
00659 std::string subdirectory_name = converter.GetSubdirectory();
00660 HeartConfig::Instance()->Write(false, subdirectory_name);
00661 }
00662
00663 if (HeartConfig::Instance()->GetVisualizeWithParallelVtk())
00664 {
00665
00666 Hdf5ToVtkConverter<ELEMENT_DIM,SPACE_DIM> converter(test_output,
00667 HeartConfig::Instance()->GetOutputFilenamePrefix(),
00668 mpMesh,
00669 true,
00670 HeartConfig::Instance()->GetOutputUsingOriginalNodeOrdering());
00671 std::string subdirectory_name = converter.GetSubdirectory();
00672 HeartConfig::Instance()->Write(false, subdirectory_name);
00673 }
00674 }
00675 HeartEventHandler::EndEvent(HeartEventHandler::DATA_CONVERSION);
00676 }
00677
00678 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00679 void AbstractCardiacProblem<ELEMENT_DIM,SPACE_DIM,PROBLEM_DIM>::DefineWriterColumns(bool extending)
00680 {
00681 if (!extending)
00682 {
00683 if ( mNodesToOutput.empty() )
00684 {
00685
00686 mpWriter->DefineFixedDimension( mpMesh->GetNumNodes() );
00687 }
00688 else
00689 {
00690
00691 mpWriter->DefineFixedDimension( mNodesToOutput, mpMesh->GetNumNodes() );
00692 }
00693
00694 mVoltageColumnId = mpWriter->DefineVariable("V","mV");
00695
00696
00697 TimeStepper stepper(mCurrentTime,
00698 HeartConfig::Instance()->GetSimulationDuration(),
00699 HeartConfig::Instance()->GetPrintingTimeStep());
00700
00701 mpWriter->DefineUnlimitedDimension("Time","msecs", stepper.EstimateTimeSteps()+1);
00702 }
00703 else
00704 {
00705 mVoltageColumnId = mpWriter->GetVariableByName("V");
00706 }
00707 }
00708
00709 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00710 void AbstractCardiacProblem<ELEMENT_DIM,SPACE_DIM,PROBLEM_DIM>::DefineExtraVariablesWriterColumns(bool extending)
00711 {
00712 mExtraVariablesId.clear();
00713
00714 if (HeartConfig::Instance()->GetOutputVariablesProvided())
00715 {
00716
00717 std::vector<std::string> output_variables;
00718 HeartConfig::Instance()->GetOutputVariables(output_variables);
00719 const unsigned num_vars = output_variables.size();
00720 mExtraVariablesId.reserve(num_vars);
00721
00722
00723 for (unsigned var_index=0; var_index<num_vars; var_index++)
00724 {
00725
00726 std::string var_name = output_variables[var_index];
00727
00728
00729 unsigned column_id;
00730 if (extending)
00731 {
00732 column_id = this->mpWriter->GetVariableByName(var_name);
00733 }
00734 else
00735 {
00736
00737
00738 column_id = this->mpWriter->DefineVariable(var_name, "unknown_units");
00739 }
00740
00741
00742 mExtraVariablesId.push_back(column_id);
00743 }
00744 }
00745 }
00746
00747 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00748 void AbstractCardiacProblem<ELEMENT_DIM,SPACE_DIM,PROBLEM_DIM>::WriteExtraVariablesOneStep()
00749 {
00750
00751 std::vector<std::string> output_variables;
00752 unsigned num_vars = mExtraVariablesId.size();
00753 if (num_vars > 0)
00754 {
00755 HeartConfig::Instance()->GetOutputVariables(output_variables);
00756 }
00757 assert(output_variables.size() == num_vars);
00758
00759
00760 for (unsigned var_index=0; var_index<num_vars; var_index++)
00761 {
00762
00763 Vec variable_data = this->mpMesh->GetDistributedVectorFactory()->CreateVec();
00764 DistributedVector distributed_var_data = this->mpMesh->GetDistributedVectorFactory()->CreateDistributedVector(variable_data);
00765
00766
00767 for (DistributedVector::Iterator index = distributed_var_data.Begin();
00768 index!= distributed_var_data.End();
00769 ++index)
00770 {
00771
00772 if (HeartRegionCode::IsRegionBath( this->mpMesh->GetNode( index.Global )->GetRegion() ))
00773 {
00774
00775
00776 distributed_var_data[index] = 0.0;
00777 }
00778 else
00779 {
00780
00781 distributed_var_data[index] = this->mpCardiacTissue->GetCardiacCell(index.Global)->
00782 GetAnyVariable(output_variables[var_index], mCurrentTime);
00783 }
00784 }
00785 distributed_var_data.Restore();
00786
00787
00788 this->mpWriter->PutVector(mExtraVariablesId[var_index], variable_data);
00789
00790 PetscTools::Destroy(variable_data);
00791 }
00792 }
00793
00794 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00795 bool AbstractCardiacProblem<ELEMENT_DIM,SPACE_DIM,PROBLEM_DIM>::InitialiseWriter()
00796 {
00797 bool extend_file = (mSolution != NULL);
00798
00799
00800 assert(!mpWriter);
00801
00802 if (extend_file)
00803 {
00804 FileFinder h5_file(OutputFileHandler::GetChasteTestOutputDirectory() + HeartConfig::Instance()->GetOutputDirectory()
00805 + "/" + HeartConfig::Instance()->GetOutputFilenamePrefix() + ".h5",
00806 RelativeTo::Absolute);
00807
00808
00809
00810
00811 PetscTools::Barrier("InitialiseWriter::Extension check");
00812 if (!h5_file.Exists())
00813 {
00814 extend_file = false;
00815 }
00816 else
00817 {
00818 Hdf5DataReader reader(HeartConfig::Instance()->GetOutputDirectory(),
00819 HeartConfig::Instance()->GetOutputFilenamePrefix(),
00820 true);
00821 std::vector<double> times = reader.GetUnlimitedDimensionValues();
00822 if (times.back() > mCurrentTime)
00823 {
00824 EXCEPTION("Attempting to extend " << h5_file.GetAbsolutePath() <<
00825 " with results from time = " << mCurrentTime <<
00826 ", but it already contains results up to time = " << times.back() << "."
00827 " Calling HeartConfig::Instance()->SetOutputDirectory() before Solve() will direct results elsewhere.");
00828 }
00829 }
00830 PetscTools::Barrier("InitialiseWriter::Extension check");
00831 }
00832 mpWriter = new Hdf5DataWriter(*mpMesh->GetDistributedVectorFactory(),
00833 HeartConfig::Instance()->GetOutputDirectory(),
00834 HeartConfig::Instance()->GetOutputFilenamePrefix(),
00835 !extend_file,
00836 extend_file);
00837
00838
00839
00840 DefineWriterColumns(extend_file);
00841
00842
00843 if (HeartConfig::Instance()->GetOutputUsingOriginalNodeOrdering())
00844 {
00845 bool success = mpWriter->ApplyPermutation(mpMesh->rGetNodePermutation(), true);
00846 if (success == false)
00847 {
00848
00849 HeartConfig::Instance()->SetOutputUsingOriginalNodeOrdering(false);
00850 }
00851 }
00852
00853 if (!extend_file)
00854 {
00855 mpWriter->EndDefineMode();
00856 }
00857
00858 return extend_file;
00859 }
00860
00861 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00862 void AbstractCardiacProblem<ELEMENT_DIM,SPACE_DIM,PROBLEM_DIM>::SetOutputNodes(std::vector<unsigned> &nodesToOutput)
00863 {
00864 mNodesToOutput = nodesToOutput;
00865 }
00866
00867 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00868 Hdf5DataReader AbstractCardiacProblem<ELEMENT_DIM,SPACE_DIM,PROBLEM_DIM>::GetDataReader()
00869 {
00870 if( (HeartConfig::Instance()->GetOutputDirectory()=="") || (HeartConfig::Instance()->GetOutputFilenamePrefix()==""))
00871 {
00872 EXCEPTION("Data reader invalid as data writer cannot be initialised");
00873 }
00874 return Hdf5DataReader(HeartConfig::Instance()->GetOutputDirectory(), HeartConfig::Instance()->GetOutputFilenamePrefix());
00875 }
00876
00877 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00878 bool AbstractCardiacProblem<ELEMENT_DIM,SPACE_DIM,PROBLEM_DIM>::GetHasBath()
00879 {
00880 return false;
00881 }
00882
00883 template<unsigned ELEMENT_DIM, unsigned SPACE_DIM, unsigned PROBLEM_DIM>
00884 void AbstractCardiacProblem<ELEMENT_DIM,SPACE_DIM,PROBLEM_DIM>::SetElectrodes()
00885 {
00886 }
00887
00888
00890
00892
00893
00894 template class AbstractCardiacProblem<1,1,1>;
00895 template class AbstractCardiacProblem<1,2,1>;
00896 template class AbstractCardiacProblem<1,3,1>;
00897 template class AbstractCardiacProblem<2,2,1>;
00898 template class AbstractCardiacProblem<3,3,1>;
00899
00900
00901 template class AbstractCardiacProblem<1,1,2>;
00902 template class AbstractCardiacProblem<2,2,2>;
00903 template class AbstractCardiacProblem<3,3,2>;
00904
00905
00906 template class AbstractCardiacProblem<1,1,3>;
00907 template class AbstractCardiacProblem<2,2,3>;
00908 template class AbstractCardiacProblem<3,3,3>;