void GonadArmPositionTrackerModifier<DIM>::UpdateAtEndOfTimeStep(AbstractCellPopulation<DIM,DIM>& rCellPopulation)
{

	if((SimulationTime::Instance()->GetTime())-(int)SimulationTime::Instance()->GetTime()==(1/250))

    for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = rCellPopulation.Begin();
         cell_iter != rCellPopulation.End();
         ++cell_iter)
    {

    	double id = cell_iter->GetCellId();
    	double position = cell_iter->GetCellData()->GetItem("DistanceAwayFromDTC");
    	double prolif = cell_iter->GetCellData()->GetItem("Proliferating");

    	fprintf(OutputPositionFile,"%e\t",SimulationTime::Instance()->GetTime());
    	fprintf(OutputPositionFile,"%f\t",id);
    	fprintf(OutputPositionFile,"%e\t",position);
    	fprintf(OutputPositionFile,"%e\t",prolif);
    	fprintf(OutputPositionFile,"\n");
    }

	if(SimulationTime::Instance()->IsFinished()){
		//Close output file
		fclose(OutputPositionFile);
	}
}
예제 #2
0
void VolumeTrackingModifier<DIM>::UpdateCellData(AbstractCellPopulation<DIM,DIM>& rCellPopulation)
{
    // Make sure the cell population is updated
    rCellPopulation.Update();

    /**
     * This hack is needed because in the case of a MeshBasedCellPopulation in which
     * multiple cell divisions have occurred over one time step, the Voronoi tessellation
     * (while existing) is out-of-date. Thus, if we did not regenerate the Voronoi
     * tessellation here, an assertion may trip as we try to access a Voronoi element
     * whose index exceeds the number of elements in the out-of-date tessellation.
     *
     * \todo work out how to properly fix this (#1986)
     */
    if (bool(dynamic_cast<MeshBasedCellPopulation<DIM>*>(&rCellPopulation)))
    {
        static_cast<MeshBasedCellPopulation<DIM>*>(&(rCellPopulation))->CreateVoronoiTessellation();
    }

    // Iterate over cell population
    for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = rCellPopulation.Begin();
         cell_iter != rCellPopulation.End();
         ++cell_iter)
    {
        // Get the volume of this cell
        double cell_volume = rCellPopulation.GetVolumeOfCell(*cell_iter);

        // Store the cell's volume in CellData
        cell_iter->GetCellData()->SetItem("volume", cell_volume);
    }
}
예제 #3
0
void AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::SetCellAncestorsToLocationIndices()
{
    for (typename AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::Iterator cell_iter=this->Begin(); cell_iter!=this->End(); ++cell_iter)
    {
        MAKE_PTR_ARGS(CellAncestor, p_cell_ancestor, (mCellLocationMap[(*cell_iter).get()]));
        cell_iter->SetAncestor(p_cell_ancestor);
    }
}
예제 #4
0
std::set<unsigned> AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::GetCellAncestors()
{
    std::set<unsigned> remaining_ancestors;
    for (typename AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::Iterator cell_iter=this->Begin(); cell_iter!=this->End(); ++cell_iter)
    {
        remaining_ancestors.insert(cell_iter->GetAncestor());
    }
    return remaining_ancestors;
}
예제 #5
0
void AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::SetDataOnAllCells(const std::string& rDataName, double dataValue)
{
    for (typename AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::Iterator cell_iter=this->Begin();
         cell_iter!=this->End();
         ++cell_iter)
    {
        cell_iter->GetCellData()->SetItem(rDataName, dataValue);
    }
}
예제 #6
0
void AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::InitialiseCells()
{
    for (typename AbstractCellPopulation<ELEMENT_DIM, SPACE_DIM>::Iterator cell_iter=this->Begin();
         cell_iter!=this->End();
         ++cell_iter)
    {
        cell_iter->InitialiseCellCycleModel();
        cell_iter->InitialiseSrnModel();
    }
}
예제 #7
0
void PlaneBasedCellKiller<DIM>::CheckAndLabelCellsForApoptosisOrDeath()
{
    for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = this->mpCellPopulation->Begin();
         cell_iter != this->mpCellPopulation->End();
         ++cell_iter)
    {
        c_vector<double, DIM> cell_location = this->mpCellPopulation->GetLocationOfCellCentre(*cell_iter);

        if (inner_prod(cell_location - mPointOnPlane, mNormalToPlane) > 0.0)
        {
            cell_iter->Kill();
        }
    }
}
void TimedPlaneBasedCellKiller<DIM>::CheckAndLabelCellsForApoptosisOrDeath()
{
    for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = this->mpCellPopulation->Begin();
         cell_iter != this->mpCellPopulation->End();
         ++cell_iter)
    {
        c_vector<double, DIM> cell_location = this->mpCellPopulation->GetLocationOfCellCentre(*cell_iter);

        if (inner_prod(cell_location - mPointOnPlane, mNormalToPlane) > 0.0 && SimulationTime::Instance()->GetTime()>=mStartTime)
        {
        	 OUTPUT<<SimulationTime::Instance()->GetTime()<<"	"<<(*cell_iter)->GetCellId()<<std::endl;
            cell_iter->Kill();
        }
    }
}
예제 #9
0
void SloughingCellKiller<DIM>::CheckAndLabelCellsForApoptosisOrDeath()
{
    switch (DIM)
    {
        case 1:
        {
            for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = this->mpCellPopulation->Begin();
                 cell_iter != this->mpCellPopulation->End();
                 ++cell_iter)
            {
                double x = this->mpCellPopulation->GetLocationOfCellCentre(*cell_iter)[0];

                if (x > mSloughHeight)
                {
                    cell_iter->Kill();
                }
            }
            break;
        }
        case 2:
        {
            for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = this->mpCellPopulation->Begin();
                 cell_iter != this->mpCellPopulation->End();
                 ++cell_iter)
            {
                c_vector<double, 2> location;
                location = this->mpCellPopulation->GetLocationOfCellCentre(*cell_iter);
                double x = location[0];
                double y = location[1];

                if ((y>mSloughHeight) || (mSloughSides && ((x<0.0) || (x>mSloughWidth))))
                {
                    cell_iter->Kill();
                }
            }
            break;
        }
        case 3:
        {
            EXCEPTION("SloughingCellKiller is not yet implemented in 3D");
            break;
        }
        default:
            // This can't happen
            NEVER_REACHED;
    }
}
예제 #10
0
void NodeBasedCellPopulation<DIM>::Update(bool hasHadBirthsOrDeaths)
{
    UpdateCellProcessLocation();

    mpNodesOnlyMesh->UpdateBoxCollection();

    if (mLoadBalanceMesh)
    {
        if ((SimulationTime::Instance()->GetTimeStepsElapsed() % mLoadBalanceFrequency) == 0)
        {
            mpNodesOnlyMesh->LoadBalanceMesh();

            UpdateCellProcessLocation();

            mpNodesOnlyMesh->UpdateBoxCollection();
        }
    }

    RefreshHaloCells();

    mpNodesOnlyMesh->CalculateInteriorNodePairs(mNodePairs, mNodeNeighbours);

    AddReceivedHaloCells();

    mpNodesOnlyMesh->CalculateBoundaryNodePairs(mNodePairs, mNodeNeighbours);

    /*
     * Update cell radii based on CellData
     */
    if (mUseVariableRadii)
    {
        for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = this->Begin();
             cell_iter != this->End();
             ++cell_iter)
        {
            double cell_radius = cell_iter->GetCellData()->GetItem("Radius");
            unsigned node_index = this->GetLocationIndexUsingCell(*cell_iter);
            this->GetNode(node_index)->SetRadius(cell_radius);
        }
    }

    // Make sure that everyone exits update together so that all asynchronous communications are complete.
    PetscTools::Barrier("Update");
}
void IsolatedLabelledCellKiller<DIM>::CheckAndLabelCellsForApoptosisOrDeath()
{
    MutableVertexMesh<DIM, DIM>& vertex_mesh = static_cast<VertexBasedCellPopulation<DIM>*>(this->mpCellPopulation)->rGetMesh();

    unsigned num_labelled_cells = this->mpCellPopulation->GetCellPropertyRegistry()->template Get<CellLabel>()->GetCellCount();

    // If there is more than one labelled cell...
    if (num_labelled_cells > 1)
    {
        // Iterate over cell population
        for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = this->mpCellPopulation->Begin();
             cell_iter != this->mpCellPopulation->End();
             ++cell_iter)
        {
            // Only consider cells with the CellLabel property
            if (cell_iter->template HasCellProperty<CellLabel>())
            {
                // Get the element index corresponding to this cell
                unsigned elem_index = this->mpCellPopulation->GetLocationIndexUsingCell(*cell_iter);

                // Get the set of neighbouring element indices
                std::set<unsigned> neighbouring_elem_indices = vertex_mesh.GetNeighbouringElementIndices(elem_index);

                // Check if any of the corresponding cells have the CellLabel property...
                unsigned num_labelled_neighbours = 0;
                for (std::set<unsigned>::iterator elem_iter = neighbouring_elem_indices.begin();
                     elem_iter != neighbouring_elem_indices.end();
                     ++elem_iter)
                {
                    if (this->mpCellPopulation->GetCellUsingLocationIndex(*elem_iter)->template HasCellProperty<CellLabel>())
                    {
                        num_labelled_neighbours++;
                    }
                }

                // ...and if none do, then kill this cell
                if (num_labelled_neighbours == 0)
                {
                    cell_iter->Kill();
                }
            }
        }
    }
}
void DeltaNotchTrackingModifier<DIM>::UpdateCellData(AbstractCellPopulation<DIM,DIM>& rCellPopulation)
{
    // Make sure the cell population is updated
    rCellPopulation.Update();

    // First recover each cell's Notch and Delta concentrations from the ODEs and store in CellData
    for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = rCellPopulation.Begin();
         cell_iter != rCellPopulation.End();
         ++cell_iter)
    {
        DeltaNotchCellCycleModel* p_model = static_cast<DeltaNotchCellCycleModel*>(cell_iter->GetCellCycleModel());
        double this_delta = p_model->GetDelta();
        double this_notch = p_model->GetNotch();

        // Note that the state variables must be in the same order as listed in DeltaNotchOdeSystem
        cell_iter->GetCellData()->SetItem("notch", this_notch);
        cell_iter->GetCellData()->SetItem("delta", this_delta);
    }

    // Next iterate over the population to compute and store each cell's neighbouring Delta concentration in CellData
    for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = rCellPopulation.Begin();
         cell_iter != rCellPopulation.End();
         ++cell_iter)
    {
        // Get the set of neighbouring location indices
        std::set<unsigned> neighbour_indices = rCellPopulation.GetNeighbouringLocationIndices(*cell_iter);

        // Compute this cell's average neighbouring Delta concentration and store in CellData
        if (!neighbour_indices.empty())
        {
            double mean_delta = 0.0;
            for (std::set<unsigned>::iterator iter = neighbour_indices.begin();
                 iter != neighbour_indices.end();
                 ++iter)
            {
                CellPtr p_cell = rCellPopulation.GetCellUsingLocationIndex(*iter);
                double this_delta = p_cell->GetCellData()->GetItem("delta");
                mean_delta += this_delta/neighbour_indices.size();
            }
            cell_iter->GetCellData()->SetItem("mean delta", mean_delta);
        }
        else
        {
            // If this cell has no neighbours, such as an isolated cell in a CaBasedCellPopulation, store 0.0 for the cell data
            cell_iter->GetCellData()->SetItem("mean delta", 0.0);
        }
    }
}
void MeshBasedCellPopulation<ELEMENT_DIM,SPACE_DIM>::WriteVtkResultsToFile(const std::string& rDirectory)
{
#ifdef CHASTE_VTK
    // Store the present time as a string
    unsigned num_timesteps = SimulationTime::Instance()->GetTimeStepsElapsed();
    std::stringstream time;
    time << num_timesteps;

    // Store the number of cells for which to output data to VTK
    unsigned num_cells_from_mesh = GetNumNodes();
    if (!mWriteVtkAsPoints && (mpVoronoiTessellation != NULL))
    {
        num_cells_from_mesh = mpVoronoiTessellation->GetNumElements();
    }

    // When outputting any CellData, we assume that the first cell is representative of all cells
    unsigned num_cell_data_items = this->Begin()->GetCellData()->GetNumItems();
    std::vector<std::string> cell_data_names = this->Begin()->GetCellData()->GetKeys();

    std::vector<std::vector<double> > cell_data;
    for (unsigned var=0; var<num_cell_data_items; var++)
    {
        std::vector<double> cell_data_var(num_cells_from_mesh);
        cell_data.push_back(cell_data_var);
    }

    if (mOutputMeshInVtk)
    {
        // Create mesh writer for VTK output
        VtkMeshWriter<ELEMENT_DIM, SPACE_DIM> mesh_writer(rDirectory, "mesh_"+time.str(), false);
        mesh_writer.WriteFilesUsingMesh(rGetMesh());
    }

    if (mWriteVtkAsPoints)
    {
        // Create mesh writer for VTK output
        VtkMeshWriter<SPACE_DIM, SPACE_DIM> cells_writer(rDirectory, "results_"+time.str(), false);

        // Iterate over any cell writers that are present
        unsigned num_cells = this->GetNumAllCells();
        for (typename std::vector<boost::shared_ptr<AbstractCellWriter<ELEMENT_DIM, SPACE_DIM> > >::iterator cell_writer_iter = this->mCellWriters.begin();
             cell_writer_iter != this->mCellWriters.end();
             ++cell_writer_iter)
        {
            // Create vector to store VTK cell data
            std::vector<double> vtk_cell_data(num_cells);

            // Loop over cells
            for (typename AbstractCellPopulation<ELEMENT_DIM,SPACE_DIM>::Iterator cell_iter = this->Begin();
                 cell_iter != this->End();
                 ++cell_iter)
            {
                // Get the node index corresponding to this cell
                unsigned node_index = this->GetLocationIndexUsingCell(*cell_iter);

                // Populate the vector of VTK cell data
                vtk_cell_data[node_index] = (*cell_writer_iter)->GetCellDataForVtkOutput(*cell_iter, this);
            }

            cells_writer.AddPointData((*cell_writer_iter)->GetVtkCellDataName(), vtk_cell_data);
        }

        // Loop over cells
        for (typename AbstractCellPopulation<ELEMENT_DIM,SPACE_DIM>::Iterator cell_iter = this->Begin();
             cell_iter != this->End();
             ++cell_iter)
        {
            // Get the node index corresponding to this cell
            unsigned node_index = this->GetLocationIndexUsingCell(*cell_iter);

            for (unsigned var=0; var<num_cell_data_items; var++)
            {
                cell_data[var][node_index] = cell_iter->GetCellData()->GetItem(cell_data_names[var]);
            }
        }
        for (unsigned var=0; var<num_cell_data_items; var++)
        {
            cells_writer.AddPointData(cell_data_names[var], cell_data[var]);
        }

        // Make a copy of the nodes in a disposable mesh for writing
        {
            std::vector<Node<SPACE_DIM>* > nodes;
            for (unsigned index=0; index<this->mrMesh.GetNumNodes(); index++)
            {
                Node<SPACE_DIM>* p_node = this->mrMesh.GetNode(index);
                nodes.push_back(p_node);
            }

            NodesOnlyMesh<SPACE_DIM> mesh;
            mesh.ConstructNodesWithoutMesh(nodes, 1.5); // Arbitrary cut off as connectivity not used.
            cells_writer.WriteFilesUsingMesh(mesh);
        }

        *(this->mpVtkMetaFile) << "        <DataSet timestep=\"";
        *(this->mpVtkMetaFile) << num_timesteps;
        *(this->mpVtkMetaFile) << "\" group=\"\" part=\"0\" file=\"results_";
        *(this->mpVtkMetaFile) << num_timesteps;
        *(this->mpVtkMetaFile) << ".vtu\"/>\n";
    }
    else if (mpVoronoiTessellation != NULL)
    {
        // Create mesh writer for VTK output
        VertexMeshWriter<ELEMENT_DIM, SPACE_DIM> mesh_writer(rDirectory, "results", false);
        std::vector<double> cell_volumes(num_cells_from_mesh);

        // Iterate over any cell writers that are present
        unsigned num_cells = this->GetNumAllCells();
        for (typename std::vector<boost::shared_ptr<AbstractCellWriter<ELEMENT_DIM, SPACE_DIM> > >::iterator cell_writer_iter = this->mCellWriters.begin();
             cell_writer_iter != this->mCellWriters.end();
             ++cell_writer_iter)
        {
            // Create vector to store VTK cell data
            std::vector<double> vtk_cell_data(num_cells);

            // Loop over elements of mpVoronoiTessellation
            for (typename VertexMesh<ELEMENT_DIM, SPACE_DIM>::VertexElementIterator elem_iter = mpVoronoiTessellation->GetElementIteratorBegin();
                 elem_iter != mpVoronoiTessellation->GetElementIteratorEnd();
                 ++elem_iter)
            {
                // Get index of this element in mpVoronoiTessellation
                unsigned elem_index = elem_iter->GetIndex();

                // Get the cell corresponding to this element, via the index of the corresponding node in mrMesh
                unsigned node_index = mpVoronoiTessellation->GetDelaunayNodeIndexCorrespondingToVoronoiElementIndex(elem_index);
                CellPtr p_cell = this->GetCellUsingLocationIndex(node_index);

                // Populate the vector of VTK cell data
                vtk_cell_data[elem_index] = (*cell_writer_iter)->GetCellDataForVtkOutput(p_cell, this);
            }

            mesh_writer.AddCellData((*cell_writer_iter)->GetVtkCellDataName(), vtk_cell_data);
        }

        // Loop over elements of mpVoronoiTessellation
        for (typename VertexMesh<ELEMENT_DIM, SPACE_DIM>::VertexElementIterator elem_iter = mpVoronoiTessellation->GetElementIteratorBegin();
             elem_iter != mpVoronoiTessellation->GetElementIteratorEnd();
             ++elem_iter)
        {
            // Get index of this element in mpVoronoiTessellation
            unsigned elem_index = elem_iter->GetIndex();

            // Get the cell corresponding to this element, via the index of the corresponding node in mrMesh
            unsigned node_index = mpVoronoiTessellation->GetDelaunayNodeIndexCorrespondingToVoronoiElementIndex(elem_index);
            CellPtr p_cell = this->GetCellUsingLocationIndex(node_index);

            for (unsigned var=0; var<num_cell_data_items; var++)
            {
                cell_data[var][elem_index] = p_cell->GetCellData()->GetItem(cell_data_names[var]);
            }
        }

        for (unsigned var=0; var<cell_data.size(); var++)
        {
            mesh_writer.AddCellData(cell_data_names[var], cell_data[var]);
        }

        mesh_writer.WriteVtkUsingMesh(*mpVoronoiTessellation, time.str());
        *(this->mpVtkMetaFile) << "        <DataSet timestep=\"";
        *(this->mpVtkMetaFile) << num_timesteps;
        *(this->mpVtkMetaFile) << "\" group=\"\" part=\"0\" file=\"results_";
        *(this->mpVtkMetaFile) << num_timesteps;
        *(this->mpVtkMetaFile) << ".vtu\"/>\n";
    }
#endif //CHASTE_VTK
}
void CombinedStaticGonadBoundaryCondition<DIM>::ImposeBoundaryCondition(const std::map<Node<DIM>*, c_vector<double, DIM> >& rOldLocations)
{

    // Iterate over the cell population and get cell location
    for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = this->mpCellPopulation->Begin();
         cell_iter != this->mpCellPopulation->End();
         ++cell_iter)
    {
    	 c_vector<double,DIM> cell_location = this->mpCellPopulation->GetLocationOfCellCentre(*cell_iter);
    	 Node<DIM>* cell_centre_node = this->mpCellPopulation->GetNode(this->mpCellPopulation->GetLocationIndexUsingCell(*cell_iter));
    	 double radius = cell_centre_node->GetRadius();

    	 // Find C, the closest point on the growth path for this cell, and R the distance to it.
        double R=0;
        c_vector<double, DIM> C= zero_vector<double>(3);

        //If all three parts of the path exist, measure distances to the lower+upper straights and the loop
        //Find min distance to each of the three parts of the path
        double R1=0; double R2=0; double R3=0;
        c_vector<double, DIM> C1=zero_vector<double>(3);
        c_vector<double, DIM> C2=zero_vector<double>(3);
        c_vector<double, DIM> C3=zero_vector<double>(3);
        GetClosestOnLowerStraight(C1,cell_location,R1);
        GetClosestOnLoop(C2,cell_location,R2);
        GetClosestOnUpperStraight(C3,cell_location,R3);
        //Take min and record closest point
        R=std::min(R1,std::min(R2,R3));
        if(R==R1){
        	C=C1;
        }else if(R==R2){
        	C=C2;
        }else{
        	C=C3;
        }

        double distance;
        HowFarAlongAreYou(C,distance);
        double SyncytiumRadius = GetSyncytiumRadius(distance);

        if(distance>mStraightLengthLower){

        	//Prevent a cell moving back down the tube to somewhere it doesn't fit
			if(radius>(mCurrentTubeRadius-SyncytiumRadius)/2){
				unsigned node_index = this->mpCellPopulation->GetLocationIndexUsingCell(*cell_iter);
				Node<DIM>* p_node = this->mpCellPopulation->GetNode(node_index);
				c_vector<double,DIM>& p_force = p_node->rGetAppliedForce();
				double damping_const = dynamic_cast<NodeBasedCellPopulation<DIM>*>(this->mpCellPopulation)->GetDampingConstant(node_index);
				p_node->rGetModifiableLocation() = cell_location-SimulationTime::Instance()->GetTimeStep()*(p_force)/damping_const;
			}else{
				// If the cell is too far inside the growth path, and therefore in the syncytium...
				if (R-radius<SyncytiumRadius-mMaximumDistance)
				{
					// ...move the cell back onto the surface of the tube by translating away from C:
					unsigned node_index = this->mpCellPopulation->GetLocationIndexUsingCell(*cell_iter);
					Node<DIM>* p_node = this->mpCellPopulation->GetNode(node_index);
					p_node->rGetModifiableLocation() = C+(SyncytiumRadius+radius)*(cell_location-C)/norm_2(cell_location-C);
				}
				// If the cell is too far from the growth path, and therefore outside the tube...
				if (R+radius-mCurrentTubeRadius > mMaximumDistance)
				{
					// ...move the cell back onto the surface of the tube by translating toward C:
					unsigned node_index = this->mpCellPopulation->GetLocationIndexUsingCell(*cell_iter);
					Node<DIM>* p_node = this->mpCellPopulation->GetNode(node_index);
					p_node->rGetModifiableLocation() = C+(mCurrentTubeRadius-radius)*(cell_location-C)/norm_2(cell_location-C);
				}
			}

        }else{
			// If the cell is too far from the growth path, and therefore outside the tube...
			if (R+radius-mCurrentTubeRadius > mMaximumDistance)
			{
				// ...move the cell back onto the surface of the tube by translating toward C:
				unsigned node_index = this->mpCellPopulation->GetLocationIndexUsingCell(*cell_iter);
				Node<DIM>* p_node = this->mpCellPopulation->GetNode(node_index);
				p_node->rGetModifiableLocation() = C+(mCurrentTubeRadius-radius)*(cell_location-C)/norm_2(cell_location-C);
			}
        }

        /*Assuming all is now well, update the cell data to record how far along the gonad arm this cell is.
         * Use the vector C, which stores the closest point on the growth path to this cell.*/
        HowFarAlongAreYou(C,distance);
        cell_iter->GetCellData()->SetItem("DistanceAwayFromDTC", mStraightLengthLower+mStraightLengthUpper+mTurnRadius*M_PI-distance);
        if(distance<(mStraightLengthLower-1)){
        	cell_iter->GetCellData()->SetItem("MaxRadius",mCurrentTubeRadius);
        }else{
        	cell_iter->GetCellData()->SetItem("MaxRadius",(mCurrentTubeRadius-SyncytiumRadius-0.1)/2);
        }
    }

}
예제 #15
0
void CellBasedPdeHandler<DIM>::WritePdeSolution(double time)
{
    if (PetscTools::AmMaster())
    {
        (*mpVizPdeSolutionResultsFile) << time << "\t";

#ifdef CHASTE_VTK
        // Note that this mesh writer is only constructed and used if mpCoarsePdeMesh exists
        VtkMeshWriter<DIM,DIM>* p_vtk_mesh_writer = NULL;
        if (DIM>1 && mpCoarsePdeMesh != NULL )
        {
            std::ostringstream time_string;
            time_string << SimulationTime::Instance()->GetTimeStepsElapsed()+1;
            std::string results_file = "pde_results_"+time_string.str();
            // Note that this mesh writer is always constructed, but is only used if mpCoarsePdeMesh exists
            p_vtk_mesh_writer = new VtkMeshWriter<DIM,DIM>(mDirPath, results_file, false);
        }
#endif //CHASTE_VTK
        for (unsigned pde_index=0; pde_index<mPdeAndBcCollection.size(); pde_index++)
        {
            if (mpCoarsePdeMesh != NULL)
            {
                PdeAndBoundaryConditions<DIM>* p_pde_and_bc = mPdeAndBcCollection[pde_index];
                assert( p_pde_and_bc->rGetDependentVariableName()!="");

#ifdef CHASTE_VTK
                if (p_pde_and_bc->GetSolution())
                {
                    if (DIM>1)
                    {
                        ReplicatableVector solution_repl(p_pde_and_bc->GetSolution());
                        std::vector<double> pde_solution;
                        for (unsigned i=0; i<mpCoarsePdeMesh->GetNumNodes(); i++)
                        {
                            pde_solution.push_back(solution_repl[i]);
                        }

                        p_vtk_mesh_writer->AddPointData(p_pde_and_bc->rGetDependentVariableName(),pde_solution);
                    }
                }

#endif //CHASTE_VTK

                for (unsigned i=0; i<mpCoarsePdeMesh->GetNumNodes(); i++)
                {
                    (*mpVizPdeSolutionResultsFile) << i << " ";
                    c_vector<double,DIM> location = mpCoarsePdeMesh->GetNode(i)->rGetLocation();
                    for (unsigned k=0; k<DIM; k++)
                    {
                        (*mpVizPdeSolutionResultsFile) << location[k] << " ";
                    }

                    if (p_pde_and_bc->GetSolution())
                    {
                        ReplicatableVector solution_repl(p_pde_and_bc->GetSolution());
                        (*mpVizPdeSolutionResultsFile) << solution_repl[i] << " ";
                    }
                    else
                    {
                        // should only come into this method AFTER solving the PDE
                        NEVER_REACHED;
                    }
                }
            }
            else // Not coarse mesh
            {
                for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = mpCellPopulation->Begin();
                     cell_iter != mpCellPopulation->End();
                     ++cell_iter)
                {
                    unsigned node_index = mpCellPopulation->GetLocationIndexUsingCell(*cell_iter);
                    (*mpVizPdeSolutionResultsFile) << node_index << " ";
                    const c_vector<double,DIM>& position = mpCellPopulation->GetLocationOfCellCentre(*cell_iter);
                    for (unsigned i=0; i<DIM; i++)
                    {
                        (*mpVizPdeSolutionResultsFile) << position[i] << " ";
                    }
                    double solution = cell_iter->GetCellData()->GetItem(mPdeAndBcCollection[pde_index]->rGetDependentVariableName());
                    (*mpVizPdeSolutionResultsFile) << solution << " ";
                }
            }
        }
        (*mpVizPdeSolutionResultsFile) << "\n";
#ifdef CHASTE_VTK
        if (p_vtk_mesh_writer != NULL)
        {
            p_vtk_mesh_writer->WriteFilesUsingMesh(*mpCoarsePdeMesh);
            delete p_vtk_mesh_writer;
        }
#endif //CHASTE_VTK
    }
}
예제 #16
0
void CellBasedPdeHandler<DIM>::SolvePdeAndWriteResultsToFile(unsigned samplingTimestepMultiple)
{
    // Record whether we are solving PDEs on a coarse mesh
    bool using_coarse_pde_mesh = (mpCoarsePdeMesh != NULL);

    // If solving PDEs on a coarse mesh, each PDE should have an averaged source term; otherwise none should
    assert(!mPdeAndBcCollection.empty());
    for (unsigned pde_index=0; pde_index<mPdeAndBcCollection.size(); pde_index++)
    {
        assert(mPdeAndBcCollection[pde_index]);
        assert(mPdeAndBcCollection[pde_index]->HasAveragedSourcePde() == using_coarse_pde_mesh || dynamic_cast<MultipleCaBasedCellPopulation<DIM>*>(mpCellPopulation));
    }

    // Make sure the cell population is in a nice state
    mpCellPopulation->Update();

    // Store a pointer to the (population-level or coarse) mesh
    TetrahedralMesh<DIM,DIM>* p_mesh;
    if (using_coarse_pde_mesh)
    {
        p_mesh = mpCoarsePdeMesh;
    }
    else
    {
        // If not using a coarse PDE mesh, we must be using a MeshBasedCellPopulation
        p_mesh = &(static_cast<MeshBasedCellPopulation<DIM>*>(mpCellPopulation)->rGetMesh());
    }

    // Loop over elements of mPdeAndBcCollection
    for (unsigned pde_index=0; pde_index<mPdeAndBcCollection.size(); pde_index++)
    {
        // Get pointer to this PdeAndBoundaryConditions object
        PdeAndBoundaryConditions<DIM>* p_pde_and_bc = mPdeAndBcCollection[pde_index];

        // Set up boundary conditions
        std::auto_ptr<BoundaryConditionsContainer<DIM,DIM,1> > p_bcc = ConstructBoundaryConditionsContainer(p_pde_and_bc, p_mesh);

        // If the solution at the previous timestep exists...
        PetscInt previous_solution_size = 0;
        if (p_pde_and_bc->GetSolution())
        {
            VecGetSize(p_pde_and_bc->GetSolution(), &previous_solution_size);
        }

        // ...then record whether it is the correct size...
        bool is_previous_solution_size_correct = (previous_solution_size == (int)p_mesh->GetNumNodes());

        // ...and if it is, store it as an initial guess for the PDE solver
        Vec initial_guess;
        if (is_previous_solution_size_correct)
        {
            // This Vec is copied by the solver's Solve() method, so must be deleted here too
            VecDuplicate(p_pde_and_bc->GetSolution(), &initial_guess);
            VecCopy(p_pde_and_bc->GetSolution(), initial_guess);
            p_pde_and_bc->DestroySolution();
        }
        else
        {
            ///\todo enable the coarse PDE mesh to change size, e.g. for a growing domain (#630/#1891)
            if (!using_coarse_pde_mesh && p_pde_and_bc->GetSolution())
            {
                assert(previous_solution_size != 0);
                p_pde_and_bc->DestroySolution();
            }
        }

        // Create a PDE solver and solve the PDE on the (population-level or coarse) mesh
        if (p_pde_and_bc->HasAveragedSourcePde())
        {
            // When using a coarse PDE mesh, we must set up the source terms before solving the PDE.
            // Pass in mCellPdeElementMap to speed up finding cells.
            this->UpdateCellPdeElementMap();
            p_pde_and_bc->SetUpSourceTermsForAveragedSourcePde(p_mesh, &mCellPdeElementMap);


            SimpleLinearEllipticSolver<DIM,DIM> solver(p_mesh, p_pde_and_bc->GetPde(), p_bcc.get());

            // If we have an initial guess, use this when solving the system...
            if (is_previous_solution_size_correct)
            {
                p_pde_and_bc->SetSolution(solver.Solve(initial_guess));
                PetscTools::Destroy(initial_guess);
            }
            else // ...otherwise do not supply one
            {
                p_pde_and_bc->SetSolution(solver.Solve());
            }
        }
        else
        {
            CellBasedPdeSolver<DIM> solver(p_mesh, p_pde_and_bc->GetPde(), p_bcc.get());

            // If we have an initial guess, use this...
            if (is_previous_solution_size_correct)
            {
                p_pde_and_bc->SetSolution(solver.Solve(initial_guess));
                PetscTools::Destroy(initial_guess);
            }
            else // ...otherwise do not supply one
            {
                p_pde_and_bc->SetSolution(solver.Solve());
            }
        }

        // Store the PDE solution in an accessible form
        ReplicatableVector solution_repl(p_pde_and_bc->GetSolution());

        // Having solved the PDE, now update CellData
        for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = mpCellPopulation->Begin();
             cell_iter != mpCellPopulation->End();
             ++cell_iter)
        {
            unsigned node_index = mpCellPopulation->GetLocationIndexUsingCell(*cell_iter);
            double solution_at_node = 0.0;

            if (using_coarse_pde_mesh)
            {
                // When using a coarse PDE mesh, the cells are not nodes of the mesh, so we must interpolate

                // Find the element in the coarse mesh that contains this cell. CellElementMap has been updated so use this.
                unsigned elem_index = mCellPdeElementMap[*cell_iter];
                Element<DIM,DIM>* p_element = mpCoarsePdeMesh->GetElement(elem_index);

                const ChastePoint<DIM>& node_location = mpCellPopulation->GetLocationOfCellCentre(*cell_iter);

                c_vector<double,DIM+1> weights = p_element->CalculateInterpolationWeights(node_location);
                for (unsigned i=0; i<DIM+1; i++)
                {
                    double nodal_value = solution_repl[p_element->GetNodeGlobalIndex(i)];
                    solution_at_node += nodal_value * weights(i);
                }
            }
            else
            {
                solution_at_node = solution_repl[node_index];
            }
            cell_iter->GetCellData()->SetItem(mPdeAndBcCollection[pde_index]->rGetDependentVariableName(), solution_at_node);
        }
    }

    // Write results to file if required
    SimulationTime* p_time = SimulationTime::Instance();
    if ((p_time->GetTimeStepsElapsed())%samplingTimestepMultiple == 0)
    {
        WritePdeSolution(p_time->GetTime());
    }
#define COVERAGE_IGNORE
    ///\todo enable this in the case where a coarse PDE mesh is used
    if (!using_coarse_pde_mesh)
    {
        if (mWriteDailyAverageRadialPdeSolution)
        {
            ///\todo Worry about round-off errors (#1891)
            p_time = SimulationTime::Instance();
            unsigned num_timesteps_per_day = (unsigned) (DBL_EPSILON + 24/SimulationTime::Instance()->GetTimeStep());
            if ((p_time->GetTimeStepsElapsed()) % num_timesteps_per_day == 0)
            {
                WriteAverageRadialPdeSolution(p_time->GetTime());
            }
        }
    }
#undef COVERAGE_IGNORE
}
void NodeBasedCellPopulationWithParticles<DIM>::WriteVtkResultsToFile(const std::string& rDirectory)
{
#ifdef CHASTE_VTK
    // Store the present time as a string
    std::stringstream time;
    time << SimulationTime::Instance()->GetTimeStepsElapsed();

    // Make sure the nodes are ordered contiguously in memory
    NodeMap map(1 + this->mpNodesOnlyMesh->GetMaximumNodeIndex());
    this->mpNodesOnlyMesh->ReMesh(map);

    // Store the number of cells for which to output data to VTK
    unsigned num_nodes = this->GetNumNodes();
    std::vector<double> rank(num_nodes);
    std::vector<double> particles(num_nodes);

    unsigned num_cell_data_items = 0;
    std::vector<std::string> cell_data_names;

    // We assume that the first cell is representative of all cells
    if (num_nodes > 0)
    {
        num_cell_data_items = this->Begin()->GetCellData()->GetNumItems();
        cell_data_names = this->Begin()->GetCellData()->GetKeys();
    }

    std::vector<std::vector<double> > cell_data;
    for (unsigned var=0; var<num_cell_data_items; var++)
    {
        std::vector<double> cell_data_var(num_nodes);
        cell_data.push_back(cell_data_var);
    }

    // Create mesh writer for VTK output
    VtkMeshWriter<DIM, DIM> mesh_writer(rDirectory, "results_"+time.str(), false);
    mesh_writer.SetParallelFiles(*(this->mpNodesOnlyMesh));

    // Iterate over any cell writers that are present
    for (typename std::vector<boost::shared_ptr<AbstractCellWriter<DIM, DIM> > >::iterator cell_writer_iter = this->mCellWriters.begin();
         cell_writer_iter != this->mCellWriters.end();
         ++cell_writer_iter)
    {
        // Create vector to store VTK cell data
        std::vector<double> vtk_cell_data(num_nodes);

        // Loop over nodes
        for (typename AbstractMesh<DIM,DIM>::NodeIterator node_iter = this->mrMesh.GetNodeIteratorBegin();
             node_iter != this->mrMesh.GetNodeIteratorEnd();
             ++node_iter)
        {
            unsigned node_index = node_iter->GetIndex();

            // If this node is a particle (not a cell), then we set the 'dummy' VTK cell data for this to be -2.0...
            if (this->IsParticle(node_index))
            {
                vtk_cell_data[node_index] = -2.0;
            }
            else
            {
                // ...otherwise we populate the vector of VTK cell data as usual
                CellPtr p_cell = this->GetCellUsingLocationIndex(node_index);
                vtk_cell_data[node_index] = (*cell_writer_iter)->GetCellDataForVtkOutput(p_cell, this);
            }
        }

        mesh_writer.AddPointData((*cell_writer_iter)->GetVtkCellDataName(), vtk_cell_data);
    }

    // Loop over cells
    for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = this->Begin();
         cell_iter != this->End();
         ++cell_iter)
    {
        // Get the node index corresponding to this cell
        unsigned global_index = this->GetLocationIndexUsingCell(*cell_iter);
        unsigned node_index = this->rGetMesh().SolveNodeMapping(global_index);

        for (unsigned var=0; var<num_cell_data_items; var++)
        {
            cell_data[var][node_index] = cell_iter->GetCellData()->GetItem(cell_data_names[var]);
        }

        rank[node_index] = (PetscTools::GetMyRank());
    }

    mesh_writer.AddPointData("Process rank", rank);

    // Loop over nodes
    for (typename AbstractMesh<DIM,DIM>::NodeIterator node_iter = this->mrMesh.GetNodeIteratorBegin();
         node_iter != this->mrMesh.GetNodeIteratorEnd();
         ++node_iter)
    {
        unsigned node_index = node_iter->GetIndex();
        particles[node_index] = (double) (this->IsParticle(node_index));
    }

    mesh_writer.AddPointData("Non-particles", particles);

    if (num_cell_data_items > 0)
    {
        for (unsigned var=0; var<cell_data.size(); var++)
        {
            mesh_writer.AddPointData(cell_data_names[var], cell_data[var]);
        }
    }

    mesh_writer.WriteFilesUsingMesh(*(this->mpNodesOnlyMesh));

    *(this->mpVtkMetaFile) << "        <DataSet timestep=\"";
    *(this->mpVtkMetaFile) << SimulationTime::Instance()->GetTimeStepsElapsed();
    *(this->mpVtkMetaFile) << "\" group=\"\" part=\"0\" file=\"results_";
    *(this->mpVtkMetaFile) << SimulationTime::Instance()->GetTimeStepsElapsed();
    EXCEPT_IF_NOT(PetscTools::IsSequential());
    {
        *(this->mpVtkMetaFile) << ".vtu\"/>\n";
    }
/*    {
        // Parallel vtu files  .vtu -> .pvtu
        *(this->mpVtkMetaFile) << ".pvtu\"/>\n";
    }*/
#endif //CHASTE_VTK
}
예제 #18
0
void NodeBasedCellPopulation<DIM>::WriteVtkResultsToFile(const std::string& rDirectory)
{
#ifdef CHASTE_VTK
    std::stringstream time;
    time << SimulationTime::Instance()->GetTimeStepsElapsed();
    VtkMeshWriter<DIM, DIM> mesh_writer(rDirectory, "results_"+time.str(), false);

    // Make sure the nodes are ordered contiguously in memory.
    NodeMap map(1 + this->mpNodesOnlyMesh->GetMaximumNodeIndex());
    this->mpNodesOnlyMesh->ReMesh(map);

    mesh_writer.SetParallelFiles(*mpNodesOnlyMesh);

    unsigned num_nodes = GetNumNodes();
    std::vector<double> cell_types(num_nodes);
    std::vector<double> cell_ancestors(num_nodes);
    std::vector<double> cell_mutation_states(num_nodes);
    std::vector<double> cell_ages(num_nodes);
    std::vector<double> cell_cycle_phases(num_nodes);
    std::vector<double> cell_radii(num_nodes);
    std::vector<std::vector<double> > cellwise_data;
    std::vector<double> rank(num_nodes);

    unsigned num_cell_data_items = 0;
    std::vector<std::string> cell_data_names;

    // We assume that the first cell is representative of all cells
    if (num_nodes > 0)
    {
        num_cell_data_items = this->Begin()->GetCellData()->GetNumItems();
        cell_data_names = this->Begin()->GetCellData()->GetKeys();
    }

    for (unsigned var=0; var<num_cell_data_items; var++)
    {
        std::vector<double> cellwise_data_var(num_nodes);
        cellwise_data.push_back(cellwise_data_var);
    }

    // Loop over cells
    for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = this->Begin();
         cell_iter != this->End();
         ++cell_iter)
    {
        // Get the node index corresponding to this cell
        unsigned global_index = this->GetLocationIndexUsingCell(*cell_iter);

        Node<DIM>* p_node = this->GetNode(global_index);

        unsigned node_index = this->rGetMesh().SolveNodeMapping(global_index);

        if (this-> template HasWriter<CellAncestorWriter>())
        {
            double ancestor_index = (cell_iter->GetAncestor() == UNSIGNED_UNSET) ? (-1.0) : (double)cell_iter->GetAncestor();
            cell_ancestors[node_index] = ancestor_index;
        }
        if (this-> template HasWriter<CellProliferativeTypesWriter>())
        {
            double cell_type = cell_iter->GetCellProliferativeType()->GetColour();
            cell_types[node_index] = cell_type;
        }
        if (this-> template HasWriter<CellMutationStatesCountWriter>())
        {
            double mutation_state = cell_iter->GetMutationState()->GetColour();

            CellPropertyCollection collection = cell_iter->rGetCellPropertyCollection();
            CellPropertyCollection label_collection = collection.GetProperties<CellLabel>();

            if (label_collection.GetSize() == 1)
            {
                boost::shared_ptr<CellLabel> p_label = boost::static_pointer_cast<CellLabel>(label_collection.GetProperty());
                mutation_state = p_label->GetColour();
            }

            cell_mutation_states[node_index] = mutation_state;
        }
        if (this-> template HasWriter<CellAgesWriter>())
        {
            double age = cell_iter->GetAge();
            cell_ages[node_index] = age;
        }
        if (this-> template HasWriter<CellProliferativePhasesWriter>())
        {
            double cycle_phase = cell_iter->GetCellCycleModel()->GetCurrentCellCyclePhase();
            cell_cycle_phases[node_index] = cycle_phase;
        }
        if (this-> template HasWriter<CellVolumesWriter>())
        {
            double cell_radius = p_node->GetRadius();
            cell_radii[node_index] = cell_radius;
        }

        for (unsigned var=0; var<num_cell_data_items; var++)
        {
            cellwise_data[var][node_index] = cell_iter->GetCellData()->GetItem(cell_data_names[var]);
        }

        rank[node_index] = (PetscTools::GetMyRank());
    }

    mesh_writer.AddPointData("Process rank", rank);

    if (this-> template HasWriter<CellProliferativeTypesWriter>())
    {
        mesh_writer.AddPointData("Cell types", cell_types);
    }
    if (this-> template HasWriter<CellAncestorWriter>())
    {
        mesh_writer.AddPointData("Ancestors", cell_ancestors);
    }
    if (this-> template HasWriter<CellMutationStatesCountWriter>())
    {
        mesh_writer.AddPointData("Mutation states", cell_mutation_states);
    }
    if (this-> template HasWriter<CellAgesWriter>())
    {
        mesh_writer.AddPointData("Ages", cell_ages);
    }
    if (this-> template HasWriter<CellProliferativePhasesWriter>())
    {
        mesh_writer.AddPointData("Cycle phases", cell_cycle_phases);
    }
    if (this-> template HasWriter<CellVolumesWriter>())
    {
        mesh_writer.AddPointData("Cell radii", cell_radii);
    }
    if (num_cell_data_items > 0)
    {
        for (unsigned var=0; var<cellwise_data.size(); var++)
        {
            mesh_writer.AddPointData(cell_data_names[var], cellwise_data[var]);
        }
    }

    mesh_writer.WriteFilesUsingMesh(*mpNodesOnlyMesh);

    *(this->mpVtkMetaFile) << "        <DataSet timestep=\"";
    *(this->mpVtkMetaFile) << SimulationTime::Instance()->GetTimeStepsElapsed();
    *(this->mpVtkMetaFile) << "\" group=\"\" part=\"0\" file=\"results_";
    *(this->mpVtkMetaFile) << SimulationTime::Instance()->GetTimeStepsElapsed();
    *(this->mpVtkMetaFile) << ".vtu\"/>\n";
#endif //CHASTE_VTK
}
unsigned AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::DoCellBirth()
{
    if (mNoBirth)
    {
        return 0;
    }

    unsigned num_births_this_step = 0;

    // Iterate over all cells, seeing if each one can be divided
    for (typename AbstractCellPopulation<ELEMENT_DIM,SPACE_DIM>::Iterator cell_iter = mrCellPopulation.Begin();
         cell_iter != mrCellPopulation.End();
         ++cell_iter)
    {
        // Check if this cell is ready to divide
        double cell_age = cell_iter->GetAge();
        if (cell_age > 0.0)
        {
            if (cell_iter->ReadyToDivide())
            {
                // Check if there is room into which the cell may divide
                if (mrCellPopulation.IsRoomToDivide(*cell_iter))
                {
                    // Create a new cell
                    CellPtr p_new_cell = cell_iter->Divide();

                    // Call method that determines how cell division occurs and returns a vector
                    c_vector<double, SPACE_DIM> new_location = CalculateCellDivisionVector(*cell_iter);

                    // If required, output this location to file
                    /**
                     * \todo (#2441)
                     *
                     * For consistency with the rest of the output code, consider removing the
                     * AbstractCellBasedSimulation member mOutputDivisionLocations, adding a new
                     * member mAgesAndLocationsOfDividingCells to AbstractCellPopulation, adding
                     * a new class CellDivisionLocationsWriter to the CellPopulationWriter hierarchy
                     * to output the content of mAgesAndLocationsOfDividingCells to file (remembering
                     * to clear mAgesAndLocationsOfDividingCells at each timestep), and replacing the
                     * following conditional statement with something like
                     *
                     * if (mrCellPopulation.HasWriter<CellDivisionLocationsWriter>())
                     * {
                     *     mCellDivisionLocations.push_back(new_location);
                     * }
                     */
                    if (mOutputDivisionLocations)
                    {
                        *mpDivisionLocationFile << SimulationTime::Instance()->GetTime() << "\t";
                        for (unsigned i=0; i<SPACE_DIM; i++)
                        {
                            *mpDivisionLocationFile << new_location[i] << "\t";
                        }
                        *mpDivisionLocationFile << "\t" << cell_age << "\n";
                    }

                    // Add new cell to the cell population
                    mrCellPopulation.AddCell(p_new_cell, new_location, *cell_iter);

                    // Update counter
                    num_births_this_step++;
                }
            }
        }
    }
    return num_births_this_step;
}
void AbstractCellBasedSimulation<ELEMENT_DIM,SPACE_DIM>::Solve()
{
    CellBasedEventHandler::BeginEvent(CellBasedEventHandler::EVERYTHING);
    CellBasedEventHandler::BeginEvent(CellBasedEventHandler::SETUP);

    // Set up the simulation time
    SimulationTime* p_simulation_time = SimulationTime::Instance();
    double current_time = p_simulation_time->GetTime();

    assert(mDt != DOUBLE_UNSET);  //Subclass constructors take care of this

    if (mEndTime == DOUBLE_UNSET)
    {
        EXCEPTION("SetEndTime has not yet been called.");
    }

    /*
     * Note that mDt is used here for "ideal time step". If this step doesn't divide the time remaining
     * then a *different* time step will be taken by the time-stepper. The real time-step (used in the
     * SimulationTime singleton) is currently not available to this class.
     *
     * \todo Should we over-write the value of mDt, or change this behaviour? (see #2159)
     */
    unsigned num_time_steps = (unsigned) ((mEndTime-current_time)/mDt+0.5);
    if (current_time > 0) // use the reset function if necessary
    {
        p_simulation_time->ResetEndTimeAndNumberOfTimeSteps(mEndTime, num_time_steps);
    }
    else
    {
        if (p_simulation_time->IsEndTimeAndNumberOfTimeStepsSetUp())
        {
            EXCEPTION("End time and number of timesteps already setup. You should not use SimulationTime::SetEndTimeAndNumberOfTimeSteps in cell-based tests.");
        }
        else
        {
            p_simulation_time->SetEndTimeAndNumberOfTimeSteps(mEndTime, num_time_steps);
        }
    }

    if (mOutputDirectory == "")
    {
        EXCEPTION("OutputDirectory not set");
    }

    double time_now = p_simulation_time->GetTime();
    std::ostringstream time_string;
    time_string << time_now;

    std::string results_directory = mOutputDirectory +"/results_from_time_" + time_string.str();
    mSimulationOutputDirectory = results_directory;

    // Set up simulation

    // Create output files for the visualizer
    OutputFileHandler output_file_handler(results_directory+"/", true);

    mrCellPopulation.OpenWritersFiles(results_directory+"/");

    if (mOutputDivisionLocations)
    {
        mpDivisionLocationFile = output_file_handler.OpenOutputFile("divisions.dat");
    }

    if (PetscTools::AmMaster())
    {
        mpVizSetupFile = output_file_handler.OpenOutputFile("results.vizsetup");
    }

    // If any PDEs have been defined, set up results files to store their solution
    if (mpCellBasedPdeHandler != NULL)
    {
        mpCellBasedPdeHandler->OpenResultsFiles(this->mSimulationOutputDirectory);
        if (PetscTools::AmMaster())
        {
            *this->mpVizSetupFile << "PDE \n";
        }

        /*
         * If any PDEs have been defined, solve them here before updating cells and store
         * their solution in results files. This also initializes the relevant CellData.
         * NOTE that this works as the PDEs are elliptic.
         */
        CellBasedEventHandler::BeginEvent(CellBasedEventHandler::PDE);
        mpCellBasedPdeHandler->SolvePdeAndWriteResultsToFile(this->mSamplingTimestepMultiple);
        CellBasedEventHandler::EndEvent(CellBasedEventHandler::PDE);
    }

    SetupSolve();

    // Call SetupSolve() on each modifier
    for (typename std::vector<boost::shared_ptr<AbstractCellBasedSimulationModifier<ELEMENT_DIM, SPACE_DIM> > >::iterator iter = mSimulationModifiers.begin();
         iter != mSimulationModifiers.end();
         ++iter)
    {
        (*iter)->SetupSolve(this->mrCellPopulation,this->mSimulationOutputDirectory);
    }

    /*
     * Age the cells to the correct time. Note that cells are created with
     * negative birth times so that some are initially almost ready to divide.
     */
    LOG(1, "Setting up cells...");
    for (typename AbstractCellPopulation<ELEMENT_DIM,SPACE_DIM>::Iterator cell_iter = mrCellPopulation.Begin();
         cell_iter != mrCellPopulation.End();
         ++cell_iter)
    {
        /*
         * We don't use the result; this call is just to force the cells to age
         * to the current time running their cell-cycle models to get there.
         */
        cell_iter->ReadyToDivide();
    }
    LOG(1, "\tdone\n");

    // Write initial conditions to file for the visualizer
    WriteVisualizerSetupFile();

    if (PetscTools::AmMaster())
    {
        *mpVizSetupFile << std::flush;
    }

    mrCellPopulation.WriteResultsToFiles(results_directory+"/");

    OutputSimulationSetup();
    CellBasedEventHandler::EndEvent(CellBasedEventHandler::SETUP);

    // Enter main time loop
    while (!( p_simulation_time->IsFinished() || StoppingEventHasOccurred() ) )
    {
        LOG(1, "--TIME = " << p_simulation_time->GetTime() << "\n");

        // This function calls DoCellRemoval(), DoCellBirth() and CellPopulation::Update()
        UpdateCellPopulation();

        // Update cell locations and topology
        UpdateCellLocationsAndTopology();

        // Update the assignment of cells to processes.
        mrCellPopulation.UpdateCellProcessLocation();

        // Increment simulation time here, so results files look sensible
        p_simulation_time->IncrementTimeOneStep();

        // If any PDEs have been defined, solve them and store their solution in results files
        if (mpCellBasedPdeHandler != NULL)
        {
            CellBasedEventHandler::BeginEvent(CellBasedEventHandler::PDE);
            mpCellBasedPdeHandler->SolvePdeAndWriteResultsToFile(this->mSamplingTimestepMultiple);
            CellBasedEventHandler::EndEvent(CellBasedEventHandler::PDE);
        }

        // Call UpdateAtEndOfTimeStep(), which may be implemented by child classes
        CellBasedEventHandler::BeginEvent(CellBasedEventHandler::UPDATESIMULATION);
        UpdateAtEndOfTimeStep();

        // Call UpdateAtEndOfTimeStep() on each modifier
        for (typename std::vector<boost::shared_ptr<AbstractCellBasedSimulationModifier<ELEMENT_DIM, SPACE_DIM> > >::iterator iter = mSimulationModifiers.begin();
             iter != mSimulationModifiers.end();
             ++iter)
        {
            (*iter)->UpdateAtEndOfTimeStep(this->mrCellPopulation);
        }
        CellBasedEventHandler::EndEvent(CellBasedEventHandler::UPDATESIMULATION);

        // Output current results to file
        CellBasedEventHandler::BeginEvent(CellBasedEventHandler::OUTPUT);
        if (p_simulation_time->GetTimeStepsElapsed()%mSamplingTimestepMultiple == 0)
        {
            mrCellPopulation.WriteResultsToFiles(results_directory+"/");

            // Call UpdateAtEndOfOutputTimeStep() on each modifier
            for (typename std::vector<boost::shared_ptr<AbstractCellBasedSimulationModifier<ELEMENT_DIM, SPACE_DIM> > >::iterator iter = mSimulationModifiers.begin();
                 iter != mSimulationModifiers.end();
                 ++iter)
            {
                (*iter)->UpdateAtEndOfOutputTimeStep(this->mrCellPopulation);
            }
        }
        CellBasedEventHandler::EndEvent(CellBasedEventHandler::OUTPUT);
    }

    LOG(1, "--END TIME = " << p_simulation_time->GetTime() << "\n");

    /*
     * Carry out a final update so that cell population is coherent with new cell positions.
     * Note that cell birth and death still need to be checked because they may be spatially
     * dependent.
     */
    UpdateCellPopulation();

    // If any PDEs have been defined, close the results files storing their solution
    if (mpCellBasedPdeHandler != NULL)
    {
        mpCellBasedPdeHandler->CloseResultsFiles();
    }

    CellBasedEventHandler::BeginEvent(CellBasedEventHandler::UPDATESIMULATION);
    UpdateAtEndOfSolve();

    // Call UpdateAtEndOfSolve(), on each modifier
    for (typename std::vector<boost::shared_ptr<AbstractCellBasedSimulationModifier<ELEMENT_DIM, SPACE_DIM> > >::iterator iter = mSimulationModifiers.begin();
         iter != mSimulationModifiers.end();
         ++iter)
    {
        (*iter)->UpdateAtEndOfSolve(this->mrCellPopulation);
    }
    CellBasedEventHandler::EndEvent(CellBasedEventHandler::UPDATESIMULATION);

    CellBasedEventHandler::BeginEvent(CellBasedEventHandler::OUTPUT);

    mrCellPopulation.CloseOutputFiles();

    if (mOutputDivisionLocations)
    {
        mpDivisionLocationFile->close();
    }

    if (PetscTools::AmMaster())
    {
        *mpVizSetupFile << "Complete\n";
        mpVizSetupFile->close();
    }

    CellBasedEventHandler::EndEvent(CellBasedEventHandler::OUTPUT);
    CellBasedEventHandler::EndEvent(CellBasedEventHandler::EVERYTHING);
}
void GonadArmMovingBoundaryCondition<DIM>::ImposeBoundaryCondition(const std::map<Node<DIM>*, c_vector<double, DIM> >& rOldLocations)
{

    // Iterate over the cell population and get cell location
    for (typename AbstractCellPopulation<DIM>::Iterator cell_iter = this->mpCellPopulation->Begin();
         cell_iter != this->mpCellPopulation->End();
         ++cell_iter)
    {
    	 c_vector<double,DIM> cell_location = this->mpCellPopulation->GetLocationOfCellCentre(*cell_iter);
    	 Node<DIM>* cell_centre_node = this->mpCellPopulation->GetNode(this->mpCellPopulation->GetLocationIndexUsingCell(*cell_iter));
    	 double radius = cell_centre_node->GetRadius();

    	 // Find C, the closest point on the growth path for this cell, and R the distance to it.
        double R=0;
        c_vector<double, DIM> C= zero_vector<double>(3);

        //If all three parts of the path exist, measure distances to the lower+upper straights and the loop
        if(mCurrentLength>mStraightLengthLower+PI*mTurnRadius){
        	//Find min distance to each of the three parts of the path
        	double R1=0; double R2=0; double R3=0;
        	c_vector<double, DIM> C1=zero_vector<double>(3);
        	c_vector<double, DIM> C2=zero_vector<double>(3);
        	c_vector<double, DIM> C3=zero_vector<double>(3);
        	GetClosestOnLowerStraight(C1,cell_location,R1);
        	GetClosestOnLoop(C2,cell_location,R2);
        	GetClosestOnUpperStraight(C3,cell_location,R3);
        	//Take min and record closest point
        	R=std::min(R1,std::min(R2,R3));
        	if(R==R1){
        		C=C1;
        	}else if(R==R2){
        		C=C2;
        	}else{
        		C=C3;
        	}
        }else if(mCurrentLength>mStraightLengthLower && mCurrentLength<=mStraightLengthLower+PI*mTurnRadius){
        	//If only the lower straight and the loop exist, similar process
        	double R1=0; double R2=0;
        	c_vector<double, DIM> C1=zero_vector<double>(3);
        	c_vector<double, DIM> C2=zero_vector<double>(3);
        	GetClosestOnLowerStraight(C1,cell_location,R1);
        	GetClosestOnLoop(C2,cell_location,R2);
        	R=std::min(R1,R2);
        	if(R==R1){
        		C=C1;
        	}else{
        		C=C2;
        	}
        }else if(mCurrentLength<=mStraightLengthLower){
        	//Distance to the lower straight of the gonad arm
        	GetClosestOnLowerStraight(C,cell_location,R);
        }else{
        	NEVER_REACHED;
        }

        // If the cell is too far from the growth path, and therefore outside the tube...
        if (R+radius-mCurrentTubeRadius > mMaximumDistance)
        {
        	// ...move the cell back onto the surface of the tube by translating toward C:
            unsigned node_index = this->mpCellPopulation->GetLocationIndexUsingCell(*cell_iter);
            Node<DIM>* p_node = this->mpCellPopulation->GetNode(node_index);
            p_node->rGetModifiableLocation() = C+(mCurrentTubeRadius-radius)*(cell_location-C)/norm_2(cell_location-C);
        }

        /*Assuming all is now well, update the cell data to record how far along the gonad arm this cell is.
         * Use the vector C, which stores the closest point on the growth path to this cell.*/
        double distance;
        HowFarAlongAreYou(C,distance);
        cell_iter->GetCellData()->SetItem("DistanceAwayFromDTC", mCurrentLength-distance);
    }
}