void TestSimpleSimulation() throw(Exception) { /*Simulation parameters*/ HeartConfig::Instance()->SetSimulationDuration(0.7); //ms (falls over after this) HeartConfig::Instance()->SetUseAbsoluteTolerance(1e-6); //HeartConfig::Instance()->SetOdeTimeStep(0.01); const double width = 0.1; const double height = 0.1; const double depth = 0.1; const unsigned num_elem_x = 8; const double space_step = width/num_elem_x; /* Make the mesh*/ DistributedTetrahedralMesh<3,3> mesh; mesh.ConstructRegularSlabMesh(space_step, width, height, depth); /*Create a cell factory of the type we defined above. */ GeneralPlaneStimulusCellFactory<CellLuoRudy1991FromCellML, 3> cell_factory(num_elem_x, width); /* monodomain problem class using (a pointer to) the cell factory */ BidomainProblem<3> problem( &cell_factory ); problem.SetMesh(&mesh); /* * HOW_TO_TAG Cardiac/Problem definition * Set discrete '''cuboid''' areas to have heterogeneous (intra- and/or extra-cellular) conductivity tensors. */ std::vector<ChasteCuboid<3> > input_areas; std::vector< c_vector<double,3> > intra_conductivities; std::vector< c_vector<double,3> > extra_conductivities; ChastePoint<3> corner_a(width/2, 0, 0); ChastePoint<3> corner_b(width, height, depth); input_areas.push_back(ChasteCuboid<3> (corner_a, corner_b)); //within the cuboid intra_conductivities.push_back( Create_c_vector(0.1, 0.1, 0.1) ); extra_conductivities.push_back( Create_c_vector(0.0, 0.0, 0.0) ); //This test should *fail* if you comment out the following line //(which blocks conductivity on the RHS of the slab). HeartConfig::Instance()->SetConductivityHeterogeneities(input_areas, intra_conductivities, extra_conductivities); //elsewhere HeartConfig::Instance()->SetIntracellularConductivities(Create_c_vector(1.2, 1.2, 1.2)); HeartConfig::Instance()->SetExtracellularConductivities(Create_c_vector(1.2, 1.2, 1.2)); /* set parameters*/ // HeartConfig::Instance()->SetSurfaceAreaToVolumeRatio(1.0); // HeartConfig::Instance()->SetCapacitance(1.0); /* Output Directory and prefix (for the hdf5 file), relative to CHASTE_TEST_OUTPUT*/ HeartConfig::Instance()->SetOutputDirectory("slab_results_het_halfcond"); HeartConfig::Instance()->SetOutputFilenamePrefix("Slab_small"); /* Initialise the problem*/ problem.Initialise(); /* Solve the PDE monodomain equaion*/ problem.Solve(); ReplicatableVector voltage_replicated(problem.GetSolution()); TS_ASSERT_EQUALS(mesh.GetNumNodes() * 2, voltage_replicated.GetSize()); unsigned lo, hi; lo = mesh.GetDistributedVectorFactory()->GetLow(); hi = mesh.GetDistributedVectorFactory()->GetHigh(); for (unsigned i=lo; i<hi; i++) { double x = mesh.GetNode(i)->rGetLocation()[0]; if (x<width/2) { //Left side is stimulated TS_ASSERT_LESS_THAN(-71.0,voltage_replicated[2 * i]); } else if (x>width/2) { //Right side is blocked TS_ASSERT_LESS_THAN(voltage_replicated[2 * i],-82.0); } } }
void TestConductionVelocityConvergesFasterWithSvi1d() { double h[3] = {0.001,0.01,0.02}; unsigned probe_node_index[3] = {300, 30, 15}; unsigned number_of_nodes[3] = {1001, 101, 51}; std::vector<double> conduction_vel_ici(3); std::vector<double> conduction_vel_svi(3); ReplicatableVector final_voltage_ici; ReplicatableVector final_voltage_svi; //HeartConfig::Instance()->SetUseRelativeTolerance(1e-8); HeartConfig::Instance()->SetSimulationDuration(4.0); //ms HeartConfig::Instance()->SetOdePdeAndPrintingTimeSteps(0.01, 0.01, 0.01); for (unsigned i=0; i<3; i++) { // ICI - ionic current interpolation - the default { DistributedTetrahedralMesh<1,1> mesh; mesh.ConstructRegularSlabMesh(h[i], 1.0); TS_ASSERT_EQUALS(mesh.GetNumNodes(), number_of_nodes[i]); //Double check (for later) that the indexing is as expected if (mesh.GetDistributedVectorFactory()->IsGlobalIndexLocal( probe_node_index[i] )) { TS_ASSERT_DELTA(mesh.GetNode( probe_node_index[i] )->rGetLocation()[0], 0.3, 1e-8); } std::stringstream output_dir; output_dir << "MonodomainIci_" << h[i]; HeartConfig::Instance()->SetOutputDirectory(output_dir.str()); HeartConfig::Instance()->SetOutputFilenamePrefix("results"); // need to have this for i=1,2 cases!! HeartConfig::Instance()->SetUseStateVariableInterpolation(false); BlockCellFactory<1> cell_factory; MonodomainProblem<1> monodomain_problem( &cell_factory ); monodomain_problem.SetMesh(&mesh); monodomain_problem.Initialise(); monodomain_problem.Solve(); final_voltage_ici.ReplicatePetscVector(monodomain_problem.GetSolution()); //// see #1633 //// end time needs to be increased for these (say, to 7ms) // Hdf5DataReader simulation_data(OutputFileHandler::GetChasteTestOutputDirectory() + output_dir.str(), // "results", false); // PropagationPropertiesCalculator ppc(&simulation_data); // unsigned node_at_0_04 = (unsigned)round(0.04/h[i]); // unsigned node_at_0_40 = (unsigned)round(0.40/h[i]); // assert(fabs(mesh.GetNode(node_at_0_04)->rGetLocation()[0]-0.04)<1e-6); // assert(fabs(mesh.GetNode(node_at_0_40)->rGetLocation()[0]-0.40)<1e-6); // conduction_vel_ici[i] = ppc.CalculateConductionVelocity(node_at_0_04,node_at_0_40,0.36); // std::cout << "conduction_vel_ici = " << conduction_vel_ici[i] << "\n"; } // SVI - state variable interpolation { DistributedTetrahedralMesh<1,1> mesh; mesh.ConstructRegularSlabMesh(h[i], 1.0); //Double check (for later) that the indexing is as expected if (mesh.GetDistributedVectorFactory()->IsGlobalIndexLocal( probe_node_index[i] )) { TS_ASSERT_DELTA(mesh.GetNode( probe_node_index[i] )->rGetLocation()[0], 0.3, 1e-8); } std::stringstream output_dir; output_dir << "MonodomainSvi_" << h[i]; HeartConfig::Instance()->SetOutputDirectory(output_dir.str()); HeartConfig::Instance()->SetOutputFilenamePrefix("results"); HeartConfig::Instance()->SetUseStateVariableInterpolation(); BlockCellFactory<1> cell_factory; MonodomainProblem<1> monodomain_problem( &cell_factory ); monodomain_problem.SetMesh(&mesh); monodomain_problem.Initialise(); monodomain_problem.Solve(); final_voltage_svi.ReplicatePetscVector(monodomain_problem.GetSolution()); // Hdf5DataReader simulation_data(OutputFileHandler::GetChasteTestOutputDirectory() + output_dir.str(), // "results", false); // PropagationPropertiesCalculator ppc(&simulation_data); // unsigned node_at_0_04 = (unsigned)round(0.04/h[i]); // unsigned node_at_0_40 = (unsigned)round(0.40/h[i]); // assert(fabs(mesh.GetNode(node_at_0_04)->rGetLocation()[0]-0.04)<1e-6); // assert(fabs(mesh.GetNode(node_at_0_40)->rGetLocation()[0]-0.40)<1e-6); // conduction_vel_svi[i] = ppc.CalculateConductionVelocity(node_at_0_04,node_at_0_40,0.36); // std::cout << "conduction_vel_svi = " << conduction_vel_svi[i] << "\n"; } if (i==0) // finest mesh { for (unsigned j=0; j<final_voltage_ici.GetSize(); j++) { // visually checked they agree at this mesh resolution, and chosen tolerance from results TS_ASSERT_DELTA(final_voltage_ici[j], final_voltage_svi[j], 0.3); if (final_voltage_ici[j]>-80) { // shouldn't be exactly equal, as long as away from resting potential TS_ASSERT_DIFFERS(final_voltage_ici[j], final_voltage_svi[j]); } } double ici_voltage_at_0_03_finest_mesh = final_voltage_ici[ probe_node_index[i] ]; double svi_voltage_at_0_03_finest_mesh = final_voltage_svi[ probe_node_index[i] ]; TS_ASSERT_DELTA(svi_voltage_at_0_03_finest_mesh, 11.0067, 2e-4); //hardcoded value from fine svi TS_ASSERT_DELTA(ici_voltage_at_0_03_finest_mesh, 11.0067, 1.2e-1); //hardcoded value from fine svi } else if (i==1) { double ici_voltage_at_0_03_middle_mesh = final_voltage_ici[ probe_node_index[i] ]; double svi_voltage_at_0_03_middle_mesh = final_voltage_svi[ probe_node_index[i] ]; // ICI conduction velocity > SVI conduction velocity // and both should be greater than CV on finesh mesh TS_ASSERT_DELTA(ici_voltage_at_0_03_middle_mesh, 19.8924, 1e-3); TS_ASSERT_DELTA(svi_voltage_at_0_03_middle_mesh, 14.9579, 1e-3); } else { double ici_voltage_at_0_03_coarse_mesh = final_voltage_ici[ probe_node_index[i] ]; double svi_voltage_at_0_03_coarse_mesh = final_voltage_svi[ probe_node_index[i] ]; // ICI conduction velocity even greater than SVI conduction // velocity TS_ASSERT_DELTA(ici_voltage_at_0_03_coarse_mesh, 24.4938, 1e-3); TS_ASSERT_DELTA(svi_voltage_at_0_03_coarse_mesh, 17.3131, 1e-3); } } }
void Test2dBathMultipleBathConductivities() throw (Exception) { HeartConfig::Instance()->SetSimulationDuration(2.0); //ms HeartConfig::Instance()->SetOutputDirectory("BidomainBath2dMultipleBathConductivities"); HeartConfig::Instance()->SetOutputFilenamePrefix("bidomain_bath_2d"); HeartConfig::Instance()->SetOdeTimeStep(0.001); //ms ??? std::set<unsigned> tissue_ids; tissue_ids.insert(0); // Same as default value defined in HeartConfig std::set<unsigned> bath_ids; bath_ids.insert(2); bath_ids.insert(3); bath_ids.insert(4); HeartConfig::Instance()->SetTissueAndBathIdentifiers(tissue_ids, bath_ids); // need to create a cell factory but don't want any intra stim, so magnitude // of stim is zero. c_vector<double,2> centre; centre(0) = 0.05; // cm centre(1) = 0.05; // cm BathCellFactory<2> cell_factory( 0.0, centre); BidomainWithBathProblem<2> bidomain_problem( &cell_factory ); DistributedTetrahedralMesh<2,2> mesh; mesh.ConstructRegularSlabMesh(0.05, 0.9, 0.9); // set the x<0.25 and x>0.75 regions as the bath region for (AbstractTetrahedralMesh<2,2>::ElementIterator iter = mesh.GetElementIteratorBegin(); iter != mesh.GetElementIteratorEnd(); ++iter) { double x = iter->CalculateCentroid()[0]; double y = iter->CalculateCentroid()[1]; if( (x>0.3) && (x<0.6) && (y>0.3) && (y<0.6) ) { iter->SetAttribute(0); } else { if (y<0.2) { iter->SetAttribute(2); } else if (y<0.7) { iter->SetAttribute(3); } else if (y<0.9) { iter->SetAttribute(4); } } } std::map<unsigned, double> multiple_bath_conductivities; multiple_bath_conductivities[2] = 7.0; multiple_bath_conductivities[3] = 1.0; multiple_bath_conductivities[4] = 0.001; HeartConfig::Instance()->SetBathMultipleConductivities(multiple_bath_conductivities); double boundary_flux = -3.0e3; double start_time = 0.0; double duration = 1.0; // of the stimulus, in ms HeartConfig::Instance()->SetElectrodeParameters(false, 0, boundary_flux, start_time, duration); bidomain_problem.SetMesh(&mesh); bidomain_problem.Initialise(); bidomain_problem.Solve(); DistributedVector distributed_solution = bidomain_problem.GetSolutionDistributedVector(); DistributedVector::Stripe voltage(distributed_solution, 0); /* * We are checking the last time step. This test will only make sure that an AP is triggered. */ bool ap_triggered = false; for (DistributedVector::Iterator index = distributed_solution.Begin(); index!= distributed_solution.End(); ++index) { // test V = 0 for all bath nodes and that an AP is triggered in the tissue if (HeartRegionCode::IsRegionBath( mesh.GetNode(index.Global)->GetRegion() )) // bath { TS_ASSERT_DELTA(voltage[index], 0.0, 1e-12); } else if (voltage[index] > 0.0)//at the last time step { ap_triggered = true; } } TS_ASSERT(PetscTools::ReplicateBool(ap_triggered)); }