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