37 #ifndef ABSTRACTCONVERGENCETESTER_HPP_
38 #define ABSTRACTCONVERGENCETESTER_HPP_
40 #include "BidomainProblem.hpp"
41 #include "MonodomainProblem.hpp"
50 #include "AbstractTetrahedralMesh.hpp"
51 #include "TrianglesMeshReader.hpp"
52 #include "AbstractCardiacCellFactory.hpp"
53 #include "OutputFileHandler.hpp"
54 #include "TrianglesMeshWriter.hpp"
55 #include "PropagationPropertiesCalculator.hpp"
56 #include "Hdf5DataReader.hpp"
57 #include "GeneralPlaneStimulusCellFactory.hpp"
58 #include "CuboidMeshConstructor.hpp"
59 #include "ZeroStimulusCellFactory.hpp"
60 #include "SimpleStimulus.hpp"
61 #include "ConstBoundaryCondition.hpp"
62 #include "StimulusBoundaryCondition.hpp"
64 #include "Warnings.hpp"
67 typedef enum StimulusType_
78 template <
class CELL,
unsigned DIM>
83 std::vector< boost::shared_ptr<SimpleStimulus> >
mpStimuli;
106 assert(numElemAcross%4 == 0);
108 for (
unsigned level=0; level<
mLevels; level++)
110 double this_stim = fullStim - (level*fullStim)/mLevels;
126 unsigned level = (
unsigned) d_level;
127 assert(fabs(level-d_level) < DBL_MAX);
194 virtual void Converge(std::string nameOfTest)=0;
202 template<
class CARDIAC_PROBLEM,
unsigned DIM>
203 void SetConductivities(CARDIAC_PROBLEM& rCardiacProblem);
205 template<
unsigned DIM>
208 c_vector<double, DIM> conductivities;
209 for (
unsigned i=0; i<DIM; i++)
211 conductivities[i] = 1.75;
215 for (
unsigned i=0; i<DIM; i++)
217 conductivities[i] = 7.0;
222 template<
unsigned DIM>
225 c_vector<double, DIM> conductivities;
226 for (
unsigned i=0; i<DIM; i++)
228 conductivities[i] = 1.75;
237 template<
class CELL,
class CARDIAC_PROBLEM,
unsigned DIM,
unsigned PROBLEM_DIM>
249 const std::string mesh_dir =
"ConvergenceMesh";
257 out_stream p_conv_info_file;
260 std::cout <<
"=========================== Beginning Test...==================================\n";
261 p_conv_info_file = conv_info_handler.
OpenOutputFile(nameOfTest+
"_info.csv");
262 (*p_conv_info_file) <<
"#Abcisa\t"
265 <<
"Max absolute err\t"
266 <<
"APD90_1st_quad\t"
267 <<
"APD90_3rd_quad\t"
268 <<
"Conduction velocity (relative diffs)" << std::endl;
272 double prev_apd90_first_qn=0.0;
273 double prev_apd90_third_qn=0.0;
274 double prev_cond_velocity=0.0;
275 std::vector<double> prev_voltage;
276 std::vector<double> prev_times;
285 #define COVERAGE_IGNORE
286 while (printing_step < 1.0e-4)
288 printing_step *= 2.0;
289 std::cout<<
"Warning: PrintingTimeStep increased\n";
291 #undef COVERAGE_IGNORE
293 #define COVERAGE_IGNORE
302 #undef COVERAGE_IGNORE
324 #define COVERAGE_IGNORE
326 #undef COVERAGE_IGNORE
345 CARDIAC_PROBLEM cardiac_problem(p_cell_factory);
346 cardiac_problem.SetMesh(&mesh);
349 unsigned third_quadrant_node;
350 unsigned first_quadrant_node;
362 first_quadrant_node = (n+1)*(n/2)+ n/4 ;
363 third_quadrant_node = (n+1)*(n/2)+3*n/4 ;
368 const unsigned first_quadrant_nodes_3d[5]={61, 362, 2452, 17960, 137296};
369 const unsigned third_quadrant_nodes_3d[5]={63, 366, 2460, 17976, 137328};
371 first_quadrant_node = first_quadrant_nodes_3d[this->
MeshNum];
372 third_quadrant_node = third_quadrant_nodes_3d[this->
MeshNum];
380 double mesh_width=constructor.
GetWidth();
383 std::vector<unsigned> nodes_to_be_output;
384 nodes_to_be_output.push_back(first_quadrant_node);
385 nodes_to_be_output.push_back(third_quadrant_node);
386 cardiac_problem.SetOutputNodes(nodes_to_be_output);
391 SetConductivities(cardiac_problem);
393 cardiac_problem.Initialise();
406 iter = r_mesh.GetBoundaryElementIteratorBegin();
407 while (iter != r_mesh.GetBoundaryElementIteratorEnd())
409 double x = ((*iter)->CalculateCentroid())[0];
413 p_bcc->AddNeumannBoundaryCondition(*iter, p_bc_stim);
418 cardiac_problem.SetBoundaryConditionsContainer(p_bcc);
428 cardiac_problem.Solve();
432 WARNING(
"This run threw an exception. Check convergence results\n");
445 std::vector<double> transmembrane_potential = results_reader.
GetVariableOverTime(
"V", third_quadrant_node);
453 std::stringstream plot_file_name_stream;
454 plot_file_name_stream<< nameOfTest <<
"_Third_quadrant_node_run_"<< file_num <<
".csv";
455 out_stream p_plot_file = plot_file_handler.
OpenOutputFile(plot_file_name_stream.str());
456 for (
unsigned data_point = 0; data_point<time_series.size(); data_point++)
458 (*p_plot_file) << time_series[data_point] <<
"\t" << transmembrane_potential[data_point] <<
"\n";
460 p_plot_file->close();
464 std::vector<double> transmembrane_potential_1qd=results_reader.
GetVariableOverTime(
"V", first_quadrant_node);
466 std::stringstream plot_file_name_stream;
467 plot_file_name_stream<< nameOfTest <<
"_First_quadrant_node_run_"<< file_num <<
".csv";
468 out_stream p_plot_file = plot_file_handler.
OpenOutputFile(plot_file_name_stream.str());
469 for (
unsigned data_point = 0; data_point<time_series.size(); data_point++)
471 (*p_plot_file) << time_series_1qd[data_point] <<
"\t" << transmembrane_potential_1qd[data_point] <<
"\n";
473 p_plot_file->close();
481 #define COVERAGE_IGNORE
487 #undef COVERAGE_IGNORE
492 #define COVERAGE_IGNORE
493 std::cout <<
"Warning - this run threw an exception in calculating propagation. Check convergence results\n";
495 #undef COVERAGE_IGNORE
497 double cond_velocity_error = 1e10;
498 double apd90_first_qn_error = 1e10;
499 double apd90_third_qn_error = 1e10;
503 if (prev_cond_velocity != 0.0)
505 cond_velocity_error = fabs(
ConductionVelocity - prev_cond_velocity) / prev_cond_velocity;
507 #define COVERAGE_IGNORE
508 if (prev_apd90_first_qn != 0.0)
510 apd90_first_qn_error = fabs(
Apd90FirstQn - prev_apd90_first_qn) / prev_apd90_first_qn;
512 if (prev_apd90_third_qn != 0.0)
514 apd90_third_qn_error = fabs(
Apd90ThirdQn - prev_apd90_third_qn) / prev_apd90_third_qn;
516 if (apd90_first_qn_error == 0.0)
518 apd90_first_qn_error = DBL_EPSILON;
520 if (apd90_third_qn_error == 0.0)
522 apd90_third_qn_error = DBL_EPSILON;
524 #undef COVERAGE_IGNORE
525 if (cond_velocity_error == 0.0)
527 cond_velocity_error = DBL_EPSILON;
536 double max_abs_error = 0;
537 double sum_sq_abs_error =0;
538 double sum_sq_prev_voltage = 0;
539 double sum_sq_abs_error_full =0;
540 double sum_sq_prev_voltage_full = 0;
545 unsigned time_factor=(time_series.size()-1) / (prev_times.size()-1);
546 assert (time_factor == 1 || time_factor == 2 || time_factor == 8);
548 for (
unsigned data_point = 0; data_point<prev_times.size(); data_point++)
550 unsigned this_data_point=time_factor*data_point;
552 assert(time_series[this_data_point] == prev_times[data_point]);
553 double abs_error = fabs(transmembrane_potential[this_data_point]-prev_voltage[data_point]);
554 max_abs_error = (abs_error > max_abs_error) ? abs_error : max_abs_error;
556 sum_sq_abs_error_full += abs_error*abs_error;
557 sum_sq_prev_voltage_full += prev_voltage[data_point] * prev_voltage[data_point];
558 if (time_series[this_data_point] <= 8.0)
561 sum_sq_abs_error += abs_error*abs_error;
562 sum_sq_prev_voltage += prev_voltage[data_point] * prev_voltage[data_point];
569 prev_voltage = transmembrane_potential;
570 prev_times = time_series;
575 double l2_norm_upstroke = sqrt(sum_sq_abs_error/sum_sq_prev_voltage);
576 double l2_norm_full = sqrt(sum_sq_abs_error_full/sum_sq_prev_voltage_full);
580 (*p_conv_info_file) << std::setprecision(8)
582 << l2_norm_full <<
"\t"
583 << l2_norm_upstroke <<
"\t"
584 << max_abs_error <<
"\t"
585 <<
Apd90FirstQn <<
" "<< apd90_first_qn_error <<
""<<
"\t"
586 <<
Apd90ThirdQn <<
" "<< apd90_third_qn_error <<
""<<
"\t"
592 #define COVERAGE_IGNORE
593 assert (time_series.size() != 1u);
594 if (time_series.back() == 0.0)
596 std::cout <<
"Failed after successful convergence - give up this convergence test\n";
599 #undef COVERAGE_IGNORE
603 if ( time_series.back() != 0.0)
617 delete p_cell_factory;
624 p_conv_info_file->close();
626 std::cout <<
"Results: " << std::endl;
631 std::cout << info_file.rdbuf();
647 std::cout<<
"================================================================================"<<std::endl;
648 std::cout<<
"Solving in " << DIM <<
"D\t";
649 std::cout<<
"Space step " << scaling <<
" cm (mesh " << this->
MeshNum <<
")" <<
"\n";
650 std::cout<<
"PDE step " << this->
PdeTimeStep <<
" ms" <<
"\t";
651 std::cout<<
"ODE step " << this->
OdeTimeStep <<
" ms" <<
"\t";
663 std::cout<<
"Stimulus = Plane\n";
667 std::cout<<
"Stimulus = Ramped first quarter\n";
671 std::cout<<
"Stimulus = Neumann\n";
677 std::time( &rawtime );
678 std::cout << std::ctime(&rawtime);
683 #define COVERAGE_IGNORE
684 std::cout<<
"Using absolute stimulus of "<<this->
AbsoluteStimulus<<std::endl;
685 #undef COVERAGE_IGNORE
687 std::cout << std::flush;
713 assert(result.size()==0);
714 assert(times.size()==0);
bool GetUseAbsoluteTolerance() const
void SetOutputDirectory(const std::string &rOutputDirectory)
double SmallPow(double x, unsigned exponent)
boost::shared_ptr< ZeroStimulus > mpZeroStimulus
std::string GetAbsolutePath() const
boost::shared_ptr< AbstractIvpOdeSolver > mpSolver
virtual void Converge(std::string nameOfTest)=0
virtual double Abscissa()=0
bool SimulateFullActionPotential
virtual bool GiveUpConvergence()=0
double GetAbsoluteTolerance() const
std::vector< boost::shared_ptr< SimpleStimulus > > mpStimuli
static double GetElapsedTime()
double GetRelativeTolerance() const
AbstractCardiacCellInterface * CreateCardiacCellForTissueNode(Node< DIM > *pNode)
void SetSimulationDuration(double simulationDuration)
out_stream OpenOutputFile(const std::string &rFileName, std::ios_base::openmode mode=std::ios::out|std::ios::trunc) const
void SetExtracellularConductivities(const c_vector< double, 3 > &rExtraConductivities)
void Construct(AbstractTetrahedralMesh< ELEMENT_DIM, SPACE_DIM > &rMesh, unsigned meshRefinementNum, double meshWidth)
double CalculateActionPotentialDuration(const double percentage, unsigned globalNodeIndex)
virtual void PopulateStandardResult(std::vector< double > &result, std::vector< double > ×)
FileFinder FindFile(std::string leafName) const
std::string GetMessage() const
double ConductionVelocity
std::vector< double > GetUnlimitedDimensionValues()
virtual void SetInitialConvergenceParameters()=0
double RelativeConvergenceCriterion
double CalculateConductionVelocity(unsigned globalNearNodeIndex, unsigned globalFarNodeIndex, const double euclideanDistance)
std::vector< double > GetVariableOverTime(const std::string &rVariableName, unsigned nodeIndex)
ChastePoint< SPACE_DIM > GetPoint() const
void Converge(std::string nameOfTest)
void SetIntracellularConductivities(const c_vector< double, 3 > &rIntraConductivities)
unsigned GetNumElements()
void SetMeshWidth(double meshWidth)
void SetOutputFilenamePrefix(const std::string &rOutputFilenamePrefix)
static HeartConfig * Instance()
virtual void UpdateConvergenceParameters()=0
RampedQuarterStimulusCellFactory(double meshWidth, unsigned numElemAcross, double fullStim=-1e7)
void SetOdePdeAndPrintingTimeSteps(double odeTimeStep, double pdeTimeStep, double printingTimeStep)