void TestExtendedTissueHeterogeneousGgap3D() throw (Exception)
    {
        HeartConfig::Instance()->Reset();
        TrianglesMeshReader<3,3> mesh_reader("mesh/test/data/cube_2mm_12_elements");
        TetrahedralMesh<3,3> mesh;
        mesh.ConstructFromMeshReader(mesh_reader);

        std::vector<boost::shared_ptr<AbstractChasteRegion<3> > > heterogeneity_areas;
        std::vector<double> Ggap_values;

        //first cuboid include node 0
        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);

        //second cuboid include node 6
        ChastePoint<3> cornerC(0.199, 0.199, 0.199);
        ChastePoint<3> cornerD(0.25, 0.25, 0.25);
        boost::shared_ptr<ChasteCuboid<3> > p_cuboid_2(new ChasteCuboid<3>(cornerC, cornerD));
        ChasteCuboid<3> cuboid_2(cornerC, cornerD);

        heterogeneity_areas.push_back(p_cuboid_2);

        //within the first area
        Ggap_values.push_back(143.0);
        //within the second area
        Ggap_values.push_back(9143.0);
        //elsewhere
        double isotropic_ggap=586.0;

        StimulatedCellFactory stimulated_cell_factory;
        UnStimulatedCellFactory unstimulated_cell_factory;
        ExtracellularStimulusFactory extracellular_stimulus_factory;

        stimulated_cell_factory.SetMesh(&mesh);
        unstimulated_cell_factory.SetMesh(&mesh);
        extracellular_stimulus_factory.SetMesh(&mesh);

        ExtendedBidomainTissue<3>  extended_bidomain_tissue( &stimulated_cell_factory,  &unstimulated_cell_factory, &extracellular_stimulus_factory);

        extended_bidomain_tissue.SetGGap(isotropic_ggap);//this is what the problem class does first

        extended_bidomain_tissue.SetGgapHeterogeneities(heterogeneity_areas, Ggap_values);
        extended_bidomain_tissue.CreateGGapConductivities();

        unsigned probe_node_1 = 0u;
        unsigned probe_node_2 = 6u;
        unsigned probe_node_3 = 5u;

        const std::vector<unsigned>& r_permutation = mesh.rGetNodePermutation();
        if (!r_permutation.empty())
        {
            probe_node_1 = r_permutation[0u];//within first cuboid
            probe_node_2 = r_permutation[6u];//within second cuboid
            probe_node_3 = r_permutation[5u];//elsewhere
        }

        Vec vector =  mesh.GetDistributedVectorFactory()->CreateVec();
        DistributedVector dist_solution = mesh.GetDistributedVectorFactory()->CreateDistributedVector(vector);
        for (DistributedVector::Iterator index = dist_solution.Begin();
             index != dist_solution.End();
             ++index)
        {
            extended_bidomain_tissue.UpdateAdditionalCaches(index.Global, index.Local, 2.0);
        }
        extended_bidomain_tissue.ReplicateAdditionalCaches();

        //Ggap
        TS_ASSERT_EQUALS(extended_bidomain_tissue.rGetGgapCacheReplicated()[probe_node_1],143.0);//within first cuboid
        TS_ASSERT_EQUALS(extended_bidomain_tissue.rGetGgapCacheReplicated()[probe_node_2],9143.0);//within second cuboid
        TS_ASSERT_EQUALS(extended_bidomain_tissue.rGetGgapCacheReplicated()[probe_node_3],586.0);//elsewhere

        PetscTools::Destroy(vector);
    }
    /**This test checks heterogeneous conductivities*/
    void TestExtendedTissueHeterogeneous3D() throw (Exception)
    {
        HeartConfig::Instance()->Reset();
        TrianglesMeshReader<3,3> mesh_reader("mesh/test/data/cube_2mm_12_elements");
        TetrahedralMesh<3,3> mesh;
        mesh.ConstructFromMeshReader(mesh_reader);

        std::vector<ChasteCuboid<3> > heterogeneity_area;
        std::vector< c_vector<double,3> > intra_conductivities;
        std::vector< c_vector<double,3> > extra_conductivities;

        //first cuboid include element 0
        ChastePoint<3> cornerA(-1, -1, 0);
        ChastePoint<3> cornerB(0.1, 0.2, 0.2);
        ChasteCuboid<3> cuboid_1(cornerA, cornerB);
        heterogeneity_area.push_back(cuboid_1);

        //second cuboid include element 4
        ChastePoint<3> cornerC(0.11, 0.0, 0);
        ChastePoint<3> cornerD(0.2, 0.11, 0.2);
        ChasteCuboid<3> cuboid_2(cornerC, cornerD);

        heterogeneity_area.push_back(cuboid_2);

        //within the first area
        intra_conductivities.push_back( Create_c_vector(1.0, 2.0, 3.0) );
        extra_conductivities.push_back( Create_c_vector(51.0, 52.0, 53.0) );

        //within the second area
        intra_conductivities.push_back( Create_c_vector(11.0, 22.0, 33.0) );
        extra_conductivities.push_back( Create_c_vector(151.0, 152.0, 153.0) );

        HeartConfig::Instance()->SetConductivityHeterogeneities(heterogeneity_area, intra_conductivities, extra_conductivities);

        //elsewhere
        double isotropic_intra_conductivity=15.0;
        double isotropic_extra_conductivity=65.0;

        HeartConfig::Instance()->SetIntracellularConductivities(Create_c_vector(isotropic_intra_conductivity, isotropic_intra_conductivity, isotropic_intra_conductivity));
        HeartConfig::Instance()->SetExtracellularConductivities(Create_c_vector(isotropic_extra_conductivity, isotropic_extra_conductivity, isotropic_extra_conductivity));

        StimulatedCellFactory stimulated_cell_factory;
        UnStimulatedCellFactory unstimulated_cell_factory;
        ExtracellularStimulusFactory extracellular_stimulus_factory;

        stimulated_cell_factory.SetMesh(&mesh);
        unstimulated_cell_factory.SetMesh(&mesh);
        extracellular_stimulus_factory.SetMesh(&mesh);

        ExtendedBidomainTissue<3>  extended_bidomain_tissue( &stimulated_cell_factory,  &unstimulated_cell_factory, &extracellular_stimulus_factory);

        extended_bidomain_tissue.SetIntracellularConductivitiesSecondCell(Create_c_vector(isotropic_intra_conductivity, isotropic_intra_conductivity, isotropic_intra_conductivity));
        extended_bidomain_tissue.CreateIntracellularConductivityTensorSecondCell();

        //first cell
//        TS_ASSERT_EQUALS(extended_bidomain_tissue.rGetIntracellularConductivityTensor(0u)(0,0),1.0);//within first cuboid
        //Line above commented due to curious problem with IntelProduction interprocedural optimisation
        TS_ASSERT_EQUALS(extended_bidomain_tissue.rGetIntracellularConductivityTensor(4u)(0,0),11.0);//within second cuboid
        TS_ASSERT_EQUALS(extended_bidomain_tissue.rGetIntracellularConductivityTensor(4u)(1,1),22.0);//within second cuboid
        TS_ASSERT_EQUALS(extended_bidomain_tissue.rGetIntracellularConductivityTensor(8u)(0,0),15.0);//elsewhere, e.g. element 8

        //second cell, should be the same as first cell
        TS_ASSERT_EQUALS(extended_bidomain_tissue.rGetIntracellularConductivityTensorSecondCell(0u)(0,0),1.0);//within first cuboid
        TS_ASSERT_EQUALS(extended_bidomain_tissue.rGetIntracellularConductivityTensorSecondCell(4u)(0,0),11.0);//within second cuboid
        TS_ASSERT_EQUALS(extended_bidomain_tissue.rGetIntracellularConductivityTensorSecondCell(4u)(1,1),22.0);//within second cuboid
        TS_ASSERT_EQUALS(extended_bidomain_tissue.rGetIntracellularConductivityTensorSecondCell(8u)(0,0),15.0);//elsewhere, e.g. element 8

        //sigma_e
        TS_ASSERT_EQUALS(extended_bidomain_tissue.rGetExtracellularConductivityTensor(0u)(0,0),51.0);//within first cuboid
        TS_ASSERT_EQUALS(extended_bidomain_tissue.rGetExtracellularConductivityTensor(4u)(0,0),151.0);//within second cuboid
        TS_ASSERT_EQUALS(extended_bidomain_tissue.rGetExtracellularConductivityTensor(4u)(1,1),152.0);//within second cuboid
        TS_ASSERT_EQUALS(extended_bidomain_tissue.rGetExtracellularConductivityTensor(8u)(0,0),65.0);//elsewhere, e.g. element 8

    }
    void TestExtendedTissueHeterogeneousConductivities2D() throw (Exception)
   {
       HeartConfig::Instance()->Reset();
       TrianglesMeshReader<2,2> mesh_reader("mesh/test/data/square_4_elements");
       TetrahedralMesh<2,2> mesh;
       mesh.ConstructFromMeshReader(mesh_reader);

       //HeartConfig setup needs to be in 3D anyway (hardcoded in HeartConfig).
       std::vector<ChasteCuboid<3> > heterogeneity_area;
       std::vector< c_vector<double,3> > intra_conductivities;
       std::vector< c_vector<double,3> > extra_conductivities;

       //first cuboid includes element 0
       ChastePoint<3> cornerA(-1, -1,-1);
       ChastePoint<3> cornerB(0.48, 2.0, 0.48);
       ChasteCuboid<3> cuboid_1(cornerA, cornerB);

       heterogeneity_area.push_back(cuboid_1);

       //second cuboid includes element 2
       ChastePoint<3> cornerC(0.52, -1, 0.52);
       ChastePoint<3> cornerD(2, 2, 2);
       ChasteCuboid<3> cuboid_2(cornerC, cornerD);

       heterogeneity_area.push_back(cuboid_2);

       //within the first area
       intra_conductivities.push_back( Create_c_vector(1.0, 2.0, 3.0) );
       extra_conductivities.push_back( Create_c_vector(51.0, 52.0, 53.0) );

       //within the second area
       intra_conductivities.push_back( Create_c_vector(11.0, 22.0, 33.0) );
       extra_conductivities.push_back( Create_c_vector(151.0, 152.0, 153.0) );

       HeartConfig::Instance()->SetConductivityHeterogeneities(heterogeneity_area, intra_conductivities, extra_conductivities);

       //elsewhere
       double isotropic_intra_conductivity=15.0;
       double isotropic_extra_conductivity=65.0;
       HeartConfig::Instance()->SetIntracellularConductivities(Create_c_vector(isotropic_intra_conductivity, isotropic_intra_conductivity, isotropic_intra_conductivity));
       HeartConfig::Instance()->SetExtracellularConductivities(Create_c_vector(isotropic_extra_conductivity, isotropic_extra_conductivity, isotropic_extra_conductivity));

       PlaneStimulusCellFactory<CellLuoRudy1991FromCellML, 2> cell_factory_1;
       PlaneStimulusCellFactory<CellLuoRudy1991FromCellML, 2> cell_factory_2;
       StimulusFactory2D extracellular_stimulus_factory;

       cell_factory_1.SetMesh(&mesh);
       cell_factory_2.SetMesh(&mesh);
       extracellular_stimulus_factory.SetMesh(&mesh);

       //2D tissue
       ExtendedBidomainTissue<2>  extended_bidomain_tissue( &cell_factory_1,  &cell_factory_2, &extracellular_stimulus_factory);

       // Do conductivity modifier here too (for coverage)
       SimpleConductivityModifier conductivity_modifier;
       extended_bidomain_tissue.SetConductivityModifier( &conductivity_modifier );

       extended_bidomain_tissue.SetIntracellularConductivitiesSecondCell(Create_c_vector(isotropic_intra_conductivity, isotropic_intra_conductivity));
       extended_bidomain_tissue.CreateIntracellularConductivityTensorSecondCell();

       //first cell
       TS_ASSERT_EQUALS(extended_bidomain_tissue.rGetIntracellularConductivityTensor(0u)(0,0),1.0);//within first cuboid
       TS_ASSERT_EQUALS(extended_bidomain_tissue.rGetIntracellularConductivityTensor(1u)(0,0),30.0);//within no cuboid (modified from 15 to 30!)
       TS_ASSERT_EQUALS(extended_bidomain_tissue.rGetIntracellularConductivityTensor(2u)(1,1),22.0);//within second cuboid
       TS_ASSERT_EQUALS(extended_bidomain_tissue.rGetIntracellularConductivityTensor(3u)(0,0),15.0);//within no cuboid

       //second cell, should be the same as first cell
       TS_ASSERT_EQUALS(extended_bidomain_tissue.rGetIntracellularConductivityTensorSecondCell(0u)(0,0),1.0);//within first cuboid
       TS_ASSERT_EQUALS(extended_bidomain_tissue.rGetIntracellularConductivityTensorSecondCell(1u)(0,0),30.0);//within no cuboid (modified from 15 to 30!)
       TS_ASSERT_EQUALS(extended_bidomain_tissue.rGetIntracellularConductivityTensorSecondCell(2u)(1,1),22.0);//within second cuboid
       TS_ASSERT_EQUALS(extended_bidomain_tissue.rGetIntracellularConductivityTensorSecondCell(3u)(0,0),15.0);//within no cuboid

       //sigma_e
       TS_ASSERT_EQUALS(extended_bidomain_tissue.rGetExtracellularConductivityTensor(0u)(0,0),51.0);//within first cuboid
       TS_ASSERT_EQUALS(extended_bidomain_tissue.rGetExtracellularConductivityTensor(1u)(0,0),130.0);//within no cuboid (modified from 65 to 130!)
       TS_ASSERT_EQUALS(extended_bidomain_tissue.rGetExtracellularConductivityTensor(2u)(1,1),152.0);//within second cuboid
       TS_ASSERT_EQUALS(extended_bidomain_tissue.rGetExtracellularConductivityTensor(3u)(0,0),65.0);//within no cuboid
   }
    void TestBidomainTissueWithHeterogeneousConductivitiesDistributed() throw (Exception)
    {
        HeartConfig::Instance()->Reset();

        // 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_2mm_12_elements", cp::media_type::NoFibreOrientation);

        TrianglesMeshReader<3,3> mesh_reader("mesh/test/data/cube_2mm_12_elements");

        // METIS_LIBRARY partition ensures that we have never own all the elements (even when there are as few as 2 processes)
        // DUMB and PARMETIS_LIBRARY may allow single process to see all the elements because it's a very small mesh
        DistributedTetrahedralMesh<3,3> mesh(DistributedTetrahedralMeshPartitionType::METIS_LIBRARY);
        mesh.ConstructFromMeshReader(mesh_reader);

        // Check that if we're in parallel no single process owns every element (to ensure that the conductivities
        // really are distributed).
        if (PetscTools::IsParallel())
        {
            TS_ASSERT_DIFFERS( mesh.GetNumElements(), mesh.GetNumLocalElements() );
        }

        std::vector<ChasteCuboid<3> > heterogeneity_area;
        std::vector< c_vector<double,3> > intra_conductivities;
        std::vector< c_vector<double,3> > extra_conductivities;

        //first cuboid include element 0
        ChastePoint<3> cornerA(-1, -1, 0);
        ChastePoint<3> cornerB(0.1, 0.2, 0.2);
        ChasteCuboid<3> cuboid_1(cornerA, cornerB);
        heterogeneity_area.push_back(cuboid_1);

        //second cuboid include element 4
        ChastePoint<3> cornerC(0.11, 0.0, 0);
        ChastePoint<3> cornerD(0.2, 0.11, 0.2);
        ChasteCuboid<3> cuboid_2(cornerC, cornerD);

        heterogeneity_area.push_back(cuboid_2);

        //within the first area
        intra_conductivities.push_back( Create_c_vector(1.0, 2.0, 3.0) );
        extra_conductivities.push_back( Create_c_vector(51.0, 52.0, 53.0) );

        //within the second area
        intra_conductivities.push_back( Create_c_vector(11.0, 22.0, 33.0) );
        extra_conductivities.push_back( Create_c_vector(151.0, 152.0, 153.0) );

        HeartConfig::Instance()->SetConductivityHeterogeneities(heterogeneity_area, intra_conductivities, extra_conductivities);


        //elsewhere
        double isotropic_intra_conductivity=15.0;
        double isotropic_extra_conductivity=65.0;
        HeartConfig::Instance()->SetIntracellularConductivities(Create_c_vector(isotropic_intra_conductivity, isotropic_intra_conductivity, isotropic_intra_conductivity));
        HeartConfig::Instance()->SetExtracellularConductivities(Create_c_vector(isotropic_extra_conductivity, isotropic_extra_conductivity, isotropic_extra_conductivity));

        PlaneStimulusCellFactory<CellLuoRudy1991FromCellML,3> cell_factory_for_het;
        cell_factory_for_het.SetMesh(&mesh);

        //CreateIntracellularConductivityTensor called in the constructor
        BidomainTissue<3> bidomain_tissue( &cell_factory_for_het );

        if (mesh.CalculateDesignatedOwnershipOfElement(0u))
        {
             TS_ASSERT_EQUALS(bidomain_tissue.rGetIntracellularConductivityTensor(0u)(0,0),1.0);//within first cuboid
             TS_ASSERT_EQUALS(bidomain_tissue.rGetExtracellularConductivityTensor(0u)(0,0),51.0);//within first cuboid
        }

        if (mesh.CalculateDesignatedOwnershipOfElement(4u))
        {
            TS_ASSERT_EQUALS(bidomain_tissue.rGetIntracellularConductivityTensor(4u)(0,0),11.0);//within second cuboid
            TS_ASSERT_EQUALS(bidomain_tissue.rGetIntracellularConductivityTensor(4u)(1,1),22.0);//within second cuboid
            TS_ASSERT_EQUALS(bidomain_tissue.rGetExtracellularConductivityTensor(4u)(0,0),151.0);//within second cuboid
            TS_ASSERT_EQUALS(bidomain_tissue.rGetExtracellularConductivityTensor(4u)(1,1),152.0);//within second cuboid
        }

        if (mesh.CalculateDesignatedOwnershipOfElement(8u))
        {
            TS_ASSERT_EQUALS(bidomain_tissue.rGetIntracellularConductivityTensor(8u)(0,0),15.0);//elsewhere, e.g. element 8
            TS_ASSERT_EQUALS(bidomain_tissue.rGetExtracellularConductivityTensor(8u)(0,0),65.0);//elsewhere, e.g. element 8
        }


    }