NodeBasedCellPopulationWithParticles<DIM>::NodeBasedCellPopulationWithParticles(NodesOnlyMesh<DIM>& rMesh,
                                      std::vector<CellPtr>& rCells,
                                      const std::vector<unsigned> locationIndices,
                                      bool deleteMesh)
    : NodeBasedCellPopulation<DIM>(rMesh, rCells, locationIndices, deleteMesh, false)
{
    EXCEPT_IF_NOT(PetscTools::IsSequential());
    if (!locationIndices.empty())
    {
        // Create a set of node indices corresponding to particles
        std::set<unsigned> node_indices;
        std::set<unsigned> location_indices;
        std::set<unsigned> particle_indices;

        for (typename AbstractMesh<DIM,DIM>::NodeIterator node_iter = rMesh.GetNodeIteratorBegin();
             node_iter != rMesh.GetNodeIteratorEnd();
             ++node_iter)
        {
            node_indices.insert(node_iter->GetIndex());
        }
        for (unsigned i=0; i<locationIndices.size(); i++)
        {
            location_indices.insert(locationIndices[i]);
        }

        std::set_difference(node_indices.begin(), node_indices.end(),
                            location_indices.begin(), location_indices.end(),
                            std::inserter(particle_indices, particle_indices.begin()));

        // This method finishes and then calls Validate()
        SetParticles(particle_indices);
    }
    else
    {
        for (typename NodesOnlyMesh<DIM>::NodeIterator node_iter = rMesh.GetNodeIteratorBegin();
             node_iter != rMesh.GetNodeIteratorEnd();
             ++node_iter)
        {
            (*node_iter).SetIsParticle(false);
        }
        NodeBasedCellPopulationWithParticles::Validate();
    }
}
    void TestUpdateCellLocationsAndTopologyWithNoForce()
    {
        // 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("TestOffLatticeSimulationUpdateCellLocationsAndTopologyWithNoForce");
        simulator.SetupSolve();

        simulator.UpdateCellLocationsAndTopology();

        if (PetscTools::AmMaster())
        {
            for (AbstractMesh<2,2>::NodeIterator node_iter = mesh.GetNodeIteratorBegin();
                    node_iter != mesh.GetNodeIteratorEnd();
                    ++node_iter)
            {
                for (unsigned d=0; d<2; d++)
                {
                    TS_ASSERT_DELTA(node_iter->rGetAppliedForce()[d], 0.0, 1e-15);
                }
            }
        }

        // Avoid memory leak
        delete nodes[0];
        delete nodes[1];
    }
コード例 #3
0
    void TestVertexCryptBoundaryForceForceWithNonVertexCellPopulation() throw (Exception)
    {
        // Create a NodeBasedCellPopulation
        std::vector<Node<2>*> nodes;
        unsigned num_nodes = 10;
        for (unsigned i=0; i<num_nodes; i++)
        {
            double x = (double)(i);
            double y = (double)(i);
            nodes.push_back(new Node<2>(i, true, x, y));
        }
        // Convert this to a NodesOnlyMesh
        NodesOnlyMesh<2> mesh;
        mesh.ConstructNodesWithoutMesh(nodes, 1.5);

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

        NodeBasedCellPopulation<2> non_vertex_cell_population(mesh, cells);

        for (AbstractMesh<2,2>::NodeIterator node_iter = mesh.GetNodeIteratorBegin();
                node_iter != mesh.GetNodeIteratorEnd();
                ++node_iter)
        {
            node_iter->ClearAppliedForce();
        }

        // Test that VertexCryptBoundaryForce throws the correct exception
        VertexCryptBoundaryForce<2> force(100);
        TS_ASSERT_THROWS_THIS(force.AddForceContribution(non_vertex_cell_population),
                "VertexCryptBoundaryForce is to be used with VertexBasedCellPopulations only");

        // Avoid memory leak
        for (unsigned i=0; i<nodes.size(); i++)
        {
            delete nodes[i];
        }
    }
    void TestRemoveDeadCellsAndReMeshWithParticles()
    {
        EXIT_IF_PARALLEL;    // This test doesn't work in parallel.

        SimulationTime* p_simulation_time = SimulationTime::Instance();
        p_simulation_time->SetEndTimeAndNumberOfTimeSteps(10.0, 1);

        // Create a simple mesh
        TrianglesMeshReader<2,2> mesh_reader("mesh/test/data/square_128_elements");
        TetrahedralMesh<2,2> generating_mesh;
        generating_mesh.ConstructFromMeshReader(mesh_reader);

        // Convert this to a NodesOnlyMesh
        NodesOnlyMesh<2> mesh;
        mesh.ConstructNodesWithoutMesh(generating_mesh, 1.2);

        // Create vector of cell location indices
        std::vector<unsigned> cell_location_indices;
        for (unsigned i=10; i<mesh.GetNumNodes(); i++)
        {
            if (i != 80)
            {
                cell_location_indices.push_back(i);
            }
        }

        // Set up cells
        std::vector<CellPtr> cells;
        CellsGenerator<FixedDurationGenerationBasedCellCycleModel, 2> cells_generator;
        cells_generator.GenerateBasic(cells, cell_location_indices.size());
        cells[27]->StartApoptosis();

        // Create a cell population, with some random particles
        NodeBasedCellPopulationWithParticles<2> cell_population_with_particles(mesh, cells, cell_location_indices);

        TS_ASSERT_EQUALS(mesh.GetNumNodes(), 81u);

        // Num real cells should be num_nodes (81) - num_particles (11) = 70
        TS_ASSERT_EQUALS(cell_population_with_particles.GetNumRealCells(), 70u);

        p_simulation_time->IncrementTimeOneStep();

        unsigned num_removed_with_particles = cell_population_with_particles.RemoveDeadCells();

        TS_ASSERT_EQUALS(num_removed_with_particles, 1u);
        TS_ASSERT_EQUALS(mesh.GetNumNodes(), 80u);
        TS_ASSERT_DIFFERS(cell_population_with_particles.rGetCells().size(), cells.size()); // CellPopulation now copies cells

        // Num real cells should be num_nodes (81) - num_particle (11) - 1 deleted node = 69
        TS_ASSERT_EQUALS(cell_population_with_particles.GetNumRealCells(), 69u);

        cell_population_with_particles.Update();

        // For coverage
        NodeMap map(mesh.GetNumAllNodes());
        map.ResetToIdentity();
        cell_population_with_particles.UpdateParticlesAfterReMesh(map);

        // Num real cells should be new_num_nodes (80) - num_particles (11)
        TS_ASSERT_EQUALS(cell_population_with_particles.GetNumRealCells(), 69u);
        TS_ASSERT_EQUALS(mesh.GetNumNodes(), mesh.GetNumAllNodes());

        // Nodes 0-9 should not been renumbered so are still particles.
        // the particle at node 80 is now at 79 as node 27 was deleted..
        for (AbstractMesh<2,2>::NodeIterator node_iter = mesh.GetNodeIteratorBegin();
                node_iter != mesh.GetNodeIteratorEnd();
                ++node_iter)
        {
            unsigned index = node_iter->GetIndex();
            // True (ie should be a particle) if i<10 or i==79, else false
            TS_ASSERT_EQUALS(cell_population_with_particles.IsParticle(index), ((index<10)||(index==80)));
        }

        // Finally, check the cells node indices have updated

        // We expect the cell node indices to be {10,11,...,79}
        std::set<unsigned> expected_node_indices;
        for (unsigned i=0; i<cell_population_with_particles.GetNumRealCells(); i++)
        {
            if (i!=27)
            {
                expected_node_indices.insert(i+10);
            }
        }
        expected_node_indices.insert(79);
        // Get actual cell node indices
        std::set<unsigned> node_indices_with_particles;

        for (AbstractCellPopulation<2>::Iterator cell_iter = cell_population_with_particles.Begin();
                cell_iter != cell_population_with_particles.End();
                ++cell_iter)
        {
            // Record node index corresponding to cell
            unsigned node_index_with_particles = cell_population_with_particles.GetLocationIndexUsingCell(*cell_iter);
            node_indices_with_particles.insert(node_index_with_particles);
        }

        TS_ASSERT_EQUALS(node_indices_with_particles, expected_node_indices);
    }