// This test relies on TestArchiveOpenerReadAndWrite succeeding
    void TestArchiveOpenerExceptions() throw(Exception)
    {
        OutputFileHandler handler(mArchiveDir, false);
        handler.SetArchiveDirectory();
        FileFinder archive_dir_finder(mArchiveDir, RelativeTo::ChasteTestOutput);
        std::string archive_base_name = "archive_opener.arch";

        // Remove the process-specific archive for this process
        FileFinder(ArchiveLocationInfo::GetProcessUniqueFilePath(archive_base_name)).Remove();
        TS_ASSERT_THROWS_CONTAINS(InputArchiveOpener archive_opener_in(archive_dir_finder, archive_base_name),
                                  "Cannot load secondary archive file: ");
        PetscTools::Barrier("TestArchiveOpenerExceptions-1");

        // Remove the main archive
        if (PetscTools::AmMaster())
        {
            ABORT_IF_THROWS(handler.FindFile(archive_base_name).Remove());
        }
        PetscTools::Barrier("TestArchiveOpenerExceptions-2");
        TS_ASSERT_THROWS_CONTAINS(InputArchiveOpener archive_opener_in(archive_dir_finder, archive_base_name),
                                  "Cannot load main archive file: ");

        // Remove write permissions on the archive dir
        //Note: changing *directory* permissions and other attributes does not work on Windows
        //See http://support.microsoft.com/kb/326549
#ifndef _MSC_VER
        if (PetscTools::AmMaster())
        {
            chmod(handler.GetOutputDirectoryFullPath().c_str(), CHASTE_READONLY);
        }
        PetscTools::Barrier("TestArchiveOpenerExceptions-3");

        /*
         * Now neither the master nor the slaves can write to their output files.
         * This avoids hitting a PetscBarrier() in the ~ArchiveOpener() because they
         * all throw an error first.
         *
         * If this test starts hanging it is because these TS_ASSERT_THROWS_CONTAINS
         * are not being thrown (rather than a real parallel calling problem).
         */
        if (PetscTools::AmMaster())
        {
            TS_ASSERT_THROWS_CONTAINS(OutputArchiveOpener archive_opener_out(archive_dir_finder, archive_base_name),
                                      "Failed to open main archive file for writing: ");
        }
        else
        {
            TS_ASSERT_THROWS_CONTAINS(OutputArchiveOpener archive_opener_out(archive_dir_finder, archive_base_name),
                                      "Failed to open secondary archive file for writing: ");
        }
        PetscTools::Barrier("TestArchiveOpenerExceptions-4");
        if (PetscTools::AmMaster())
        {
            // Restore permissions on the folder before allowing processes to continue.
            chmod(handler.GetOutputDirectoryFullPath().c_str(), CHASTE_READ_WRITE_EXECUTE);
        }
#endif // _MSC_VER
        PetscTools::Barrier("TestArchiveOpenerExceptions-5");
    }
    void TestAssemblerMeshType()
    {
        TetrahedralMesh<2,2> mesh;
        ContinuumMechanicsProblemDefinition<2> problem_defn(mesh);

        TS_ASSERT_THROWS_CONTAINS(ContinuumMechanicsNeumannBcsAssembler<2>(&mesh, &problem_defn),
                                  "Continuum mechanics solvers require a quadratic mesh");

        TetrahedralMesh<3,3> mesh3d;
        ContinuumMechanicsProblemDefinition<3> problem_defn3d(mesh3d);

        TS_ASSERT_THROWS_CONTAINS(ContinuumMechanicsNeumannBcsAssembler<3>(&mesh3d, &problem_defn3d),
                                  "Continuum mechanics solvers require a quadratic mesh");
    }
    void TestGetNodesByComponentValue() throw(Exception)
    {
        QuadraticMesh<2> mesh(0.1,1.0,1.0);
        mesh.Scale(1.0, 2.0); //historical reasons

        std::vector<unsigned> indices
          = NonlinearElasticityTools<2>::GetNodesByComponentValue(mesh,0,0);

        TS_ASSERT_EQUALS(indices.size(), 21u);
        for (unsigned i=0; i<indices.size(); i++)
        {
            TS_ASSERT_DELTA(mesh.GetNode(indices[i])->rGetLocation()[0], 0.0, 1e-12);
        }

        TrianglesMeshReader<3,3> reader("mesh/test/data/cube_136_elements");
        TetrahedralMesh<3,3> mesh3d;
        mesh3d.ConstructFromMeshReader(reader);
        mesh3d.Scale(0.3423244,1.343244325,6.23435);

        std::vector<unsigned> indices3d
          = NonlinearElasticityTools<3>::GetNodesByComponentValue(mesh3d,2,6.23435);

        TS_ASSERT_EQUALS(indices3d.size(), 13u);
        for (unsigned i=0; i<indices3d.size(); i++)
        {
            TS_ASSERT_DELTA(mesh3d.GetNode(indices3d[i])->rGetLocation()[2], 6.23435, 1e-12);
        }

        TS_ASSERT_THROWS_CONTAINS(NonlinearElasticityTools<3>::GetNodesByComponentValue(mesh3d, 2, 6.234),
                "Could not find any nodes on requested surface (note: tolerance = 1e-0");
    }
Ejemplo n.º 4
0
    void TestWithCoarseSlightlyOutsideFine() throw(Exception)
    {
        // Fine mesh is has h=0.1, on unit cube (so 6000 elements)
        TetrahedralMesh<3,3> fine_mesh;
        fine_mesh.ConstructRegularSlabMesh(0.1, 1.0,1.0,1.0);

        // Coarse mesh is slightly bigger than in previous test
        QuadraticMesh<3> coarse_mesh(1.0, 1.0, 1.0, 1.0); // xmax > 1.0
        coarse_mesh.Scale(1.03, 1.0, 1.0);

        FineCoarseMeshPair<3> mesh_pair(fine_mesh,coarse_mesh);

        GaussianQuadratureRule<3> quad_rule(3);

        // Need to call SetUpBoxesOnFineMesh first
        TS_ASSERT_THROWS_CONTAINS(mesh_pair.ComputeFineElementsAndWeightsForCoarseQuadPoints(quad_rule, true), "Call");

        mesh_pair.SetUpBoxesOnFineMesh(0.3);
        TS_ASSERT_EQUALS(mesh_pair.mpFineMeshBoxCollection->GetNumBoxes(), 4*4*4u);

        mesh_pair.ComputeFineElementsAndWeightsForCoarseQuadPoints(quad_rule, true);

        TS_ASSERT_EQUALS(mesh_pair.mNotInMesh.size(), 2u); // hardcoded
        TS_ASSERT_EQUALS(mesh_pair.mNotInMeshNearestElementWeights.size(), 2u);

        TS_ASSERT_EQUALS(mesh_pair.rGetElementsAndWeights().size(), 6*8u);

        for (unsigned i=0; i<mesh_pair.rGetElementsAndWeights().size(); i++)
        {
            TS_ASSERT_LESS_THAN(mesh_pair.rGetElementsAndWeights()[i].ElementNum, fine_mesh.GetNumElements());

            // comment out this test as now some of the weights are negative/greater than one
            //for (unsigned j=0; j<4; j++)
            //{
            //    TS_ASSERT_LESS_THAN(-1e14, mesh_pair.rGetElementsAndWeights()[i].Weights(j));
            //    TS_ASSERT_LESS_THAN(mesh_pair.rGetElementsAndWeights()[i].Weights(j), 1.0+1e-14);
            //}
        }

        /*
         * For each quadrature point that was not found in the fine mesh, check
         * that its x-value is greater than one - this is the only way it could
         * be outside the fine mesh.
         */
        QuadraturePointsGroup<3> quad_point_posns(coarse_mesh, quad_rule);
        for (unsigned i=0; i<mesh_pair.mNotInMesh.size(); i++)
        {
            double x = quad_point_posns.rGet(mesh_pair.mNotInMesh[i])(0);
            TS_ASSERT_LESS_THAN(1.0, x);
        }

        mesh_pair.PrintStatistics();

        TS_ASSERT_EQUALS( Warnings::Instance()->GetNumWarnings(), 1u);
        Warnings::Instance()->QuietDestroy();
    }
Ejemplo n.º 5
0
    void TestReadingMissingAttributes() throw(Exception)
    {
        // The reader immediately reads and caches face data so missing attributes
        // immediately cause an Exception to be thrown
        TS_ASSERT_THROWS_CONTAINS(READER_2D mesh_reader("mesh/test/data/baddata/canonical_triangle_missing_edge_attribute"),"Error in reading attribute");

        // The reader doesn't read node data until GetNextNode() is called
        READER_2D mesh_reader("mesh/test/data/baddata/canonical_triangle_missing_node_attribute");
        TS_ASSERT_EQUALS(mesh_reader.GetNumNodes(), 3u);

        // Read the data for the first node successfully
        mesh_reader.GetNextNode();
        TS_ASSERT_EQUALS(mesh_reader.GetNodeAttributes().size(), 2u);
        TS_ASSERT_DELTA(mesh_reader.GetNodeAttributes()[0], 8.234, 1e-6);
        TS_ASSERT_DELTA(mesh_reader.GetNodeAttributes()[1], 25.4,  1e-6);

        // The second node has a missing attribute
        TS_ASSERT_THROWS_CONTAINS(mesh_reader.GetNextNode(),"Error in reading attribute");
    }
Ejemplo n.º 6
0
    void TestReadingWithGenericReader() throw(Exception)
    {
        std::auto_ptr<AbstractMeshReader<2,2> > p_mesh_reader = GenericMeshReader<2,2>("mesh/test/data/disk_522_elements");
        TS_ASSERT_EQUALS(p_mesh_reader->GetNumNodes(), 312u);
        TS_ASSERT_EQUALS(p_mesh_reader->GetNumElements(), 522u);
        TS_ASSERT_EQUALS(p_mesh_reader->GetNumFaceAttributes(), 1u);
        TS_ASSERT_EQUALS(p_mesh_reader->GetNumElementAttributes(), 0u);

        TS_ASSERT_THROWS_CONTAINS((GenericMeshReader<2,2>("mesh/test/data/no_such_file")),
                                  "Could not open appropriate mesh files for mesh/test/data/no_such_file");
    }
Ejemplo n.º 7
0
    void TestNodeExchange() throw(Exception)
    {
        HeartConfig::Instance()->Reset();

        HeartConfig::Instance()->Reset();
        DistributedTetrahedralMesh<1,1> mesh;
        mesh.ConstructRegularSlabMesh(0.1, 1.0); // [0,1] with h=0.1, ie 11 node mesh

        MyCardiacCellFactory cell_factory;
        cell_factory.SetMesh(&mesh);

        MonodomainTissue<1> monodomain_tissue( &cell_factory, true );


        if ( PetscTools::GetNumProcs() == 1 )
        {
            TS_ASSERT_EQUALS( mesh.GetNumHaloNodes(), 0u );
        }
        else
        {
            if ( PetscTools::AmMaster() || PetscTools::AmTopMost() )
            {
                TS_ASSERT_EQUALS( mesh.GetNumHaloNodes(), 1u );
            }
            else
            {
                TS_ASSERT_EQUALS( mesh.GetNumHaloNodes(), 2u );
            }
        }

        for (DistributedTetrahedralMesh<1,1>::HaloNodeIterator it=mesh.GetHaloNodeIteratorBegin();
                it != mesh.GetHaloNodeIteratorEnd();
                ++it)
        {
            AbstractCardiacCellInterface* cell = monodomain_tissue.GetCardiacCellOrHaloCell( (*it)->GetIndex() );
            TS_ASSERT_DELTA(cell->GetStimulus(0.001),0,1e-10);
        }

        if ( PetscTools::AmMaster() )
        {
            // Master owns node 0
            AbstractCardiacCellInterface* cell = monodomain_tissue.GetCardiacCellOrHaloCell(0);
            TS_ASSERT_DELTA(cell->GetStimulus(0.001), -80.0, 1e-10);
        }
        else
        {
            // Zero is not halo owned by any process (unless we have a lot of them).
            TS_ASSERT_THROWS_CONTAINS(monodomain_tissue.GetCardiacCellOrHaloCell(0),
                                      "Requested node/halo 0 does not belong to processor ");
        }
    }
Ejemplo n.º 8
0
    void TestGenericReader() throw (Exception)
    {
        std::auto_ptr<AbstractMeshReader<3, 3> > p_mesh_reader = GenericMeshReader<3,3>("mesh/test/data/Memfem_slab");

        TS_ASSERT_EQUALS(p_mesh_reader->GetNumNodes(), 381u);
        TS_ASSERT_EQUALS(p_mesh_reader->GetNumElements(), 1030u);
        TS_ASSERT_EQUALS(p_mesh_reader->GetNumFaces(), 758u);
        TS_ASSERT_EQUALS(p_mesh_reader->GetNumElementAttributes(), 0u);
        TS_ASSERT_EQUALS(p_mesh_reader->GetNumFaceAttributes(), 0u);

        // The file does not exist
        TS_ASSERT_THROWS_CONTAINS((GenericMeshReader<3,3>("no_file")),
                                  "Could not open appropriate mesh files for no_file");
    }
    void TestExceptions() throw(Exception)
    {
        std::vector<double> freqs;
        freqs.push_back(4);
        freqs.push_back(7);
        freqs.push_back(20);

        std::vector<std::complex<double> > imps;
        imps.push_back(std::complex<double>(5, 2));
        imps.push_back(std::complex<double>(4, 4));
        imps.push_back(std::complex<double>(3.5, 4.5));

        TS_ASSERT_THROWS_CONTAINS(ImpedancePostProcessor(freqs, imps), "Impedance post processor requires data points at 5 Hz & 20 Hz");
    }
Ejemplo n.º 10
0
    void TestOpenFutureBoostArchive() throw (Exception)
    {

        //Check testout/archive/specific_secondary.arch
        FileFinder archive_dir("global/test/data", RelativeTo::ChasteSourceRoot);
        std::string archive_file = "future_boost.arch";
        // future_boost has got archive version 14 in it
        // 33 => 3
        // 34 => 4
        // 36 => 5
        // 37 => 5
        // 40 => 5
        // 42 => 7
        // 46 => 9
        // 48 => 9
        // 49 => 9
        // 51 => 9
        // 52 => ??
        // 53 => 10
        // 54 => 10
        // 55 => 10
        // 56 => 11
        // 57 => 11
        // 58 => 12
        // 59 => 13

#ifndef BOOST_VERSION
        TS_FAIL("This test needs to know the version of Boost with which it was compiled.");
        return;
#endif
//#if BOOST_VERSION >= 999999
//        InputArchiveOpener archive_opener_in(archive_dir, archive_file, 0);
//        boost::archive::text_iarchive* p_arch = archive_opener_in.GetCommonArchive();
//        boost::archive::text_iarchive* p_process_arch = ProcessSpecificArchive<boost::archive::text_iarchive>::Get();
//
//        const unsigned test_int = 321;
//        unsigned test_int1, test_int2;
//        (*p_arch) & test_int1;
//        (*p_process_arch) & test_int2;
//
//        TS_ASSERT_EQUALS(test_int1, test_int);
//        TS_ASSERT_EQUALS(test_int2, 0u);
//#else
        //Current Boost can't read this archive...
        TS_ASSERT_THROWS_CONTAINS(InputArchiveOpener archive_opener_in(archive_dir, archive_file, 0),
                                  "Could not open Boost archive '");
//#endif
    }
Ejemplo n.º 11
0
    void TestComputeFineElemsAndWeightsForCoarseNodes() throw(Exception)
    {
        TetrahedralMesh<2,2> fine_mesh;
        TrianglesMeshReader<2,2> mesh_reader("mesh/test/data/square_4_elements");
        fine_mesh.ConstructFromMeshReader(mesh_reader);

        QuadraticMesh<2> coarse_mesh(0.5, 0.5, 0.5);
        coarse_mesh.Translate(0.2,0.1);

        FineCoarseMeshPair<2> mesh_pair(fine_mesh,coarse_mesh);

        // Need to call SetUpBoxesOnFineMesh first
        TS_ASSERT_THROWS_CONTAINS(mesh_pair.ComputeFineElementsAndWeightsForCoarseNodes(true), "Call");

        mesh_pair.SetUpBoxesOnFineMesh();
        mesh_pair.ComputeFineElementsAndWeightsForCoarseNodes(true);

        // All coarse quadrature points should have been found in the fine mesh
        TS_ASSERT_EQUALS(mesh_pair.mNotInMesh.size(), 0u);
        TS_ASSERT_EQUALS(mesh_pair.mNotInMeshNearestElementWeights.size(), 0u);

        // Check the elements and weights have been set up correctly
        TS_ASSERT_EQUALS(mesh_pair.rGetElementsAndWeights().size(), 9u);

        // Check the first four nodes against what they should be
        TS_ASSERT_EQUALS(mesh_pair.rGetElementsAndWeights()[0].ElementNum, 1u);
        TS_ASSERT_EQUALS(mesh_pair.rGetElementsAndWeights()[1].ElementNum, 1u);
        TS_ASSERT_EQUALS(mesh_pair.rGetElementsAndWeights()[2].ElementNum, 0u);
        TS_ASSERT_EQUALS(mesh_pair.rGetElementsAndWeights()[3].ElementNum, 2u);

        for (unsigned i=0; i<mesh_pair.rGetElementsAndWeights().size(); i++)
        {
            TS_ASSERT_LESS_THAN(mesh_pair.rGetElementsAndWeights()[i].ElementNum, fine_mesh.GetNumElements());

            // All the weights should be between 0 and 1 as no coarse nodes are
            // Note weights = (1-psi_x-psi_y-psi_z, psi_x, psi_y, psi_z), where psi is the position of the
            // point in that element when transformed to the canonical element
            for (unsigned j=0; j<3; j++)
            {
                TS_ASSERT_LESS_THAN(-1e14, mesh_pair.rGetElementsAndWeights()[i].Weights(j));
                TS_ASSERT_LESS_THAN(mesh_pair.rGetElementsAndWeights()[i].Weights(j), 1.0+1e-14);
            }
        }

        TS_ASSERT_EQUALS(mesh_pair.mStatisticsCounters[0], 9u);
        TS_ASSERT_EQUALS(mesh_pair.mStatisticsCounters[1], 0u);
    }
Ejemplo n.º 12
0
    void TestAcinarImpedance() throw(Exception)
    {
        TetrahedralMesh<1,3> mesh;
        TrianglesMeshReader<1,3> mesh_reader("mesh/test/data/y_branch_3d_mesh");
        mesh.ConstructFromMeshReader(mesh_reader);

        TS_ASSERT_THROWS_CONTAINS(SimpleImpedanceProblem(mesh, 1u), "Outlet node is not a boundary node");

        SimpleImpedanceProblem problem(mesh, 0u);
        problem.rGetMesh(); //for coverage

        unsigned node_index = 3; //Arbitrary terminal node

        problem.SetElastance(2*M_PI/2.0);

        TS_ASSERT_DELTA(real(problem.CalculateAcinusImpedance(mesh.GetNode(node_index), 0.0)), 0.0, 1e-6);
        TS_ASSERT_DELTA(real(problem.CalculateAcinusImpedance(mesh.GetNode(node_index), 1.0)), 0.0, 1e-6);
        TS_ASSERT_DELTA(imag(problem.CalculateAcinusImpedance(mesh.GetNode(node_index), 1.0)), -1.0, 1e-6);
    }
Ejemplo n.º 13
0
    // Solve with a space step of 0.5mm.
    //
    // Note that this space step ought to be too big!
    //
    // NOTE: This test uses NON-PHYSIOLOGICAL parameters values (conductivities,
    // surface-area-to-volume ratio, capacitance, stimulus amplitude). Essentially,
    // the equations have been divided through by the surface-area-to-volume ratio.
    // (Historical reasons...)
    void TestMonodomainFailing()
    {
        if (PetscTools::GetNumProcs() > 3u)
        {
            TS_TRACE("This test is not suitable for more than 3 processes.");
            return;
        }
        HeartConfig::Instance()->SetIntracellularConductivities(Create_c_vector(0.0005));
        HeartConfig::Instance()->SetSimulationDuration(1); //ms
//        HeartConfig::Instance()->SetMeshFileName("mesh/test/data/1D_0_to_1_20_elements");
//        HeartConfig::Instance()->SetSpaceDimension(1);
//        HeartConfig::Instance()->SetFibreLength(1.0, 1.0/20.0);
        HeartConfig::Instance()->SetSpaceDimension(3);
        HeartConfig::Instance()->SetSlabDimensions(0.2, 0.1, 0.1, 0.05);
        HeartConfig::Instance()->SetOutputDirectory("MonoFailing");
        HeartConfig::Instance()->SetOutputFilenamePrefix("MonodomainLR91_SVI");
        HeartConfig::Instance()->SetUseStateVariableInterpolation(true);

        PlaneStimulusCellFactory<CellLuoRudy1991FromCellML, 3> cell_factory;
        MonodomainProblem<3> monodomain_problem(&cell_factory);

        monodomain_problem.Initialise();

        HeartConfig::Instance()->SetSurfaceAreaToVolumeRatio(1.0);
//        HeartConfig::Instance()->SetCapacitance(1.0);

        // the mesh is too coarse, and this simulation will result in cell gating
        // variables going out of range. An exception should be thrown in the
        // EvaluateYDerivatives() method of the cell model


        TS_ASSERT_THROWS_CONTAINS(monodomain_problem.Solve(),
#ifndef NDEBUG
            // VerifyStateVariables is only called when debug is on
            "State variable fast_sodium_current_m_gate__m has gone out of range. "
            "Check numerical parameters, for example time and space stepsizes");
#else
            // This test hits a later assert(!isnan) if we do a ndebug build.
            "Assertion tripped: !std::isnan(i_ionic)");
#endif // NDEBUG
    }
    /**
     * Create a simulation of a NodeBasedCellPopulation to test movement threshold.
     */
    void TestMovementThreshold() throw (Exception)
    {
        EXIT_IF_PARALLEL;   // This test doesn't work in parallel because only one process will throw.

        // Creates nodes and mesh
        std::vector<Node<2>*> nodes;
        nodes.push_back(new Node<2>(0,  false,  0.0, 0.0));
        nodes.push_back(new Node<2>(0,  false,  0.0, 0.3));
        NodesOnlyMesh<2> mesh;
        mesh.ConstructNodesWithoutMesh(nodes, 1.5);

        // Create cells
        std::vector<CellPtr> cells;
        CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator;
        cells_generator.GenerateBasicRandom(cells, mesh.GetNumNodes());

        // Create a node based cell population
        NodeBasedCellPopulation<2> node_based_cell_population(mesh, cells);
        node_based_cell_population.SetAbsoluteMovementThreshold(1e-6);

        // Set up cell-based simulation
        OffLatticeSimulation<2> simulator(node_based_cell_population);
        simulator.SetEndTime(0.1);
        simulator.SetOutputDirectory("TestOffLatticeSimulationWithNodeBasedCellPopulationThreshold");

        // Create a force law and pass it to the simulation
        MAKE_PTR(GeneralisedLinearSpringForce<2>, p_linear_force);
        p_linear_force->SetCutOffLength(1.5);
        simulator.AddForce(p_linear_force);

        // Solve
        TS_ASSERT_THROWS_CONTAINS(simulator.Solve(),
                "which is more than the AbsoluteMovementThreshold:");

        // Avoid memory leak
        delete nodes[0];
        delete nodes[1];
    }
Ejemplo n.º 15
0
    void TestKspExceptionsForCoverage()
    {
        TS_ASSERT_THROWS_NOTHING( KSPEXCEPT(2));

        /*
         * These next few lines are designed to force the coverage test to pass.
         * Some are hard to throw in normal circumstances --
         * "Unknown KSP error code" ought never to be thrown.
         */
        TS_ASSERT_THROWS_CONTAINS( KSPEXCEPT(KSP_DIVERGED_ITS), "DIVERGED_ITS in function \'User provided function\' on line");
        // The next one is deliberately fragile because it contains the line number in this test suite (to check that the line number is output correctly).
        TS_ASSERT_THROWS_THIS( KSPEXCEPT(KSP_DIVERGED_DTOL),  "DIVERGED_DTOL in function \'User provided function\' on line 102 of file ./global/test/TestPetscSetup.hpp");
        TS_ASSERT_THROWS( KSPEXCEPT(KSP_DIVERGED_BREAKDOWN), Exception );
        TS_ASSERT_THROWS( KSPEXCEPT(KSP_DIVERGED_BREAKDOWN_BICG), Exception );
        TS_ASSERT_THROWS( KSPEXCEPT(KSP_DIVERGED_NONSYMMETRIC), Exception );
        TS_ASSERT_THROWS( KSPEXCEPT(KSP_DIVERGED_INDEFINITE_PC), Exception );
        TS_ASSERT_THROWS( KSPEXCEPT(-735827), Exception );


        KSPWARNIFFAILED(KSP_DIVERGED_ITS);
        TS_ASSERT_EQUALS(Warnings::Instance()->GetNumWarnings(), 1u);
        Warnings::QuietDestroy();
    }
Ejemplo n.º 16
0
    void RunTest(const std::string& rOutputDirName,
                 const std::string& rModelName,
                 const std::vector<std::string>& rArgs,
                 bool testLookupTables=false,
                 double tableTestV=-1000)
    {
        // Copy CellML file (and .out if present) into output dir
        OutputFileHandler handler(rOutputDirName, true);
        FileFinder cellml_file("heart/test/data/cellml/" + rModelName + ".cellml", RelativeTo::ChasteSourceRoot);
        handler.CopyFileTo(cellml_file);
        FileFinder out_file("heart/test/data/cellml/" + rModelName + ".out", RelativeTo::ChasteSourceRoot);
        if (out_file.Exists())
        {
            handler.CopyFileTo(out_file);
        }

        // Create options file
        std::vector<std::string> args(rArgs);
//        args.push_back("--profile");
        CellMLToSharedLibraryConverter converter(true);
        if (!args.empty())
        {
            converter.CreateOptionsFile(handler, rModelName, args);
        }

        // Do the conversion
        FileFinder copied_file(rOutputDirName + "/" + rModelName + ".cellml", RelativeTo::ChasteTestOutput);
        DynamicCellModelLoaderPtr p_loader = converter.Convert(copied_file);
        // Apply a stimulus of -40 uA/cm^2 - should work for all models
        boost::shared_ptr<AbstractCardiacCellInterface> p_cell(CreateCellWithStandardStimulus(*p_loader, -40.0));

        // Check that the default stimulus units are correct
        if (p_cell->HasCellMLDefaultStimulus())
        {
            // Record the existing stimulus and re-apply it at the end
            boost::shared_ptr<AbstractStimulusFunction> original_stim = p_cell->GetStimulusFunction();

            // Tell the cell to use the default stimulus and retrieve it
            boost::shared_ptr<RegularStimulus> p_reg_stim = p_cell->UseCellMLDefaultStimulus();

            if (rModelName!="aslanidi_model_2009") // Even before recent changes aslanidi model has stimulus of -400 !
            {
                // Stimulus magnitude should be approximately between -5 and -81 uA/cm^2
                TS_ASSERT_LESS_THAN(p_reg_stim->GetMagnitude(),-5);
                TS_ASSERT_LESS_THAN(-81,p_reg_stim->GetMagnitude());
            }

            // Stimulus duration should be approximately between 0.1 and 5 ms.
            TS_ASSERT_LESS_THAN(p_reg_stim->GetDuration(),6.01);
            TS_ASSERT_LESS_THAN(0.1,p_reg_stim->GetDuration());

            // Stimulus period should be approximately between 70 (for bondarenko - seems fast! - would expect 8-10 beats per second for mouse) and 2000ms.
            TS_ASSERT_LESS_THAN(p_reg_stim->GetPeriod(),2000);
            TS_ASSERT_LESS_THAN(70,p_reg_stim->GetPeriod());

            p_cell->SetIntracellularStimulusFunction(original_stim);
        }

        // Check lookup tables exist if they should
        if (testLookupTables && rModelName != "hodgkin_huxley_squid_axon_model_1952_modified")
        {
            double v = p_cell->GetVoltage();
            p_cell->SetVoltage(tableTestV);
            TS_ASSERT_THROWS_CONTAINS(p_cell->GetIIonic(), "outside lookup table range");
            p_cell->SetVoltage(v);
        }
        Simulate(rOutputDirName, rModelName, p_cell);
    }
Ejemplo n.º 17
0
    void TestSolvePdeAndWriteResultsToFileAndGetPDESolutionAtPointWithoutCoarsePdeMeshDirichlet() throw(Exception)
    {
        EXIT_IF_PARALLEL;

        // Set up SimulationTime
        SimulationTime::Instance()->SetEndTimeAndNumberOfTimeSteps(0.5, 6);

        // Set up mesh
        MutableMesh<2,2> mesh;
        TrianglesMeshReader<2,2> mesh_reader("mesh/test/data/disk_522_elements");
        mesh.ConstructFromMeshReader(mesh_reader);

        // Set up cells
        std::vector<CellPtr> cells;
        CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator;
        cells_generator.GenerateBasic(cells, mesh.GetNumNodes());

        // Set up cell population
        MeshBasedCellPopulation<2> cell_population(mesh, cells);

        // Create a PDE handler object using this cell population
        CellBasedPdeHandler<2> pde_handler(&cell_population);

        // Create a single PDE and pass to the handler
        SimplePdeForTesting pde;
        ConstBoundaryCondition<2> bc(1.0);
        PdeAndBoundaryConditions<2> pde_and_bc(&pde, &bc, false);
        pde_and_bc.SetDependentVariableName("variable");

        // For coverage, provide an initial guess for the solution
        std::vector<double> data(mesh.GetNumNodes());
        for (unsigned i=0; i<mesh.GetNumNodes(); i++)
        {
            data[i] = 1.0;
        }

        Vec vector = PetscTools::CreateVec(data);
        pde_and_bc.SetSolution(vector);

        pde_handler.AddPdeAndBc(&pde_and_bc);

        // Open result file ourselves
        OutputFileHandler output_file_handler("TestWritePdeSolution", false);
        pde_handler.mpVizPdeSolutionResultsFile = output_file_handler.OpenOutputFile("results.vizpdesolution");

        // Solve PDE (set sampling timestep multiple to be large doesn't do anything as always output on 1st timestep)
        pde_handler.SolvePdeAndWriteResultsToFile(10);

        // Close result file ourselves
        pde_handler.mpVizPdeSolutionResultsFile->close();

        // Test that this is correct by comparing with an existing results file
        std::string results_dir = output_file_handler.GetOutputDirectoryFullPath();

        NumericFileComparison comparison(results_dir + "results.vizpdesolution", "cell_based/test/data/TestCellBasedPdeHandler/results.vizpdesolution");
        TS_ASSERT(comparison.CompareFiles());

        // Check the correct solution was obtained
        for (AbstractCellPopulation<2>::Iterator cell_iter = cell_population.Begin();
             cell_iter != cell_population.End();
             ++cell_iter)
        {
            double radius = norm_2(cell_population.GetLocationOfCellCentre(*cell_iter));
            double analytic_solution = 1.0 - 0.25*(1 - pow(radius,2.0));

            // Test that PDE solver is working correctly
            TS_ASSERT_DELTA(cell_iter->GetCellData()->GetItem("variable"), analytic_solution, 0.02);
        }

        // Now check the GetPdeSolutionAtPoint method

        // First loop over nodes and check it works
        // Check the correct solution was obtained
        for (AbstractCellPopulation<2>::Iterator cell_iter = cell_population.Begin();
             cell_iter != cell_population.End();
             ++cell_iter)
        {
            double cell_data_solution(cell_iter->GetCellData()->GetItem("variable"));
            c_vector<double,2> cell_location = cell_population.GetLocationOfCellCentre(*cell_iter);

            TS_ASSERT_DELTA(pde_handler.GetPdeSolutionAtPoint(cell_location,"variable"), cell_data_solution, 1e-6);
        }

        // Now choose some other points

        // Centre
        c_vector<double,2> point;
        point(0) = 0.0;
        point(1) = 0.0;

        TS_ASSERT_DELTA(pde_handler.GetPdeSolutionAtPoint(point,"variable"), 0.75, 0.01);

        // Cover exception
        TS_ASSERT_THROWS_CONTAINS(pde_handler.GetPdeSolutionAtPoint(point, "not_a_var"),
                                  "There is no PDE with that variable.");

        // Random point
        point(0) = 0.5;
        point(1) = 0.5;

        TS_ASSERT_DELTA(pde_handler.GetPdeSolutionAtPoint(point,"variable"), 1.0 - (1.0-2.0*0.5*0.5)/4.0, 0.01);

        // Point on the boundary
        point(0) = 1.0;
        point(1) = 0.0;

        TS_ASSERT_DELTA(pde_handler.GetPdeSolutionAtPoint(point,"variable"), 1.0, 1e-6);
    }
    // These tests are older than the above tests..
    void TestImplicitNhs2dOneMechanicsElement() throw(Exception)
    {
        PlaneStimulusCellFactory<CellLuoRudy1991FromCellML, 2> cell_factory(-1000*1000);

        HeartConfig::Instance()->SetSimulationDuration(10.0);

        CardiacElectroMechProbRegularGeom<2> problem(INCOMPRESSIBLE,
                                                     0.05, /* width (cm) */
                                                     1,    /* mech mesh size*/
                                                     5,    /* elec elem each dir */
                                                     &cell_factory,
                                                     NHS,
                                                     1.0,  /* mechanics solve timestep */
                                                     0.01, /* contraction model ode timestep */
                                                     "TestCardiacElectroMechOneElement");
        c_vector<double,2> pos;
        pos(0) = 0.05;
        pos(1) = 0.0;

        problem.SetWatchedPosition(pos);



        TS_ASSERT_THROWS_CONTAINS(problem.SetOutputDeformationGradientsAndStress(3.4),"not a multiple");
        problem.SetOutputDeformationGradientsAndStress(3.0);

        problem.Solve();

        // test by checking the length of the tissue against hardcoded value
        std::vector<c_vector<double,2> >& r_deformed_position = problem.rGetDeformedPosition();
        TS_ASSERT_DELTA(r_deformed_position[1](0), 0.0497, 1e-4);

        OutputFileHandler handler("TestCardiacElectroMechOneElement",false);

        NumericFileComparison comparer(handler.GetOutputDirectoryFullPath() + "watched.txt","heart/test/data/good_watched.txt");
        TS_ASSERT(comparer.CompareFiles(1e-2));

        FileFinder electrics_dir = handler.FindFile("electrics");
        TS_ASSERT(electrics_dir.IsDir());


        // check electrics output was written
        TS_ASSERT(handler.FindFile("deformation/deformation_gradient_0.strain").Exists());
        TS_ASSERT(handler.FindFile("deformation/deformation_gradient_3.strain").Exists());
        TS_ASSERT(handler.FindFile("deformation/deformation_gradient_6.strain").Exists());
        TS_ASSERT(handler.FindFile("deformation/second_PK_0.stress").Exists());
        TS_ASSERT(handler.FindFile("deformation/second_PK_3.stress").Exists());
        TS_ASSERT(handler.FindFile("deformation/second_PK_6.stress").Exists());



        // coverage

        HeartConfig::Instance()->SetSimulationDuration(10.0); // has to be reset after a solve, it seems..

        // We can now #2370 put any model anywhere, so these checks don't make sense...
//        CardiacElectroMechProbRegularGeom<2> prob_with_bad_model(INCOMPRESSIBLE,0.05,1,5,&cell_factory,NONPHYSIOL1,1,0.01,"");
//        TS_ASSERT_THROWS_CONTAINS(prob_with_bad_model.Solve(),"Invalid contraction model");
//
//        CardiacElectroMechProbRegularGeom<2> prob_with_bad_model_comp(COMPRESSIBLE,0.05,1,5,&cell_factory,NONPHYSIOL1,1,0.01,"");
//        TS_ASSERT_THROWS_CONTAINS(prob_with_bad_model_comp.Solve(),"Invalid contraction model");

        CardiacElectroMechProbRegularGeom<2> prob_with_bad_timesteps(INCOMPRESSIBLE,0.05,1,5,&cell_factory,NHS,0.025,0.01,"");
        TS_ASSERT_THROWS_CONTAINS(prob_with_bad_timesteps.Initialise(),"does not divide");


        MechanicsEventHandler::Headings();
        MechanicsEventHandler::Report();
    }
Ejemplo n.º 19
0
    void TestHandler() throw(Exception)
    {
        // Test that CHASTE_TEST_OUTPUT always has a trailing slash even before
        // a class object is instantiated
        const std::string chaste_test_output(OutputFileHandler::GetChasteTestOutputDirectory());
        TS_ASSERT_EQUALS( *(chaste_test_output.end()-1), '/');

        // Make a handler that points straight to the CHASTE_TEST_OUTPUT directory.
        OutputFileHandler handler("");
        const std::string handler_path(handler.GetOutputDirectoryFullPath());
        TS_ASSERT(handler_path.length() > 0);
        TS_ASSERT_EQUALS(handler_path, handler.GetChasteTestOutputDirectory());
        TS_ASSERT_EQUALS(handler.GetRelativePath(), "");

        // Test that CHASTE_TEST_OUTPUT always has a trailing slash
        TS_ASSERT_EQUALS( *(handler_path.end()-1), '/');

        // Make a handler that points to a sub-directory.
        std::string dir = "testhandler";
        OutputFileHandler handler2(dir);
        std::string full_dir = handler2.GetOutputDirectoryFullPath();
        TS_ASSERT_EQUALS(full_dir.substr(full_dir.length()-dir.length()-1), dir+"/");
        TS_ASSERT_EQUALS(full_dir.substr(0, full_dir.length()-dir.length()-1), handler_path);
        TS_ASSERT_EQUALS(handler2.GetRelativePath(), dir);

        // We can also create handlers from a FileFinder (provided it points to a location in CHASTE_TEST_OUTPUT)
        OutputFileHandler handler3(handler.FindFile("testhandler2"));
        full_dir = handler3.GetOutputDirectoryFullPath();
        TS_ASSERT_EQUALS(full_dir.substr(full_dir.length()-dir.length()-2), dir+"2/");
        TS_ASSERT_EQUALS(full_dir.substr(0, full_dir.length()-dir.length()-2), handler_path);
        TS_ASSERT_EQUALS(handler3.GetRelativePath(), "testhandler2");

        // Check that all three handlers can create files
        out_stream p_file_stream;
        p_file_stream = handler.OpenOutputFile("test_file", std::ios::out);
        TS_ASSERT(FileFinder(handler_path + "test_file").Exists());

        p_file_stream = handler.OpenOutputFile("test_file2");
        TS_ASSERT(FileFinder(handler_path + "test_file2").Exists());

        p_file_stream = handler2.OpenOutputFile("test_file");
        TS_ASSERT(FileFinder(handler2.GetOutputDirectoryFullPath() + "test_file").Exists());

        p_file_stream = handler2.OpenOutputFile("test_", 34, ".txt");
        TS_ASSERT(FileFinder(handler2.GetOutputDirectoryFullPath() + "test_34.txt").Exists());

        p_file_stream = handler3.OpenOutputFile("test_file");
        TS_ASSERT(FileFinder(handler3.GetOutputDirectoryFullPath() + "test_file").Exists());

        // This should try to write files to /, which isn't allowed (we hope!)
        TS_ASSERT_THROWS_CONTAINS(OutputFileHandler bad_handler("../../../../../../../../../../../../../../../", false),
                                  "due to it potentially being above, and cleaning, CHASTE_TEST_OUTPUT.");
        TS_ASSERT_THROWS_CONTAINS(OutputFileHandler bad_handler("/", false),
                                  "The constructor argument to OutputFileHandler must be a relative path");
        TS_ASSERT_THROWS_CONTAINS(OutputFileHandler bad_handler(FileFinder("/"), false),
                                  "The location provided to OutputFileHandler must be inside CHASTE_TEST_OUTPUT");

        // Check the CopyFileTo method
        FileFinder source_file("global/test/TestOutputFileHandler.hpp", RelativeTo::ChasteSourceRoot);
        TS_ASSERT(!handler2.FindFile("TestOutputFileHandler.hpp").Exists());
        PetscTools::Barrier("TestOutputFileHandler-0");
        FileFinder dest_file = handler2.CopyFileTo(source_file);
        TS_ASSERT(dest_file.Exists());
        FileFinder missing_file("global/no_file", RelativeTo::ChasteSourceRoot);
        TS_ASSERT_THROWS_CONTAINS(handler2.CopyFileTo(missing_file), "Can only copy single files");
        FileFinder global_dir("global", RelativeTo::ChasteSourceRoot);
        TS_ASSERT_THROWS_CONTAINS(handler2.CopyFileTo(global_dir), "Can only copy single files");

        // We don't want other people using CHASTE_TEST_OUTPUT whilst we are messing with it!
        PetscTools::Barrier("TestOutputFileHandler-1");

        // Test that the environment variable actually influences the location of files
        {
            setenv("CHASTE_TEST_OUTPUT", "", 1/*Overwrite*/);
            // Check this folder is not present
            FileFinder test_folder("testoutput/whatever", RelativeTo::ChasteSourceRoot);
            TS_ASSERT(!test_folder.Exists());

            PetscTools::Barrier("TestOutputFileHandler-2");

            // Make a folder and erase it - NB only master can erase files and check it is successful!
            OutputFileHandler handler4("whatever");
            TS_ASSERT(test_folder.Exists());
            PetscTools::Barrier("TestOutputFileHandler-2b");
            if (PetscTools::AmMaster())
            {
                test_folder.Remove();
                // If we've not written anything else to the testoutput folder, remove that too
                // rather than leaving an empty folder lieing around in the source tree!
                FileFinder output_root("", RelativeTo::ChasteTestOutput);
                if (output_root.IsEmpty())
                {
                    output_root.DangerousRemove();
                }
            }
            PetscTools::Barrier("TestOutputFileHandler-2c");
        }

        {
            setenv("CHASTE_TEST_OUTPUT", "config__cyborg__T800__cooper", 1/*Overwrite*/);
            // Test that CHASTE_TEST_OUTPUT always has a trailing slash even before
            // a class object is instantiated and when the directory does not exist
            const std::string nonexistent_test_path(OutputFileHandler::GetChasteTestOutputDirectory());
            TS_ASSERT_EQUALS( *(nonexistent_test_path.end()-1), '/');
        }

        {
            // Check this folder is not present
            std::string test_folder("somewhere_without_trailing_forward_slash");
            TS_ASSERT(!FileFinder(test_folder, RelativeTo::CWD).Exists());
            PetscTools::Barrier("TestOutputFileHandler-3");

            setenv("CHASTE_TEST_OUTPUT", test_folder.c_str(), 1/*Overwrite*/);

            // Make a folder using a FileFinder, for coverage of the case where the root output folder doesn't exist
            FileFinder sub_folder("test_folder", RelativeTo::ChasteTestOutput);
            TS_ASSERT(!sub_folder.Exists());
            PetscTools::Barrier("TestOutputFileHandler-3a");
            OutputFileHandler creating_handler(sub_folder);
            TS_ASSERT(sub_folder.Exists());

            // Make a folder
            OutputFileHandler handler5("whatever");
            TS_ASSERT(FileFinder(test_folder, RelativeTo::CWD).Exists());
            PetscTools::Barrier("TestOutputFileHandler-3b");

            // Erase it
            if (PetscTools::AmMaster())
            {
                FileFinder(test_folder).DangerousRemove();
            }
        }

        // Reset the location of CHASTE_TEST_OUTPUT
        setenv("CHASTE_TEST_OUTPUT", chaste_test_output.c_str(), 1/*Overwrite*/);

        // We don't want other people using CHASTE_TEST_OUTPUT while we are messing with it!
        PetscTools::Barrier("TestOutputFileHandler-4");

        // Coverage of the case where we can't open a file for writing
        OutputFileHandler handler6("no_write_access");
        if (PetscTools::AmMaster())
        {
            std::string dir_path =  handler6.GetOutputDirectoryFullPath();
#ifndef _MSC_VER
            // This test can never pass on modern Windows OS! See: http://support.microsoft.com/kb/326549
            // You can't change DIRECTORY attributes
            chmod(dir_path.c_str(), CHASTE_READONLY);
            TS_ASSERT_THROWS_CONTAINS(p_file_stream = handler6.OpenOutputFile("test_file"),
                                      "Could not open file");
#endif
            chmod(dir_path.c_str(), CHASTE_READ_WRITE_EXECUTE);
            fs::remove(dir_path + ".chaste_deletable_folder");
            fs::remove(dir_path);
        }

        // Check behaviour of FindFile("")
        FileFinder handler_self = handler.FindFile("");
        TS_ASSERT_EQUALS(handler_self.GetAbsolutePath(), handler.GetOutputDirectoryFullPath());
    }
Ejemplo n.º 20
0
    void TestWeCanOnlyDeleteFoldersWeHaveMadeOurselves() throw(Exception, std::exception)
    {
        std::string test_folder = "cannot_delete_me";
        if (PetscTools::AmMaster())
        {
            ABORT_IF_THROWS(fs::create_directories(OutputFileHandler::GetChasteTestOutputDirectory() + test_folder));
        }
        // Wait until directory has been created, and check it exists
        PetscTools::Barrier("TestWeCanOnlyDeleteFoldersWeHaveMadeOurselves-1");
        FileFinder cannot_delete(test_folder, RelativeTo::ChasteTestOutput);
        TS_ASSERT(cannot_delete.IsDir());

        // Try to use it as an output folder
        TS_ASSERT_THROWS_CONTAINS(OutputFileHandler bad_handler(test_folder),
                                  "because signature file \".chaste_deletable_folder\" is not present");

        // Tidy up
        if (PetscTools::AmMaster())
        {
            TS_ASSERT(cannot_delete.Exists());
            cannot_delete.DangerousRemove();
            TS_ASSERT(!cannot_delete.Exists());
        }

        // Now create a folder the proper way
        test_folder = "can_delete_me";
        OutputFileHandler handler(test_folder);
        out_stream p_file_stream = handler.OpenOutputFile("test_file");
        p_file_stream->close(); // Windows does not like deleting open files

        // Test file is present
        FileFinder test_file = handler.FindFile("test_file");
        TS_ASSERT(test_file.Exists());
        PetscTools::Barrier("TestWeCanOnlyDeleteFoldersWeHaveMadeOurselves-2");

        OutputFileHandler handler2(test_folder, false /* don't clean */);

        // Test file is still present
        TS_ASSERT(test_file.Exists());
        PetscTools::Barrier("TestWeCanOnlyDeleteFoldersWeHaveMadeOurselves-3");

        OutputFileHandler handler3(test_folder, true /* do clean */);

        // Test file is deleted
        TS_ASSERT(!test_file.Exists());
        PetscTools::Barrier("TestWeCanOnlyDeleteFoldersWeHaveMadeOurselves-4");

        // Check we can delete the test_folder too
        if (PetscTools::AmMaster())
        {
            FileFinder folder = handler.FindFile("");
            TS_ASSERT(folder.Exists());
            folder.Remove();
            TS_ASSERT(!folder.Exists());
        }

        // Test we can make a directory of folders and delete them all
        OutputFileHandler handler4("what_about_me/and_me/and_me/and_da_da_da", true);

        // Check we have made a subdirectory
        FileFinder sub_folder("what_about_me/and_me", RelativeTo::ChasteTestOutput);
        TS_ASSERT(sub_folder.IsDir());
        PetscTools::Barrier("TestWeCanOnlyDeleteFoldersWeHaveMadeOurselves-5");

        OutputFileHandler handler5("what_about_me", true);

        // Check we have wiped the sub-directories
        TS_ASSERT(!sub_folder.Exists());
        PetscTools::Barrier("TestWeCanOnlyDeleteFoldersWeHaveMadeOurselves-6");

        // Check we can delete the main directory too
        if (PetscTools::AmMaster())
        {
            FileFinder folder = handler5.FindFile("");
            TS_ASSERT(folder.Exists());
            folder.Remove();
            TS_ASSERT(!folder.Exists());
        }
    }
    void TestPottsBasedWithCoarseMeshTwoEquations() throw(Exception)
    {
        EXIT_IF_PARALLEL;

        // Create a simple 2D PottsMesh
        PottsMeshGenerator<2> generator(6, 2, 2, 6, 2, 2);
        PottsMesh<2>* p_mesh = generator.GetMesh();

        // Create cells
        std::vector<CellPtr> cells;
        MAKE_PTR(DifferentiatedCellProliferativeType, p_diff_type);
        CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator;
        cells_generator.GenerateBasicRandom(cells, p_mesh->GetNumElements(), p_diff_type);

        // Create cell population
        PottsBasedCellPopulation<2> cell_population(*p_mesh, cells);

        // Set up cell-based simulation
        OnLatticeSimulation<2> simulator(cell_population);
        simulator.SetOutputDirectory("TestPottsBasedCellPopulationWithTwoPdes");
        simulator.SetEndTime(0.1);

        // Set up PDE and pass to simulation via handler (zero uptake to check analytic solution)
        AveragedSourcePde<2> pde_1(cell_population, 0.0);
        ConstBoundaryCondition<2> bc_1(1.0);
        PdeAndBoundaryConditions<2> pde_and_bc_1(&pde_1, &bc_1, false);
        pde_and_bc_1.SetDependentVariableName("quantity 1");

        AveragedSourcePde<2> pde_2(cell_population, 0.0);
        ConstBoundaryCondition<2> bc_2(1.0);
        PdeAndBoundaryConditions<2> pde_and_bc_2(&pde_2, &bc_2, false);
        pde_and_bc_2.SetDependentVariableName("quantity 2");

        CellBasedPdeHandler<2> pde_handler(&cell_population);
        pde_handler.AddPdeAndBc(&pde_and_bc_1);
        pde_handler.AddPdeAndBc(&pde_and_bc_2);
        ChastePoint<2> lower(0.0, 0.0);
        ChastePoint<2> upper(50.0, 50.0);
        ChasteCuboid<2> cuboid(lower, upper);
        pde_handler.UseCoarsePdeMesh(10.0, cuboid, true);
        pde_handler.SetImposeBcsOnCoarseBoundary(true);

        simulator.SetCellBasedPdeHandler(&pde_handler);

        // Create update rules and pass to the simulation
        MAKE_PTR(VolumeConstraintPottsUpdateRule<2>, p_volume_constraint_update_rule);
        simulator.AddPottsUpdateRule(p_volume_constraint_update_rule);
        MAKE_PTR(AdhesionPottsUpdateRule<2>, p_adhesion_update_rule);
        simulator.AddPottsUpdateRule(p_adhesion_update_rule);

        // Solve the system
        simulator.Solve();

        // Test solution is constant
        for (AbstractCellPopulation<2>::Iterator cell_iter = cell_population.Begin();
             cell_iter != cell_population.End();
             ++cell_iter)
        {
            double analytic_solution = 1.0;

            // Test that PDE solver is working correctly on both pdes
            TS_ASSERT_DELTA(cell_iter->GetCellData()->GetItem("quantity 1"), analytic_solution, 1e-2);
            TS_ASSERT_DELTA(cell_iter->GetCellData()->GetItem("quantity 2"), analytic_solution, 1e-2);
        }
#ifdef CHASTE_VTK
        //First file exists
        FileFinder vtk_file("TestPottsBasedCellPopulationWithTwoPdes/results_from_time_0/pde_results_1.vtu", RelativeTo::ChasteTestOutput);
        TS_ASSERT(vtk_file.Exists());
        // Check that the second VTK file for the solution has the dependent quantities
        OutputFileHandler handler("TestPottsBasedCellPopulationWithTwoPdes", false);
        VtkMeshReader<3,3> vtk_reader(handler.GetOutputDirectoryFullPath()+"results_from_time_0/pde_results_2.vtu");
        std::vector<double> data1;
        //There is no Oxygen
        TS_ASSERT_THROWS_CONTAINS(vtk_reader.GetPointData("Oxygen", data1), "No point data");
        TS_ASSERT(data1.empty());
        vtk_reader.GetPointData("quantity 1", data1);
        TS_ASSERT_EQUALS(data1.size(), 6u*6u);
        std::vector<double> data2;
        vtk_reader.GetPointData("quantity 2", data2);
        TS_ASSERT_EQUALS(data1.size(), data2.size());
#endif //CHASTE_VTK
    }
    void TestArchiving() throw(Exception)
    {
        OutputFileHandler archive_dir_("mixed_mesh_archive"); // Clear folder
        FileFinder main_archive_dir("mixed_mesh_archive", RelativeTo::ChasteTestOutput);
        std::string archive_file = "mixed_dimension_mesh.arch";
        ArchiveLocationInfo::SetMeshFilename("mixed_dimension_mesh");

        MixedDimensionMesh<2,2>* p_mesh = new MixedDimensionMesh<2,2>(DistributedTetrahedralMeshPartitionType::DUMB);
        unsigned num_nodes;
        unsigned local_num_nodes;
        unsigned num_elements;
        unsigned num_cable_elements;
        unsigned num_local_cable_elements;
        // archive
        {
            TrianglesMeshReader<2,2> mesh_reader("mesh/test/data/mixed_dimension_meshes/2D_0_to_1mm_200_elements");

            p_mesh->ConstructFromMeshReader(mesh_reader);
            num_nodes = p_mesh->GetNumNodes();
            local_num_nodes = p_mesh->GetNumLocalNodes();
            num_elements = p_mesh->GetNumElements();
            num_cable_elements = p_mesh->GetNumCableElements();
            num_local_cable_elements = p_mesh->GetNumLocalCableElements();

            ArchiveOpener<boost::archive::text_oarchive, std::ofstream> arch_opener(main_archive_dir, archive_file);
            boost::archive::text_oarchive* p_arch = arch_opener.GetCommonArchive();

            AbstractTetrahedralMesh<2,2>* const p_mesh_abstract = static_cast<AbstractTetrahedralMesh<2,2>* >(p_mesh);
            (*p_arch) << p_mesh_abstract;
        }

        FileFinder ncl_file("mixed_dimension_mesh.ncl", main_archive_dir);
        TS_ASSERT(ncl_file.Exists());

        // restore
        {
            // Should archive the most abstract class you can to check boost knows what individual classes are.
            // (but here AbstractMesh doesn't have the methods below).
            AbstractTetrahedralMesh<2,2>* p_mesh_abstract2;

            // Create an input archive
            ArchiveOpener<boost::archive::text_iarchive, std::ifstream> arch_opener(main_archive_dir, archive_file);
            boost::archive::text_iarchive* p_arch = arch_opener.GetCommonArchive();

            // restore from the archive
            (*p_arch) >> p_mesh_abstract2;
            // Check we have the right number of nodes & elements
            MixedDimensionMesh<2,2>* p_mesh2 = static_cast<MixedDimensionMesh<2,2>*>(p_mesh_abstract2);

            TS_ASSERT_EQUALS(p_mesh2->GetNumNodes(), num_nodes);
            TS_ASSERT_EQUALS(p_mesh2->GetNumLocalNodes(), local_num_nodes);
            TS_ASSERT_EQUALS(p_mesh2->GetNumElements(), num_elements);
            TS_ASSERT_EQUALS(p_mesh2->GetNumCableElements(), num_cable_elements);
            TS_ASSERT_EQUALS(p_mesh2->GetNumLocalCableElements(), num_local_cable_elements);

            // Check elements have the right nodes
            for (unsigned i=0; i<num_cable_elements; i++)
            {
                try
                {
                    Element<1,2>* p_element = p_mesh->GetCableElement(i);
                    Element<1,2>* p_element2 = p_mesh2->GetCableElement(i);
                    TS_ASSERT_EQUALS(p_element->GetNodeGlobalIndex(0), p_element2->GetNodeGlobalIndex(0));
                }
                catch(Exception& e)
                {
                    TS_ASSERT_DIFFERS((int)e.GetShortMessage().find("does not belong to processor"),-1);
                }
            }
            delete p_mesh2;
        }

        // restore from a single processor archive
        {
            FileFinder archive_dir("mesh/test/data/mixed_mesh_archive", RelativeTo::ChasteSourceRoot);
            if ( PetscTools::IsSequential() )
            {
                ArchiveOpener<boost::archive::text_iarchive, std::ifstream> arch_opener(archive_dir, archive_file);
                boost::archive::text_iarchive* p_arch = arch_opener.GetCommonArchive();
                AbstractTetrahedralMesh<2,2>* p_mesh_abstract3 = NULL;
                (*p_arch) >> p_mesh_abstract3;

                //Double check that the cables are intact
                MixedDimensionMesh<2,2>* p_mesh3 = static_cast<MixedDimensionMesh<2,2>*>(p_mesh_abstract3);
                Element<1,2>* p_element = p_mesh3->GetCableElement(9);
                TS_ASSERT_EQUALS(p_element->GetNodeGlobalIndex(0), 64u);
                TS_ASSERT_EQUALS(p_element->GetNodeGlobalIndex(1), 65u);
                TS_ASSERT_DELTA(p_element->GetAttribute(), 10.5, 1e-8);

                delete p_mesh_abstract3;
            }
            else
            {
                typedef ArchiveOpener<boost::archive::text_iarchive, std::ifstream> InputArchiveOpener;
                if (PetscTools::GetMyRank() > 0)
                {
                    // Should not read this archive because none exists here.
                    TS_ASSERT_THROWS_CONTAINS(InputArchiveOpener arch_opener(archive_dir, archive_file),
                                              "Cannot load secondary archive file:");
                }
                else
                {
                    // Should not read this archive because there are two or more processes and
                    // this archive was written on one process.
                    InputArchiveOpener arch_opener(archive_dir, archive_file);
                    boost::archive::text_iarchive* p_arch = arch_opener.GetCommonArchive();
                    AbstractTetrahedralMesh<2,2>* p_mesh3 = NULL;
                    TS_ASSERT_THROWS_THIS((*p_arch) >> p_mesh3,
                                          "This archive was written for a different number of processors");

                }
            }
        }
Ejemplo n.º 23
0
    void TestColemanDynamicVentilationThreeBifurcations() throw(Exception)
    {
        FileFinder mesh_finder("lung/test/data/three_bifurcations", RelativeTo::ChasteSourceRoot);

        //The three bifurcation mesh defines a fully symmetric three bifurcation airway tree.
        //The composite ventilation problem is then equivalent to a trumpet problem connected
        //to an acinus with compliance equal to the total compliance of all the acini.
        double total_compliance = 0.1/98.0665/1e3;  //in m^3 / pa. Converted from 0.1 L/cmH2O per lung to four acinar compartments
        double acinar_compliance = total_compliance/4.0;

        SimpleAcinarUnitFactory factory(acinar_compliance, 2400.0);
        TS_ASSERT_THROWS_CONTAINS(factory.GetMesh(), "The mesh object has not been set in the acinar unit factory");

        double viscosity = 1.92e-5;               //Pa s
        double terminal_airway_radius = 0.00005;   //m
        double resistance_per_unit_length = 8*viscosity/(M_PI*SmallPow(terminal_airway_radius, 4));
        //All airways in the mesh have radius 0.05 mm. The first branch is 3mm long, the others are 5mm.
        double total_airway_resistance = (0.003 + 0.005/2 + 0.005/4)*resistance_per_unit_length;

        double ode_volume = 0.0;

        //Setup a simulation iterating between the flow solver and the acinar balloon.
        DynamicVentilationProblem problem(&factory, mesh_finder.GetAbsolutePath(), 0u);
        problem.rGetMatrixVentilationProblem().SetOutflowPressure(0.0);
        problem.rGetMatrixVentilationProblem().SetMeshInMilliMetres();
        problem.SetTimeStep(0.01);
        factory.GetNumberOfAcini();

        TimeStepper time_stepper(0.0, 1.0, 0.01);

        while (!time_stepper.IsTimeAtEnd())
        {
            //Solve corresponding backward Euler problem for testing
            double pleural_pressure =  factory.GetPleuralPressureForNode(time_stepper.GetNextTime(), NULL);

            double dt = time_stepper.GetNextTimeStep();
            ode_volume = (ode_volume - dt*pleural_pressure/total_airway_resistance)/(1 + dt/(total_airway_resistance*total_compliance));

            //Solve using DynamicVentilationProblem
            problem.SetEndTime(time_stepper.GetNextTime());
            problem.Solve();

            std::map<unsigned, AbstractAcinarUnit*>& r_acinar_map = problem.rGetAcinarUnitMap();
            TS_ASSERT_DELTA(ode_volume, r_acinar_map[5]->GetVolume(), 1e-6);

            time_stepper.AdvanceOneTimeStep();
        }

        //Solve for longer and write output to VTK
        problem.SetSamplingTimeStepMultiple(10u);
        problem.SetOutputDirectory("TestDynamicVentilation");
        problem.SetOutputFilenamePrefix("three_bifurcations");
        problem.SetWriteVtkOutput();
        problem.SetEndTime(1.5);
        problem.Solve();

#ifdef CHASTE_VTK
        std::string filepath = OutputFileHandler::GetChasteTestOutputDirectory() + "TestDynamicVentilation/";
        std::string basename = filepath + "three_bifurcations";
        FileFinder vtu_file(basename + ".vtu", RelativeTo::Absolute);
        TS_ASSERT(vtu_file.Exists());
#endif
    }
    void TestInterpolatorTimesAndGenerateReferenceTrace() throw(Exception)
    {
#ifdef CHASTE_CVODE
        OutputFileHandler handler("CvodeCellsWithDataClamp");

        boost::shared_ptr<AbstractIvpOdeSolver> p_empty_solver;
        boost::shared_ptr<AbstractStimulusFunction> p_empty_stimulus;

        // N.B. Because we use the Shannon model as a lot of examples,
        // here it is actually a Shannon->WithModifiers->WithDataClamp->CvodeCell
        // (the WithModifiers doesn't need to be there to use the data clamp!)
        mpModel.reset(new CellShannon2004FromCellMLCvodeDataClamp(p_empty_solver,p_empty_stimulus));

        TS_ASSERT_EQUALS(mpModel->HasParameter("membrane_data_clamp_current_conductance"), true);

        mpModel->SetMaxSteps(5000);
        mpModel->UseCellMLDefaultStimulus();

        // Run a simulation without clamping switched on

        Timer::Reset();
        double end_time = 400.0;
        OdeSolution solution = mpModel->Compute(0, end_time, 0.2);
        Timer::Print("OdeSolution");
        std::vector<double> expt_times = solution.rGetTimes();
        std::vector<double> expt_data = solution.GetAnyVariable("membrane_voltage");
        solution.WriteToFile("CvodeCellsWithDataClamp","shannon_original_no_clamp", "ms", 1, false); // false to clean

        TS_ASSERT_THROWS_THIS(mpModel->TurnOnDataClamp(),
            "Before calling TurnOnDataClamp(), please provide experimental data via the SetExperimentalData() method.");

        // Test the interpolation methods.
        {
            mpModel->SetExperimentalData(expt_times, expt_data);

            // Note - unless the data clamp is switched on the below method just returns DOUBLE_UNSET to save time interpolating.
            double time = 100.0;
            TS_ASSERT_EQUALS(mpModel->GetExperimentalVoltageAtTimeT(time), DOUBLE_UNSET);

            // So now turn on the data clamp
            mpModel->TurnOnDataClamp();

# if CHASTE_SUNDIALS_VERSION >= 20400
            double tol = 5e-3; // mV
#else
            double tol = 0.2; // mV
#endif
            TS_ASSERT_DELTA(mpModel->GetExperimentalVoltageAtTimeT(time), -8.55863245e+01, tol);

            // So turn it off again
            mpModel->TurnOffDataClamp();
            TS_ASSERT_DELTA(mpModel->GetParameter("membrane_data_clamp_current_conductance"), 0.0, 1e-12);
            mpModel->TurnOnDataClamp(200.0);
            TS_ASSERT_DELTA(mpModel->GetParameter("membrane_data_clamp_current_conductance"), 200.0, 1e-12);
            mpModel->TurnOffDataClamp();
            TS_ASSERT_DELTA(mpModel->GetParameter("membrane_data_clamp_current_conductance"), 0.0, 1e-12);
            mpModel->TurnOnDataClamp();
            TS_ASSERT_DELTA(mpModel->GetParameter("membrane_data_clamp_current_conductance"), 100.0, 1e-12); // the default

            // Test a couple of times where no interpolation is needed (on data points).
            time = 116.0;
            double v_at_116 = 1.53670634e+01;
            TS_ASSERT_DELTA(mpModel->GetExperimentalVoltageAtTimeT(time), v_at_116, tol);

            time = 116.2;
            double v_at_116_2 = 1.50089546e+01;
            TS_ASSERT_DELTA(mpModel->GetExperimentalVoltageAtTimeT(time), v_at_116_2, tol);

            // Now test a time where interpolation is required.
            time = 116.1;
            TS_ASSERT_DELTA(mpModel->GetExperimentalVoltageAtTimeT(time), 0.5*(v_at_116 + v_at_116_2), tol);

            // Test ends
            TS_ASSERT_DELTA(mpModel->GetExperimentalVoltageAtTimeT(0.0), expt_data[0], 1e-4);
            TS_ASSERT_DELTA(mpModel->GetExperimentalVoltageAtTimeT(end_time), expt_data.back(), 1e-4);

            // Test exceptions
            TS_ASSERT_THROWS_CONTAINS(mpModel->GetExperimentalVoltageAtTimeT(-1e-12),
                                      "is outside the times stored in the data clamp");
            TS_ASSERT_THROWS_CONTAINS(mpModel->GetExperimentalVoltageAtTimeT(end_time+1e-12),
                                      "is outside the times stored in the data clamp");

            //std::cout << "membrane_data_clamp_current_conductance = " << mpModel->GetParameter("membrane_data_clamp_current_conductance") << std::endl << std::flush;
            //std::cout << "mpModel->GetExperimentalVoltageAtTimeT(time) = " << mpModel->GetExperimentalVoltageAtTimeT(time) << std::endl << std::flush;

            unsigned how_many = 10000u;
            Timer::Reset();
            for (unsigned i=0; i<how_many; i++)
            {
                mpModel->GetExperimentalVoltageAtTimeT(time);
            }
            Timer::PrintAndReset("GetExperimentalVoltageAtTimeT");
        }

        // Generate some noisier data - more like a real cell.
        out_stream experimental_voltage_results_file = handler.OpenOutputFile("Shannon_noisy_data.dat");
        double experimental_noise_sd = 0.25; // directly from Teun's AP data trace of a stationary-looking bit
        for (unsigned i=0; i<expt_data.size(); i++)
        {
            double random_number = RandomNumberGenerator::Instance()->StandardNormalRandomDeviate();
            expt_data[i] +=  (10+experimental_noise_sd*random_number); // make experimental data very different to see if clamp works
            *experimental_voltage_results_file << expt_times[i] << "\t" << expt_data[i] << std::endl;
        }
        experimental_voltage_results_file->close();

        // In this half of the test, try running simulations with the clamp.
        {
            // Now solve with data clamp to the noisy data
            mpModel->SetExperimentalData(expt_times, expt_data);
            mpModel->ResetToInitialConditions();
            mpModel->TurnOnDataClamp();

            mpModel->SetParameter("membrane_data_clamp_current_conductance",0.001);

            std::vector<double> data_clamp_times;
            std::vector<double> data_clamp_voltage;

            for (int i = -4; i < 3; i++)
            {
                double clamp_conductance = pow(10,i);
                std::cout << "clamp_conductance = " << clamp_conductance << std::endl << std::flush;
                std::stringstream output_file;
                output_file << "Shannon_test_solution_with_data_clamp_conductance_exponent_" << i << ".dat";

                mpModel->ResetToInitialConditions();
                mpModel->SetParameter("membrane_data_clamp_current_conductance",clamp_conductance);
                solution = mpModel->Compute(0, 400, 0.2);
                data_clamp_times = solution.rGetTimes();
                data_clamp_voltage = solution.GetAnyVariable("membrane_voltage");

                out_stream data_clamp_voltage_results_file = handler.OpenOutputFile(output_file.str());
                for (unsigned j=0; j<data_clamp_voltage.size(); j++)
                {
                    *data_clamp_voltage_results_file << data_clamp_times[j] << "\t" << data_clamp_voltage[j] << "\n";
                }
                data_clamp_voltage_results_file->close();
            }
        }
#else
        std::cout << "Cvode is not enabled.\n";
#endif
    }
    void TestAdvance()
    {
        const double smidge = 1e-10;

        double start_time = 0.0;
        double end_time = 2.0;
        double timestep = 3.7e-05;

        // This is how a time stepper is normally used
        TimeStepper my_stepper(start_time, end_time, timestep);
        while ( !my_stepper.IsTimeAtEnd() )
        {
            // do something

            my_stepper.AdvanceOneTimeStep();
        }

        // Tests
        TS_ASSERT_THROWS_THIS(TimeStepper(end_time, start_time, timestep),
                              "The simulation duration must be positive, not -2");

        // Note that the timestep in this test does not divide whole time interval nicely, therefore we can't enforce a constant timestep.
        bool enforce_constant_timestep = true;
        TS_ASSERT_THROWS_CONTAINS(TimeStepper(start_time, end_time, timestep, enforce_constant_timestep),
                                      "TimeStepper estimates non-constant timesteps will need to be used");

        TimeStepper stepper(start_time, end_time, timestep);

        TS_ASSERT_EQUALS(stepper.EstimateTimeSteps(), (unsigned) floor((end_time - start_time)/timestep) );

        double real_time_step = timestep;
        unsigned time_step_number = 0;
        double current_time = start_time;

        /*
         * We'll trap for stopping times that are close to the end time
         * in order to avoid having a timestep of 1e-14 (or whatever) at
         * the end in the case of rounding errors.
         */
        double close_to_end_time = end_time - smidge*timestep;

        while (current_time < end_time)
        {
            TS_ASSERT(!stepper.IsTimeAtEnd());

            time_step_number++;

            // Determine what the value time step should really be like
            double to_time = start_time+time_step_number*timestep;

            if (to_time >= close_to_end_time)
            {
                real_time_step = end_time - current_time;
                //std::cout<<"TImes: " << timestep << " " << stepper.GetNextTimeStep() <<", difference = " << timestep - stepper.GetNextTimeStep()  << "\n";
                to_time = end_time;

                // Note that with non-constant timesteps, the final timestep can vary a lot (but not more than a normal sized timestep!).
                TS_ASSERT_DELTA(stepper.GetNextTimeStep(), timestep, timestep);
            }
            else
            {
                // Otherwise the GetNextTimeStep() returns the stored timestep,
                TS_ASSERT_EQUALS(stepper.GetNextTimeStep(),  timestep);

            }
            TS_ASSERT_DELTA(stepper.GetNextTimeStep(), real_time_step, DBL_EPSILON);
            TS_ASSERT_EQUALS(stepper.GetIdealTimeStep(), timestep);
            TS_ASSERT_EQUALS(stepper.GetTime(), current_time);
            TS_ASSERT_EQUALS(stepper.GetNextTime(), to_time);

            // Determine the new current time
            current_time = to_time;
            stepper.AdvanceOneTimeStep();

            TS_ASSERT_EQUALS(current_time, stepper.GetTime());
        }

        TS_ASSERT(stepper.IsTimeAtEnd());
        TS_ASSERT(stepper.GetTotalTimeStepsTaken()==time_step_number);

        //Stepper no longer allows increments beyond the end to be silently ignored
        TS_ASSERT_THROWS_THIS(stepper.AdvanceOneTimeStep(), "TimeStepper incremented beyond end time.");
    }
Ejemplo n.º 26
0
    void TestComputeCoarseElementsForFineElementCentroids() throw(Exception)
    {
        TetrahedralMesh<2,2> fine_mesh;
        fine_mesh.ConstructRegularSlabMesh(0.2, 1.0, 1.0);

        QuadraticMesh<2> coarse_mesh(1.0, 1.0, 1.0); // 2 triangular elements

        FineCoarseMeshPair<2> mesh_pair(fine_mesh,coarse_mesh);

        TS_ASSERT_THROWS_CONTAINS(mesh_pair.ComputeCoarseElementsForFineElementCentroids(true),"Call SetUpBoxesOnCoarseMesh()");

        mesh_pair.SetUpBoxesOnCoarseMesh();
        mesh_pair.ComputeCoarseElementsForFineElementCentroids(true);

        //Check that the indices of the coarse mesh elements are as expected
        unsigned lower_left_element_index=1u;
        ChastePoint<2> lower_left(0.25, 0.25);
        TS_ASSERT_EQUALS(coarse_mesh.GetContainingElementIndex(lower_left), lower_left_element_index);

        unsigned upper_right_element_index=0u;
        ChastePoint<2> upper_right(0.75, 0.75);
        TS_ASSERT_EQUALS(coarse_mesh.GetContainingElementIndex(upper_right), upper_right_element_index);

        TS_ASSERT_EQUALS( mesh_pair.rGetCoarseElementsForFineElementCentroids().size(), fine_mesh.GetNumElements());
        for (unsigned i=0; i<fine_mesh.GetNumElements(); i++)
        {
            double x = fine_mesh.GetElement(i)->CalculateCentroid()(0);
            double y = fine_mesh.GetElement(i)->CalculateCentroid()(1);
            if (x+y < 1.0)
            {
                TS_ASSERT_EQUALS(mesh_pair.rGetCoarseElementsForFineElementCentroids()[i], lower_left_element_index);
            }
            else
            {
                TS_ASSERT_EQUALS(mesh_pair.rGetCoarseElementsForFineElementCentroids()[i], upper_right_element_index);
            }
        }

        // Coverage
        mesh_pair.DeleteCoarseBoxCollection();
        mesh_pair.SetUpBoxesOnCoarseMesh(0.8); // force a point to be found in a neighbouring box
        mesh_pair.ComputeCoarseElementsForFineElementCentroids(true);

        mesh_pair.DeleteCoarseBoxCollection();
        mesh_pair.SetUpBoxesOnCoarseMesh(0.1); // force a point to be found in a nonlocal box
        mesh_pair.ComputeCoarseElementsForFineElementCentroids(true);

        mesh_pair.DeleteCoarseBoxCollection();
        mesh_pair.SetUpBoxesOnCoarseMesh(); // back to default

        /*
         * Translate the fine mesh in the (-1, -1) direction --> all fine elements
         * nearest to (not contained in) element 0. We have to make the fine mesh
         * tiny and then translate a small amount so that it is still in the box
         * collection for the coarse (normally the two meshes should overlap).
         */
        fine_mesh.Scale(1e-2, 1e-2);
        fine_mesh.Translate(-1.1e-2, -1.1e-2);
        mesh_pair.ComputeCoarseElementsForFineElementCentroids(true);
        TS_ASSERT_EQUALS( mesh_pair.rGetCoarseElementsForFineElementCentroids().size(), fine_mesh.GetNumElements());
        for (unsigned i=0; i<fine_mesh.GetNumElements(); i++)
        {
            TS_ASSERT_EQUALS( mesh_pair.rGetCoarseElementsForFineElementCentroids()[i], lower_left_element_index);
        }
    }
Ejemplo n.º 27
0
    void TestComputeCoarseElementsForFineNodes() throw(Exception)
    {
        TetrahedralMesh<2,2> fine_mesh;
        fine_mesh.ConstructRegularSlabMesh(0.2, 1.0, 1.0);

        QuadraticMesh<2> coarse_mesh(1.0, 1.0, 1.0); // 2 triangular elements

        FineCoarseMeshPair<2> mesh_pair(fine_mesh,coarse_mesh);
        TS_ASSERT_THROWS_CONTAINS(mesh_pair.ComputeCoarseElementsForFineNodes(true),"Call SetUpBoxesOnCoarseMesh()");

        mesh_pair.SetUpBoxesOnCoarseMesh();
        mesh_pair.ComputeCoarseElementsForFineNodes(true);

        //Check that the indices of the coarse mesh elements are as expected
        unsigned lower_left_element_index=1u;
        ChastePoint<2> lower_left(0.25, 0.25);
        TS_ASSERT_EQUALS(coarse_mesh.GetContainingElementIndex(lower_left), lower_left_element_index);
        ChastePoint<2> lower_left1(0.1, 0.25); //Double check that there is a `backslash`
        ChastePoint<2> lower_left2(0.25, 0.1);
        TS_ASSERT_EQUALS(coarse_mesh.GetContainingElementIndex(lower_left1), lower_left_element_index);
        TS_ASSERT_EQUALS(coarse_mesh.GetContainingElementIndex(lower_left2), lower_left_element_index);

        unsigned upper_right_element_index=0u;
        ChastePoint<2> upper_right(0.75, 0.75);
        TS_ASSERT_EQUALS(coarse_mesh.GetContainingElementIndex(upper_right), upper_right_element_index);

        for (unsigned i=0; i<fine_mesh.GetNumNodes(); i++)
        {
            double x = fine_mesh.GetNode(i)->rGetLocation()[0];
            double y = fine_mesh.GetNode(i)->rGetLocation()[1];

            if ( x+y < 1.0 - 1e-5 )  // x+y < 1
            {
                TS_ASSERT_EQUALS(mesh_pair.rGetCoarseElementsForFineNodes()[i], lower_left_element_index);
            }
            else if ( x+y > 1.0 + 1e-5 )  // x+y > 1
            {
                TS_ASSERT_EQUALS(mesh_pair.rGetCoarseElementsForFineNodes()[i], upper_right_element_index);
            }
            else // x=1-y, so in both elements, result could be either. However, it should find 0 first
            {
                //TS_ASSERT_LESS_THAN(mesh_pair.rGetCoarseElementsForFineNodes()[i], 2u);
                TS_ASSERT_EQUALS(mesh_pair.rGetCoarseElementsForFineNodes()[i], 0u);
            }
        }

        /*
         * Translate the fine mesh in the (-1, -1) direction --> all fine nodes
         * nearest to (not contained in) element 0. We have to make the fine mesh
         * tiny and then translate a small amount so that it is still in the box
         * collection for the coarse (normally the two meshes should overlap).
         */
        fine_mesh.Scale(1e-2, 1e-2);
        fine_mesh.Translate(-1.1e-2, -1.1e-2);
        mesh_pair.ComputeCoarseElementsForFineNodes(true);
        for (unsigned i=0; i<fine_mesh.GetNumNodes(); i++)
        {
            TS_ASSERT_EQUALS(mesh_pair.rGetCoarseElementsForFineNodes()[i], lower_left_element_index);
        }

        // Call again with safeMode=false this time (same results, faster)
        mesh_pair.rGetCoarseElementsForFineNodes()[0] = 189342958;
        mesh_pair.ComputeCoarseElementsForFineNodes(false);
        for (unsigned i=0; i<fine_mesh.GetNumNodes(); i++)
        {
            TS_ASSERT_EQUALS(mesh_pair.rGetCoarseElementsForFineNodes()[i], lower_left_element_index);
        }

        // Coverage:
        //  call again
        mesh_pair.SetUpBoxesOnCoarseMesh();
        //  delete
        mesh_pair.DeleteCoarseBoxCollection();
    }