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 "CardiacElectroMechanicsProblem.hpp"
00030
00031 #include "OutputFileHandler.hpp"
00032 #include "ReplicatableVector.hpp"
00033 #include "HeartConfig.hpp"
00034 #include "LogFile.hpp"
00035 #include "ChastePoint.hpp"
00036 #include "Element.hpp"
00037 #include "BoundaryConditionsContainer.hpp"
00038 #include "AbstractDynamicLinearPdeSolver.hpp"
00039 #include "TimeStepper.hpp"
00040 #include "QuadraturePointsGroup.hpp"
00041 #include "TrianglesMeshWriter.hpp"
00042 #include "Hdf5ToMeshalyzerConverter.hpp"
00043 #include "Hdf5ToCmguiConverter.hpp"
00044 #include "MeshalyzerMeshWriter.hpp"
00045 #include "PetscTools.hpp"
00046
00047 #include "ImplicitCardiacMechanicsSolver.hpp"
00048 #include "ExplicitCardiacMechanicsSolver.hpp"
00049 #include "MooneyRivlinMaterialLaw.hpp"
00050 #include "CmguiDeformedSolutionsWriter.hpp"
00051 #include "VoltageInterpolaterOntoMechanicsMesh.hpp"
00052
00053 template<unsigned DIM>
00054 void CardiacElectroMechanicsProblem<DIM>::DetermineWatchedNodes()
00055 {
00056 assert(mIsWatchedLocation);
00057
00058
00059 double min_dist = DBL_MAX;
00060 unsigned node_index = UNSIGNED_UNSET;
00061 for(unsigned i=0; i<mpElectricsMesh->GetNumNodes(); i++)
00062 {
00063 double dist = norm_2(mWatchedLocation - mpElectricsMesh->GetNode(i)->rGetLocation());
00064 if(dist < min_dist)
00065 {
00066 min_dist = dist;
00067 node_index = i;
00068 }
00069 }
00070
00071
00072 assert(node_index != UNSIGNED_UNSET);
00073 c_vector<double,DIM> pos = mpElectricsMesh->GetNode(node_index)->rGetLocation();
00074
00075 if(min_dist > 1e-8)
00076 {
00077 #define COVERAGE_IGNORE
00078 std::cout << "ERROR: Could not find an electrics node very close to requested watched location - "
00079 << "min distance was " << min_dist << " for node " << node_index
00080 << " at location " << pos << std::flush;;
00081
00083
00084 NEVER_REACHED;
00085 #undef COVERAGE_IGNORE
00086 }
00087 else
00088 {
00089 LOG(2,"Chosen electrics node "<<node_index<<" at location " << pos << " to be watched");
00090 mWatchedElectricsNodeIndex = node_index;
00091 }
00092
00093
00094 min_dist = DBL_MAX;
00095 node_index = UNSIGNED_UNSET;
00096 c_vector<double,DIM> pos_at_min;
00097
00098 for(unsigned i=0; i<mpMechanicsMesh->GetNumNodes(); i++)
00099 {
00100 c_vector<double,DIM> position = mpMechanicsMesh->GetNode(i)->rGetLocation();
00101
00102 double dist = norm_2(position-mWatchedLocation);
00103
00104 if(dist < min_dist)
00105 {
00106 min_dist = dist;
00107 node_index = i;
00108 pos_at_min = position;
00109 }
00110 }
00111
00112
00113 assert(node_index != UNSIGNED_UNSET);
00114
00115 if(min_dist > 1e-8)
00116 {
00117 #define COVERAGE_IGNORE
00118 std::cout << "ERROR: Could not find a mechanics node very close to requested watched location - "
00119 << "min distance was " << min_dist << " for node " << node_index
00120 << " at location " << pos_at_min;
00121
00123
00124 assert(0);
00125 #undef COVERAGE_IGNORE
00126 }
00127 else
00128 {
00129 LOG(2,"Chosen mechanics node "<<node_index<<" at location " << pos << " to be watched");
00130 mWatchedMechanicsNodeIndex = node_index;
00131 }
00132
00133 OutputFileHandler handler(mOutputDirectory,false);
00134 mpWatchedLocationFile = handler.OpenOutputFile("watched.txt");
00135 }
00136
00137 template<unsigned DIM>
00138 void CardiacElectroMechanicsProblem<DIM>::WriteWatchedLocationData(double time, Vec voltage)
00139 {
00140 assert(mIsWatchedLocation);
00141
00142 std::vector<c_vector<double,DIM> >& deformed_position = mpCardiacMechSolver->rGetDeformedPosition();
00143
00145 ReplicatableVector voltage_replicated(voltage);
00146 double V = voltage_replicated[mWatchedElectricsNodeIndex];
00147
00150
00151
00152
00153 *mpWatchedLocationFile << time << " ";
00154 for(unsigned i=0; i<DIM; i++)
00155 {
00156 *mpWatchedLocationFile << deformed_position[mWatchedMechanicsNodeIndex](i) << " ";
00157 }
00158 *mpWatchedLocationFile << V << "\n";
00159 mpWatchedLocationFile->flush();
00160 }
00161
00162 template<unsigned DIM>
00163 c_matrix<double,DIM,DIM>& CardiacElectroMechanicsProblem<DIM>::rGetModifiedConductivityTensor(unsigned elementIndex, const c_matrix<double,DIM,DIM>& rOriginalConductivity)
00164 {
00165 if(mLastModifiedConductivity.first==elementIndex)
00166 {
00167
00168 return mLastModifiedConductivity.second;
00169 }
00170 else
00171 {
00172
00173
00174
00175 unsigned containing_mechanics_elem = mpMeshPair->rGetCoarseElementsForFineElementCentroids()[elementIndex];
00176 c_matrix<double,DIM,DIM>& r_deformation_gradient = mDeformationGradientsForEachMechanicsElement[containing_mechanics_elem];
00177
00178
00179 c_matrix<double,DIM,DIM> inv_F = Inverse(r_deformation_gradient);
00180 mLastModifiedConductivity.second = prod(inv_F, rOriginalConductivity);
00181 mLastModifiedConductivity.second = prod(mLastModifiedConductivity.second, trans(inv_F));
00182
00183
00184 mLastModifiedConductivity.first = elementIndex;
00185 return mLastModifiedConductivity.second;
00186 }
00187 }
00188
00189
00190
00191
00193
00194
00195
00196
00197
00198
00199
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224 template<unsigned DIM>
00225 CardiacElectroMechanicsProblem<DIM>::CardiacElectroMechanicsProblem(
00226 ContractionModel contractionModel,
00227 TetrahedralMesh<DIM,DIM>* pElectricsMesh,
00228 QuadraticMesh<DIM>* pMechanicsMesh,
00229 std::vector<unsigned> fixedMechanicsNodes,
00230 AbstractCardiacCellFactory<DIM>* pCellFactory,
00231 double endTime,
00232 double electricsPdeTimeStep,
00233 double mechanicsSolveTimestep,
00234 double contractionModelOdeTimeStep,
00235 std::string outputDirectory = "") :
00236 mpMeshPair(NULL)
00237 {
00238
00239 MechanicsEventHandler::Reset();
00240 MechanicsEventHandler::BeginEvent(MechanicsEventHandler::ALL);
00241
00242
00243
00244
00245 HeartEventHandler::Disable();
00246
00247 mContractionModel = contractionModel;
00248
00249
00250 assert(endTime > 0);
00251 mEndTime = endTime;
00252
00253
00254 HeartConfig::Instance()->SetSimulationDuration(mEndTime);
00255
00256 assert(electricsPdeTimeStep>0);
00257 mElectricsTimeStep = electricsPdeTimeStep;
00258
00259 mNumElecTimestepsPerMechTimestep = (unsigned) floor((mechanicsSolveTimestep/electricsPdeTimeStep)+0.5);
00260 if(fabs(mNumElecTimestepsPerMechTimestep*electricsPdeTimeStep - mechanicsSolveTimestep) > 1e-6)
00261 {
00262 EXCEPTION("Electrics PDE timestep does not divide mechanics solve timestep");
00263 }
00264 mMechanicsTimeStep = mechanicsSolveTimestep;
00265
00266
00267
00268 assert(mechanicsSolveTimestep <= 10);
00269
00270 assert(contractionModelOdeTimeStep <= mMechanicsTimeStep+1e-14);
00271 mContractionModelOdeTimeStep = contractionModelOdeTimeStep;
00272
00273
00274
00275
00276 assert(pCellFactory != NULL);
00277 mpMonodomainProblem = new MonodomainProblem<DIM>(pCellFactory);
00278
00279
00280 mWriteOutput = (outputDirectory!="");
00281 if(mWriteOutput)
00282 {
00283 mOutputDirectory = outputDirectory;
00284
00285 OutputFileHandler handler(mOutputDirectory);
00286 mDeformationOutputDirectory = mOutputDirectory + "/deformation";
00287 HeartConfig::Instance()->SetOutputDirectory(mOutputDirectory + "/electrics");
00288 HeartConfig::Instance()->SetOutputFilenamePrefix("voltage");
00289 }
00290 else
00291 {
00292 mDeformationOutputDirectory = "";
00293 }
00294 mNoElectricsOutput = false;
00295
00296
00297 mpElectricsMesh = pElectricsMesh;
00298 mpMechanicsMesh = pMechanicsMesh;
00299 mFixedNodes = fixedMechanicsNodes;
00300
00301 mpCardiacMechSolver = NULL;
00302
00303
00304
00305 std::string log_dir = mOutputDirectory;
00306 LogFile::Instance()->Set(2, mOutputDirectory);
00307 LogFile::Instance()->WriteHeader("Electromechanics");
00308 LOG(2, DIM << "d Implicit CardiacElectroMechanics Simulation:");
00309 LOG(2, "End time = " << mEndTime << ", electrics time step = " << mElectricsTimeStep << ", mechanics timestep = " << mMechanicsTimeStep << "\n");
00310 LOG(2, "Contraction model ode timestep " << mContractionModelOdeTimeStep);
00311 LOG(2, "Output is written to " << mOutputDirectory << "/[deformation/electrics]");
00312
00313 if(mpElectricsMesh != NULL)
00314 {
00315 LOG(2, "Electrics mesh has " << mpElectricsMesh->GetNumNodes() << " nodes");
00316 }
00317 if(mpMechanicsMesh != NULL)
00318 {
00319 LOG(2, "Mechanics mesh has " << mpMechanicsMesh->GetNumNodes() << " nodes");
00320 }
00321
00322 mIsWatchedLocation = false;
00323 mWatchedElectricsNodeIndex = UNSIGNED_UNSET;
00324 mWatchedMechanicsNodeIndex = UNSIGNED_UNSET;
00325
00326 mFibreSheetDirectionsFile = "";
00327
00328 mConductivityAffectedByDeformationMef = false;
00329 mCellModelsAffectedByDeformationMef = false;
00330
00331 mLastModifiedConductivity.first = UNSIGNED_UNSET;
00332
00333
00334 }
00335
00336 template<unsigned DIM>
00337 CardiacElectroMechanicsProblem<DIM>::~CardiacElectroMechanicsProblem()
00338 {
00344 if(mIsWatchedLocation && mpMechanicsMesh)
00345 {
00346 mpWatchedLocationFile->close();
00347 }
00348
00349 delete mpMonodomainProblem;
00350
00351 delete mpCardiacMechSolver;
00352
00353 delete mpMeshPair;
00354
00355 LogFile::Close();
00356 }
00357
00358 template<unsigned DIM>
00359 void CardiacElectroMechanicsProblem<DIM>::Initialise()
00360 {
00361 LOG(2, "Initialising..");
00362
00363 assert(mpElectricsMesh!=NULL);
00364 assert(mpMechanicsMesh!=NULL);
00365 assert(mpCardiacMechSolver==NULL);
00366
00367 if(mIsWatchedLocation)
00368 {
00369 DetermineWatchedNodes();
00370 }
00371
00372
00373
00374 mpMonodomainProblem->SetMesh(mpElectricsMesh);
00375 HeartConfig::Instance()->SetIntracellularConductivities(Create_c_vector(1.75,1.75,1.75));
00376 mpMonodomainProblem->Initialise();
00377
00378
00379
00380
00381 switch(mContractionModel)
00382 {
00383 case NASH2004:
00384
00385 mpCardiacMechSolver = new ExplicitCardiacMechanicsSolver<DIM>(mContractionModel,mpMechanicsMesh,mDeformationOutputDirectory,mFixedNodes);
00386 break;
00387 case KERCHOFFS2003:
00388
00389 mpCardiacMechSolver = new ImplicitCardiacMechanicsSolver<DIM>(mContractionModel,mpMechanicsMesh,mDeformationOutputDirectory,mFixedNodes);
00390 break;
00391 case NHS:
00392
00393 mpCardiacMechSolver = new ImplicitCardiacMechanicsSolver<DIM>(mContractionModel,mpMechanicsMesh,mDeformationOutputDirectory,mFixedNodes);
00394 break;
00395 default:
00396 EXCEPTION("Invalid contraction model, options are: KERCHOFFS2003 or NHS");
00397 }
00398
00399 if(mFibreSheetDirectionsFile!="")
00400 {
00401 mpCardiacMechSolver->SetVariableFibreSheetDirections(mFibreSheetDirectionsFile, mFibreSheetDirectionsDefinedPerQuadraturePoint);
00402 }
00403
00404
00405
00406 mpMeshPair = new FineCoarseMeshPair<DIM>(*mpElectricsMesh, *mpMechanicsMesh);
00407 mpMeshPair->SetUpBoxesOnFineMesh();
00408 mpMeshPair->ComputeFineElementsAndWeightsForCoarseQuadPoints(*(mpCardiacMechSolver->GetQuadratureRule()), false);
00409 mpMeshPair->DeleteFineBoxCollection();
00410
00411
00412
00413
00414 if(mConductivityAffectedByDeformationMef || mCellModelsAffectedByDeformationMef)
00415 {
00416 mpMeshPair->SetUpBoxesOnCoarseMesh();
00417 }
00418
00419 if(mCellModelsAffectedByDeformationMef)
00420 {
00421
00422
00423 mpMeshPair->ComputeCoarseElementsForFineNodes(false);
00424
00425
00426 mStretchesForEachMechanicsElement.resize(mpMechanicsMesh->GetNumElements(),1.0);
00427 }
00428
00429 if(mConductivityAffectedByDeformationMef)
00430 {
00431
00432
00433 mpMeshPair->ComputeCoarseElementsForFineElementCentroids(false);
00434
00435
00436 mDeformationGradientsForEachMechanicsElement.resize(mpMechanicsMesh->GetNumElements(),identity_matrix<double>(DIM));
00437
00438
00439
00440 mpMonodomainProblem->GetMonodomainTissue()->SetConductivityModifier(this);
00441 }
00442
00443 if(mWriteOutput)
00444 {
00445 TrianglesMeshWriter<DIM,DIM> mesh_writer(mOutputDirectory,"electrics_mesh",false);
00446 mesh_writer.WriteFilesUsingMesh(*mpElectricsMesh);
00447 }
00448 }
00449
00450 template<unsigned DIM>
00451 void CardiacElectroMechanicsProblem<DIM>::Solve()
00452 {
00453
00454
00455 if(mpCardiacMechSolver==NULL)
00456 {
00457 Initialise();
00458 }
00459
00460 boost::shared_ptr<BoundaryConditionsContainer<DIM,DIM,1> > p_bcc(new BoundaryConditionsContainer<DIM,DIM,1>);
00461 p_bcc->DefineZeroNeumannOnMeshBoundary(mpElectricsMesh, 0);
00462 mpMonodomainProblem->SetBoundaryConditionsContainer(p_bcc);
00463
00464
00465
00466 AbstractDynamicLinearPdeSolver<DIM,DIM,1>* p_electrics_solver
00467 = mpMonodomainProblem->CreateSolver();
00468
00469
00470 Vec voltage=NULL;
00471 Vec initial_voltage = mpMonodomainProblem->CreateInitialCondition();
00472
00473 unsigned num_quad_points = mpCardiacMechSolver->GetTotalNumQuadPoints();
00474 std::vector<double> interpolated_calcium_concs(num_quad_points, 0.0);
00475 std::vector<double> interpolated_voltages(num_quad_points, 0.0);
00476
00477
00478 unsigned counter = 0;
00479
00480 TimeStepper stepper(0.0, mEndTime, mMechanicsTimeStep);
00481
00482 CmguiDeformedSolutionsWriter<DIM>* p_cmgui_writer = NULL;
00483
00484 unsigned mech_writer_counter = 0;
00485 if (mWriteOutput)
00486 {
00487 mpCardiacMechSolver->SetWriteOutput();
00488 mpCardiacMechSolver->WriteCurrentDeformation("solution",mech_writer_counter);
00489
00490 p_cmgui_writer = new CmguiDeformedSolutionsWriter<DIM>(mOutputDirectory+"/deformation/cmgui",
00491 "solution",
00492 *(this->mpMechanicsMesh),
00493 WRITE_QUADRATIC_MESH);
00494 std::vector<std::string> fields;
00495 fields.push_back("V");
00496 p_cmgui_writer->SetAdditionalFieldNames(fields);
00497 p_cmgui_writer->WriteInitialMesh();
00498
00499
00500 if(!mNoElectricsOutput)
00501 {
00502
00503
00504
00505 HeartConfig::Instance()->SetPrintingTimeStep(mMechanicsTimeStep);
00506 mpMonodomainProblem->InitialiseWriter();
00507 mpMonodomainProblem->WriteOneStep(stepper.GetTime(), initial_voltage);
00508 }
00509
00510 if(mIsWatchedLocation)
00511 {
00512 WriteWatchedLocationData(stepper.GetTime(), initial_voltage);
00513 }
00514 }
00515
00516 PrepareForSolve();
00517
00518 while (!stepper.IsTimeAtEnd())
00519 {
00520 LOG(2, "\nCurrent time = " << stepper.GetTime());
00521 #ifdef MECH_VERBOSE // defined in AbstractNonlinearElasticitySolver
00522
00523 std::cout << "\n\n ** Current time = " << stepper.GetTime() << "\n";
00524 #endif
00525
00532 if(mCellModelsAffectedByDeformationMef)
00533 {
00534
00535
00536 mpCardiacMechSolver->ComputeDeformationGradientAndStretchInEachElement(mDeformationGradientsForEachMechanicsElement, mStretchesForEachMechanicsElement);
00537
00538
00539 for(unsigned global_index = mpElectricsMesh->GetDistributedVectorFactory()->GetLow();
00540 global_index < mpElectricsMesh->GetDistributedVectorFactory()->GetHigh();
00541 global_index++)
00542 {
00543 unsigned containing_elem = mpMeshPair->rGetCoarseElementsForFineNodes()[global_index];
00544 double stretch = mStretchesForEachMechanicsElement[containing_elem];
00545 mpMonodomainProblem->GetTissue()->GetCardiacCell(global_index)->SetStretch(stretch);
00546 }
00547
00548
00549
00550
00551 }
00552
00553 p_electrics_solver->SetTimeStep(mElectricsTimeStep);
00554
00560 LOG(2, " Solving electrics");
00561 MechanicsEventHandler::BeginEvent(MechanicsEventHandler::NON_MECH);
00562 for(unsigned i=0; i<mNumElecTimestepsPerMechTimestep; i++)
00563 {
00564 double current_time = stepper.GetTime() + i*mElectricsTimeStep;
00565 double next_time = stepper.GetTime() + (i+1)*mElectricsTimeStep;
00566
00567
00568 p_electrics_solver->SetTimes(current_time, next_time);
00569 p_electrics_solver->SetInitialCondition( initial_voltage );
00570
00571 voltage = p_electrics_solver->Solve();
00572
00573 PetscReal min_voltage, max_voltage;
00574 VecMax(voltage,PETSC_NULL,&max_voltage);
00575 VecMin(voltage,PETSC_NULL,&min_voltage);
00576 if(i==0)
00577 {
00578 LOG(2, " minimum and maximum voltage is " << min_voltage <<", "<<max_voltage);
00579 }
00580 else if(i==1)
00581 {
00582 LOG(2, " ..");
00583 }
00584
00585 VecDestroy(initial_voltage);
00586 initial_voltage = voltage;
00587 }
00588
00589 if(mConductivityAffectedByDeformationMef)
00590 {
00591 p_electrics_solver->SetMatrixIsNotAssembled();
00592 }
00593
00594
00600
00601
00602
00603 LOG(2, " Interpolating Ca_I and voltage");
00604
00605 ReplicatableVector voltage_repl(voltage);
00606
00607
00608
00609 ReplicatableVector calcium_repl(mpElectricsMesh->GetNumNodes());
00610 PetscInt lo, hi;
00611 VecGetOwnershipRange(voltage, &lo, &hi);
00612 for(int index=lo; index<hi; index++)
00613 {
00614 calcium_repl[index] = mpMonodomainProblem->GetTissue()->GetCardiacCell(index)->GetIntracellularCalciumConcentration();
00615 }
00616 PetscTools::Barrier();
00617 calcium_repl.Replicate(lo,hi);
00618
00619
00620 for(unsigned i=0; i<mpMeshPair->rGetElementsAndWeights().size(); i++)
00621 {
00622 double interpolated_CaI = 0;
00623 double interpolated_voltage = 0;
00624
00625 Element<DIM,DIM>& element = *(mpElectricsMesh->GetElement(mpMeshPair->rGetElementsAndWeights()[i].ElementNum));
00626 for(unsigned node_index = 0; node_index<element.GetNumNodes(); node_index++)
00627 {
00628 unsigned global_node_index = element.GetNodeGlobalIndex(node_index);
00629 double CaI_at_node = calcium_repl[global_node_index];
00630 interpolated_CaI += CaI_at_node*mpMeshPair->rGetElementsAndWeights()[i].Weights(node_index);
00631 interpolated_voltage += voltage_repl[global_node_index]*mpMeshPair->rGetElementsAndWeights()[i].Weights(node_index);
00632 }
00633
00634 interpolated_calcium_concs[i] = interpolated_CaI;
00635 interpolated_voltages[i] = interpolated_voltage;
00636 }
00637
00638 LOG(2, " Setting Ca_I. max value = " << Max(interpolated_calcium_concs));
00639
00640
00641
00642
00643
00644 mpCardiacMechSolver->SetCalciumAndVoltage(interpolated_calcium_concs, interpolated_voltages);
00645 MechanicsEventHandler::EndEvent(MechanicsEventHandler::NON_MECH);
00646
00647
00648
00654 LOG(2, " Solving mechanics ");
00655 mpCardiacMechSolver->SetWriteOutput(false);
00656
00657
00658
00659 mpCardiacMechSolver->SetCurrentTime(stepper.GetTime());
00660
00662
00663
00664 MechanicsEventHandler::BeginEvent(MechanicsEventHandler::ALL_MECH);
00665 mpCardiacMechSolver->Solve(stepper.GetTime(), stepper.GetNextTime(), mContractionModelOdeTimeStep);
00666 MechanicsEventHandler::EndEvent(MechanicsEventHandler::ALL_MECH);
00667
00668 LOG(2, " Number of newton iterations = " << mpCardiacMechSolver->GetNumNewtonIterations());
00669
00670
00671 stepper.AdvanceOneTimeStep();
00672 counter++;
00673
00674
00680 MechanicsEventHandler::BeginEvent(MechanicsEventHandler::OUTPUT);
00681 if(mWriteOutput && (counter%WRITE_EVERY_NTH_TIME==0))
00682 {
00683 LOG(2, " Writing output");
00684
00685 mech_writer_counter++;
00686 mpCardiacMechSolver->SetWriteOutput();
00687 mpCardiacMechSolver->WriteCurrentDeformation("solution",mech_writer_counter);
00688
00689 p_cmgui_writer->WriteDeformationPositions(rGetDeformedPosition(), counter);
00690
00691 if(!mNoElectricsOutput)
00692 {
00693 mpMonodomainProblem->mpWriter->AdvanceAlongUnlimitedDimension();
00694 mpMonodomainProblem->WriteOneStep(stepper.GetTime(), voltage);
00695 }
00696
00697 if(mIsWatchedLocation)
00698 {
00699 WriteWatchedLocationData(stepper.GetTime(), voltage);
00700 }
00701 OnEndOfTimeStep(counter);
00702 }
00703 MechanicsEventHandler::EndEvent(MechanicsEventHandler::OUTPUT);
00704
00705
00706 LogFile::Instance()->WriteElapsedTime(" ");
00707 }
00708
00709
00710
00711 if ((mWriteOutput) && (!mNoElectricsOutput))
00712 {
00713 HeartConfig::Instance()->Reset();
00714 mpMonodomainProblem->mpWriter->Close();
00715 delete mpMonodomainProblem->mpWriter;
00716
00717 std::string input_dir = mOutputDirectory+"/electrics";
00718
00719
00720 std::string config_directory = HeartConfig::Instance()->GetOutputDirectory();
00721 HeartConfig::Instance()->SetOutputDirectory(input_dir);
00722
00723
00724
00725
00726 Hdf5ToCmguiConverter<DIM,DIM> cmgui_converter(input_dir,"voltage",mpElectricsMesh);
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740 VoltageInterpolaterOntoMechanicsMesh<DIM> cnverter(*mpElectricsMesh,*mpMechanicsMesh,input_dir,"voltage");
00741
00742
00743 HeartConfig::Instance()->SetOutputDirectory(config_directory);
00744 }
00745
00746 if(p_cmgui_writer)
00747 {
00748 if(mNoElectricsOutput)
00749 {
00750 p_cmgui_writer->WriteCmguiScript();
00751 }
00752 else
00753 {
00754 p_cmgui_writer->WriteCmguiScript("../../electrics/cmgui_output/voltage_mechanics_mesh");
00755 }
00756 delete p_cmgui_writer;
00757 }
00758 VecDestroy(voltage);
00759 delete p_electrics_solver;
00760
00761 MechanicsEventHandler::EndEvent(MechanicsEventHandler::ALL);
00762 }
00763
00764
00765
00766 template<unsigned DIM>
00767 double CardiacElectroMechanicsProblem<DIM>::Max(std::vector<double>& vec)
00768 {
00769 double max = -1e200;
00770 for(unsigned i=0; i<vec.size(); i++)
00771 {
00772 if(vec[i]>max) max=vec[i];
00773 }
00774 return max;
00775 }
00776
00777 template<unsigned DIM>
00778 void CardiacElectroMechanicsProblem<DIM>::SetNoElectricsOutput()
00779 {
00780 mNoElectricsOutput = true;
00781 }
00782
00783 template<unsigned DIM>
00784 void CardiacElectroMechanicsProblem<DIM>::SetWatchedPosition(c_vector<double,DIM> watchedLocation)
00785 {
00786 mIsWatchedLocation = true;
00787 mWatchedLocation = watchedLocation;
00788 }
00789
00790 template<unsigned DIM>
00791 void CardiacElectroMechanicsProblem<DIM>::SetVariableFibreSheetDirectionsFile(std::string fibreSheetDirectionsFile, bool definedPerQuadraturePoint)
00792 {
00793 mFibreSheetDirectionsFile = fibreSheetDirectionsFile;
00794 mFibreSheetDirectionsDefinedPerQuadraturePoint = definedPerQuadraturePoint;
00795 }
00796
00797 template<unsigned DIM>
00798 std::vector<c_vector<double,DIM> >& CardiacElectroMechanicsProblem<DIM>::rGetDeformedPosition()
00799 {
00800 return mpCardiacMechSolver->rGetDeformedPosition();
00801 }
00802
00803
00804
00805
00807
00809
00810
00811 template class CardiacElectroMechanicsProblem<2>;
00812 template class CardiacElectroMechanicsProblem<3>;