/** * Tests archiving of the tissue object. * It creates one, changes the default values of some member variables and saves. * Then it tries to load from the archive and checks that the member variables are with the right values. */ void TestSaveAndLoadExtendedBidomainTissue() throw (Exception) { HeartConfig::Instance()->Reset(); // Archive settings FileFinder archive_dir("extended_tissue_archive", RelativeTo::ChasteTestOutput); std::string archive_file = "extended_bidomain_tissue.arch"; bool cache_replication_saved = false; double saved_printing_timestep = 2.0; double default_printing_timestep = HeartConfig::Instance()->GetPrintingTimeStep(); c_matrix<double, 3, 3> intra_tensor_before_archiving; c_matrix<double, 3, 3> intra_tensor_second_cell_before_archiving; c_matrix<double, 3, 3> extra_tensor_before_archiving; //creation and save { // This call is required to set the appropriate conductivity media and to make sure that HeartConfig // knows the mesh filename despite we use our own mesh reader. HeartConfig::Instance()->SetMeshFileName("mesh/test/data/cube_136_elements"); TrianglesMeshReader<3,3> mesh_reader("mesh/test/data/cube_136_elements"); DistributedTetrahedralMesh<3,3> mesh; mesh.ConstructFromMeshReader(mesh_reader); UnStimulatedCellFactory first_cell; StimulatedCellFactory second_cell; ExtracellularStimulusFactory extra_factory; first_cell.SetMesh(&mesh); second_cell.SetMesh(&mesh); extra_factory.SetMesh(&mesh); ExtendedBidomainTissue<3> extended_tissue( &first_cell, &second_cell , &extra_factory); //set a value different from default for the conductivities of the second cell extended_tissue.SetIntracellularConductivitiesSecondCell(Create_c_vector(25.0,26.0,27.0)); //this is normally done by the problem class, but in this test we do it manually extended_tissue.CreateIntracellularConductivityTensorSecondCell(); extended_tissue.SetCacheReplication(cache_replication_saved); // Not the default to check it is archived... //shuffle default values to check if they get archived properly extended_tissue.SetAmFirstCell(11.0); extended_tissue.SetAmSecondCell(22.0); extended_tissue.SetAmGap(33.0); extended_tissue.SetCmFirstCell(44.0); extended_tissue.SetCmSecondCell(55.0); extended_tissue.SetGGap(66.0); //again, away from default value to check for archiving extended_tissue.SetUserSuppliedExtracellularStimulus(true); //set some heterogeneities in Ggap std::vector<boost::shared_ptr<AbstractChasteRegion<3> > > heterogeneity_areas; std::vector<double> Ggap_values; ChastePoint<3> cornerA(-1, -1, 0); ChastePoint<3> cornerB(0.001, 0.001, 0.001); boost::shared_ptr<ChasteCuboid<3> > p_cuboid_1(new ChasteCuboid<3>(cornerA, cornerB)); heterogeneity_areas.push_back(p_cuboid_1); //within the first area Ggap_values.push_back(143.0); extended_tissue.SetGgapHeterogeneities(heterogeneity_areas, Ggap_values); extended_tissue.CreateGGapConductivities(); // Some checks to make sure HeartConfig is being saved and loaded by this too. HeartConfig::Instance()->SetPrintingTimeStep(saved_printing_timestep); TS_ASSERT_DELTA(HeartConfig::Instance()->GetPrintingTimeStep(), saved_printing_timestep, 1e-9); intra_tensor_before_archiving = extended_tissue.rGetIntracellularConductivityTensor(0); intra_tensor_second_cell_before_archiving = extended_tissue.rGetIntracellularConductivityTensorSecondCell(0); extra_tensor_before_archiving = extended_tissue.rGetExtracellularConductivityTensor(0); // Save ArchiveOpener<boost::archive::text_oarchive, std::ofstream> arch_opener(archive_dir, archive_file); boost::archive::text_oarchive* p_arch = arch_opener.GetCommonArchive(); AbstractCardiacTissue<3>* const p_archive_bidomain_tissue = &extended_tissue; (*p_arch) << p_archive_bidomain_tissue; HeartConfig::Reset(); TS_ASSERT_DELTA(HeartConfig::Instance()->GetPrintingTimeStep(), default_printing_timestep, 1e-9); TS_ASSERT_DIFFERS(saved_printing_timestep, default_printing_timestep); } //load { ArchiveOpener<boost::archive::text_iarchive, std::ifstream> arch_opener(archive_dir, archive_file); boost::archive::text_iarchive* p_arch = arch_opener.GetCommonArchive(); AbstractCardiacTissue<3>* p_abstract_tissue; (*p_arch) >> p_abstract_tissue; assert(p_abstract_tissue!=NULL); //dynamic cast so we are able to test specific variables of ExtendedBidomainTissue ExtendedBidomainTissue<3>* p_extended_tissue = dynamic_cast<ExtendedBidomainTissue<3>*>(p_abstract_tissue); assert(p_extended_tissue != NULL); const c_matrix<double, 3, 3>& intra_tensor_after_archiving = p_extended_tissue->rGetIntracellularConductivityTensor(0); const c_matrix<double, 3, 3>& intra_tensor_second_cell_after_archiving = p_extended_tissue->rGetIntracellularConductivityTensorSecondCell(0); const c_matrix<double, 3, 3>& extra_tensor_after_archiving = p_extended_tissue->rGetExtracellularConductivityTensor(0); //check before archiving = after archiving for(unsigned i=0; i<3; i++) { for(unsigned j=0; j<3; j++) { TS_ASSERT_DELTA(intra_tensor_before_archiving(i,j), intra_tensor_after_archiving(i,j), 1e-9); TS_ASSERT_DELTA(intra_tensor_second_cell_before_archiving(i,j), intra_tensor_second_cell_after_archiving(i,j), 1e-9); TS_ASSERT_DELTA(extra_tensor_before_archiving(i,j), extra_tensor_after_archiving(i,j), 1e-9); } } //check that the member variable mIntracellularConductivitiesSecondCell was archived properly TS_ASSERT_EQUALS(p_extended_tissue->GetIntracellularConductivitiesSecondCell()(0),25.0); TS_ASSERT_EQUALS(p_extended_tissue->GetIntracellularConductivitiesSecondCell()(1),26.0); TS_ASSERT_EQUALS(p_extended_tissue->GetIntracellularConductivitiesSecondCell()(2),27.0); //check that we get the same values from the archive which are different from the default TS_ASSERT_EQUALS(p_extended_tissue->GetAmFirstCell(), 11.0); TS_ASSERT_EQUALS(p_extended_tissue->GetAmSecondCell(), 22.0); TS_ASSERT_EQUALS(p_extended_tissue->GetAmGap(), 33.0); TS_ASSERT_EQUALS(p_extended_tissue->GetCmFirstCell(), 44.0); TS_ASSERT_EQUALS(p_extended_tissue->GetCmSecondCell(), 55.0); TS_ASSERT_EQUALS(p_extended_tissue->GetGGap(), 66.0); // We shouldn't need to re-build the mesh, but we use it to check that the new tissue has the same mesh // Also, when testing in parallel, we use it to get the vector factory to loop over the nodes we own. // this is because p_extended_tissue->pGetMesh()->GetDistributedVectorFactory() doesn't compile (discards qualifier stuff caused by use of const). TrianglesMeshReader<3,3> mesh_reader("mesh/test/data/cube_136_elements"); DistributedTetrahedralMesh<3,3> mesh; mesh.ConstructFromMeshReader(mesh_reader); TS_ASSERT_EQUALS(mesh.GetNumNodes(), p_extended_tissue->pGetMesh()->GetNumNodes());//note: this is allowed because GetNumNodes has const in the signature //check archiving of stimulus for first cell at some random times (it is unstimulated everywhere at all times) for (unsigned i = 0; i < mesh.GetNumNodes(); i++) { if (mesh.GetDistributedVectorFactory()->IsGlobalIndexLocal(i)) { TS_ASSERT_EQUALS(p_extended_tissue->GetCardiacCell(i)->GetIntracellularStimulus(0.0), 0.0); TS_ASSERT_EQUALS(p_extended_tissue->GetCardiacCell(i)->GetIntracellularStimulus(0.1), 0.0); TS_ASSERT_EQUALS(p_extended_tissue->GetCardiacCell(i)->GetIntracellularStimulus(2.5), 0.0); TS_ASSERT_EQUALS(p_extended_tissue->GetCardiacCell(i)->GetIntracellularStimulus(28.9), 0.0); } } //for second cell and other stuff, we probe nodes 0 and 1. unsigned node_0 = 0u; unsigned node_1 = 1u; //If the test is run in parallel, we need to work out the new indices const std::vector<unsigned>& r_permutation = mesh.rGetNodePermutation(); if (!r_permutation.empty()) { node_0 = r_permutation[0u]; node_1 = r_permutation[1u]; } //second cell is stimulated in the corner (node 0) from time 0 to 1. check it gets all this after loading if (mesh.GetDistributedVectorFactory()->IsGlobalIndexLocal(node_0)) { TS_ASSERT_EQUALS(p_extended_tissue->GetCardiacSecondCell(node_0)->GetIntracellularStimulus(0.5), -105.0*1400); TS_ASSERT_EQUALS(p_extended_tissue->GetCardiacSecondCell(node_0)->GetIntracellularStimulus(2.5), 0.0); //find local index of (the new) node_0, it should be in the heterogeneity region unsigned ownership_range_low = mesh.GetDistributedVectorFactory()->GetLow(); unsigned local_index = node_0 - ownership_range_low; //std::cout<<local_index<<std::endl; TS_ASSERT_EQUALS(p_extended_tissue->rGetGapsDistributed()[local_index],143.0);//g_gap value inside heterogeneity region } //node 0 has extracellular stimulus (1 ms from 0.1) if (mesh.GetDistributedVectorFactory()->IsGlobalIndexLocal(node_0)) { TS_ASSERT_EQUALS(p_extended_tissue->GetExtracellularStimulus(node_0)->GetStimulus(0.0), 0); TS_ASSERT_EQUALS(p_extended_tissue->GetExtracellularStimulus(node_0)->GetStimulus(0.5), -428000); TS_ASSERT_EQUALS(p_extended_tissue->GetExtracellularStimulus(node_0)->GetStimulus(1.0), -428000); TS_ASSERT_EQUALS(p_extended_tissue->GetExtracellularStimulus(node_0)->GetStimulus(1.15), 0); } //node 1 doesn't if (mesh.GetDistributedVectorFactory()->IsGlobalIndexLocal(node_1)) { TS_ASSERT_EQUALS(p_extended_tissue->GetExtracellularStimulus(node_1)->GetStimulus(0.0), 0); TS_ASSERT_EQUALS(p_extended_tissue->GetExtracellularStimulus(node_1)->GetStimulus(0.5), 0); TS_ASSERT_EQUALS(p_extended_tissue->GetExtracellularStimulus(node_1)->GetStimulus(1.0), 0); TS_ASSERT_EQUALS(p_extended_tissue->GetExtracellularStimulus(node_1)->GetStimulus(1.15), 0); //find local index of (the new) node_1, it should NOT be in the heterogeneity region unsigned ownership_range_low = mesh.GetDistributedVectorFactory()->GetLow(); unsigned local_index = node_1 - ownership_range_low; TS_ASSERT_EQUALS(p_extended_tissue->rGetGapsDistributed()[local_index],66.0);//standard g_gap value, outside heterogeneity region } //check the archiving of the flag (it would be false by default, but we set it to true before archiving) TS_ASSERT_EQUALS(p_extended_tissue->HasTheUserSuppliedExtracellularStimulus(),true); TS_ASSERT_EQUALS(cache_replication_saved, p_extended_tissue->GetDoCacheReplication()); TS_ASSERT_DELTA(HeartConfig::Instance()->GetPrintingTimeStep(), saved_printing_timestep, 1e-9); TS_ASSERT_DIFFERS(saved_printing_timestep, default_printing_timestep); // Test we are testing something in case default changes delete p_extended_tissue; } }
void TestSaveAndLoadCardiacPDE() { HeartConfig::Instance()->Reset(); // Archive settings FileFinder archive_dir("tissue_archive", RelativeTo::ChasteTestOutput); std::string archive_file = "bidomain_tissue.arch"; bool cache_replication_saved = false; double saved_printing_timestep = 2.0; double default_printing_timestep = HeartConfig::Instance()->GetPrintingTimeStep(); std::vector<cp::media_type> media_types; media_types.push_back(cp::media_type::Orthotropic); media_types.push_back(cp::media_type::Axisymmetric); media_types.push_back(cp::media_type::NoFibreOrientation); for (std::vector<cp::media_type>::iterator it = media_types.begin(); it != media_types.end(); ++it) { c_matrix<double, 3, 3> intra_tensor_before_archiving; c_matrix<double, 3, 3> extra_tensor_before_archiving; { // This call is required to set the appropriate conductivity media and to make sure that HeartConfig // knows the mesh filename despite we use our own mesh reader. HeartConfig::Instance()->SetMeshFileName("mesh/test/data/3D_Single_tetrahedron_element", *it); TrianglesMeshReader<3,3> mesh_reader("mesh/test/data/3D_Single_tetrahedron_element"); TetrahedralMesh<3,3> mesh; mesh.ConstructFromMeshReader(mesh_reader); MyCardiacCellFactory<3> cell_factory; cell_factory.SetMesh(&mesh); BidomainTissue<3> bidomain_tissue( &cell_factory ); bidomain_tissue.SetCacheReplication(cache_replication_saved); // Not the default to check it is archived... // Some checks to make sure HeartConfig is being saved and loaded by this too. HeartConfig::Instance()->SetPrintingTimeStep(saved_printing_timestep); TS_ASSERT_DELTA(HeartConfig::Instance()->GetPrintingTimeStep(), saved_printing_timestep, 1e-9); intra_tensor_before_archiving = bidomain_tissue.rGetIntracellularConductivityTensor(0); extra_tensor_before_archiving = bidomain_tissue.rGetExtracellularConductivityTensor(0); // Save ArchiveOpener<boost::archive::text_oarchive, std::ofstream> arch_opener(archive_dir, archive_file); boost::archive::text_oarchive* p_arch = arch_opener.GetCommonArchive(); AbstractCardiacTissue<3>* const p_archive_bidomain_tissue = &bidomain_tissue; (*p_arch) << p_archive_bidomain_tissue; HeartConfig::Reset(); TS_ASSERT_DELTA(HeartConfig::Instance()->GetPrintingTimeStep(), default_printing_timestep, 1e-9); TS_ASSERT_DIFFERS(saved_printing_timestep, default_printing_timestep); } { ArchiveOpener<boost::archive::text_iarchive, std::ifstream> arch_opener(archive_dir, archive_file); boost::archive::text_iarchive* p_arch = arch_opener.GetCommonArchive(); AbstractCardiacTissue<3>* p_bidomain_tissue; (*p_arch) >> p_bidomain_tissue; assert(p_bidomain_tissue!=NULL); const c_matrix<double, 3, 3>& intra_tensor_after_archiving = p_bidomain_tissue->rGetIntracellularConductivityTensor(0); const c_matrix<double, 3, 3>& extra_tensor_after_archiving = dynamic_cast<BidomainTissue<3>*>(p_bidomain_tissue)->rGetExtracellularConductivityTensor(0); //Naughty Gary using dynamic cast, but only for testing... for(unsigned i=0; i<3; i++) { for(unsigned j=0; j<3; j++) { TS_ASSERT_DELTA(intra_tensor_before_archiving(i,j), intra_tensor_after_archiving(i,j), 1e-9); TS_ASSERT_DELTA(extra_tensor_before_archiving(i,j), extra_tensor_after_archiving(i,j), 1e-9); } } TS_ASSERT_EQUALS(cache_replication_saved, p_bidomain_tissue->GetDoCacheReplication()); TS_ASSERT_DELTA(HeartConfig::Instance()->GetPrintingTimeStep(), saved_printing_timestep, 1e-9); TS_ASSERT_DIFFERS(saved_printing_timestep, default_printing_timestep); // Test we are testing something in case default changes delete p_bidomain_tissue; } } }