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