NodeBasedTissue.cpp

00001 /*
00002 
00003 Copyright (C) University of Oxford, 2005-2010
00004 
00005 University of Oxford means the Chancellor, Masters and Scholars of the
00006 University of Oxford, having an administrative office at Wellington
00007 Square, Oxford OX1 2JD, UK.
00008 
00009 This file is part of Chaste.
00010 
00011 Chaste is free software: you can redistribute it and/or modify it
00012 under the terms of the GNU Lesser General Public License as published
00013 by the Free Software Foundation, either version 2.1 of the License, or
00014 (at your option) any later version.
00015 
00016 Chaste is distributed in the hope that it will be useful, but WITHOUT
00017 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
00019 License for more details. The offer of Chaste under the terms of the
00020 License is subject to the License being interpreted in accordance with
00021 English Law and subject to any action against the University of Oxford
00022 being under the jurisdiction of the English Courts.
00023 
00024 You should have received a copy of the GNU Lesser General Public License
00025 along with Chaste. If not, see <http://www.gnu.org/licenses/>.
00026 
00027 */
00028 #include "NodeBasedTissue.hpp"
00029 
00030 
00031 template<unsigned DIM>
00032 NodeBasedTissue<DIM>::NodeBasedTissue(const std::vector<Node<DIM>* > nodes,
00033                                       std::vector<TissueCell>& rCells,
00034                                       const std::vector<unsigned> locationIndices,
00035                                       bool deleteNodes)
00036     : AbstractCellCentreBasedTissue<DIM>(rCells, locationIndices),
00037       mNodes(nodes.begin(), nodes.end()),
00038       mAddedNodes(true),
00039       mpBoxCollection(NULL),
00040       mDeleteNodes(deleteNodes)
00041 {
00042     Validate();
00043 }
00044 
00045 // archiving constructor
00046 template<unsigned DIM>
00047 NodeBasedTissue<DIM>::NodeBasedTissue(const std::vector<Node<DIM>* > nodes, bool deleteNodes)
00048     : AbstractCellCentreBasedTissue<DIM>(),
00049       mNodes(nodes.begin(), nodes.end()),
00050       mAddedNodes(true),
00051       mpBoxCollection(NULL),
00052       mDeleteNodes(deleteNodes)
00053 {
00054     // No Validate() because the cells are not associated with the tissue yet in archiving
00055 }
00056 
00057 
00058 template<unsigned DIM>
00059 NodeBasedTissue<DIM>::NodeBasedTissue(const AbstractMesh<DIM,DIM>& rMesh,
00060                                       std::vector<TissueCell>& rCells)
00061     : AbstractCellCentreBasedTissue<DIM>(rCells),
00062       mAddedNodes(false),
00063       mpBoxCollection(NULL),
00064       mDeleteNodes(true)
00065 {
00066     mNodes.reserve(rMesh.GetNumNodes());
00067     // Copy the actual node objects from mesh to this (mesh-less) tissue.
00068     for (unsigned i=0; i<rMesh.GetNumNodes(); i++)
00069     {
00070         Node<DIM>* p_node = new Node<DIM>(*(rMesh.GetNode(i)));
00071         mNodes.push_back(p_node);
00072     }
00073     mAddedNodes = true;
00074     Validate();
00075 }
00076 
00077 template<unsigned DIM>
00078 NodeBasedTissue<DIM>::~NodeBasedTissue()
00079 {
00080     Clear();
00081 
00082     // Free node memory
00083     if (mDeleteNodes)
00084     {
00085         for (unsigned i=0; i<mNodes.size(); i++)
00086         {
00087             delete mNodes[i];
00088         }
00089     }
00090 }
00091 
00092 
00093 template<unsigned DIM>
00094 void NodeBasedTissue<DIM>::Clear()
00095 {
00096     delete mpBoxCollection;
00097     mpBoxCollection = NULL;
00098     mNodePairs.clear();
00099     mDeletedNodeIndices.clear();
00100     mAddedNodes = false;
00101 }
00102 
00103 
00104 template<unsigned DIM>
00105 void NodeBasedTissue<DIM>::Validate()
00106 {
00107     std::vector<bool> validated_node(GetNumNodes());
00108     for (unsigned i=0; i<validated_node.size(); i++)
00109     {
00110         validated_node[i] = false;
00111     }
00112 
00113     for (typename AbstractTissue<DIM>::Iterator cell_iter=this->Begin(); cell_iter!=this->End(); ++cell_iter)
00114     {
00115         unsigned node_index = this->mCellLocationMap[&(*cell_iter)];
00116         validated_node[node_index] = true;
00117     }
00118 
00119     for (unsigned i=0; i<validated_node.size(); i++)
00120     {
00121         if (!validated_node[i])
00122         {
00123             std::stringstream ss;
00124             ss << "Node " << i << " does not appear to have a cell associated with it";
00125             EXCEPTION(ss.str());
00126         }
00127     }
00128 }
00129 
00130 
00131 template<unsigned DIM>
00132 std::vector<Node<DIM>* >& NodeBasedTissue<DIM>::rGetNodes()
00133 {
00134     return mNodes;
00135 }
00136 
00137 
00138 template<unsigned DIM>
00139 const std::vector<Node<DIM>* >& NodeBasedTissue<DIM>::rGetNodes() const
00140 {
00141     return mNodes;
00142 }
00143 
00144 
00145 template<unsigned DIM>
00146 void NodeBasedTissue<DIM>::SplitUpIntoBoxes(double cutOffLength, c_vector<double, 2*DIM> domainSize)
00147 {
00148     mpBoxCollection = new BoxCollection<DIM>(cutOffLength, domainSize);
00149     mpBoxCollection->SetupLocalBoxesHalfOnly();
00150 
00151     for (unsigned i=0; i<mNodes.size(); i++)
00152     {
00153         unsigned box_index = mpBoxCollection->CalculateContainingBox(mNodes[i]);
00154         mpBoxCollection->rGetBox(box_index).AddNode(mNodes[i]);
00155     }
00156 }
00157 
00158 
00159 template<unsigned DIM>
00160 void NodeBasedTissue<DIM>::FindMaxAndMin()
00161 {
00162     c_vector<double, DIM> min_posn;
00163     c_vector<double, DIM> max_posn;
00164     for (unsigned i=0; i<DIM; i++)
00165     {
00166         min_posn(i) = DBL_MAX;
00167         max_posn(i) = -DBL_MAX;
00168     }
00169 
00170     for (unsigned i=0; i<mNodes.size(); i++)
00171     {
00172         for (unsigned j=0; j<DIM; j++)
00173         {
00174             if (this->GetNode(i)->rGetLocation()[j] > max_posn(j))
00175             {
00176                 max_posn(j) = this->GetNode(i)->rGetLocation()[j];
00177             }
00178             if (this->GetNode(i)->rGetLocation()[j] < min_posn(j))
00179             {
00180                 min_posn(j) = this->GetNode(i)->rGetLocation()[j];
00181             }
00182         }
00183     }
00184 
00185     for (unsigned i=0; i<DIM; i++)
00186     {
00187         assert(min_posn(i) != DBL_MAX);
00188         mMinSpatialPositions(i) = min_posn(i);
00189 
00190         assert(max_posn(i) != -DBL_MAX);
00191         mMaxSpatialPositions(i) = max_posn(i);
00192     }
00193 }
00194 
00195 
00196 template<unsigned DIM>
00197 Node<DIM>* NodeBasedTissue<DIM>::GetNode(unsigned index)
00198 {
00199     return mNodes[index];
00200 }
00201 
00202 
00203 template<unsigned DIM>
00204 void NodeBasedTissue<DIM>::SetNode(unsigned nodeIndex, ChastePoint<DIM>& rNewLocation)
00205 {
00206     mNodes[nodeIndex]->SetPoint(rNewLocation);
00207 }
00208 
00209 
00210 template<unsigned DIM>
00211 void NodeBasedTissue<DIM>::Update(bool hasHadBirthsOrDeaths)
00212 {
00213     if (hasHadBirthsOrDeaths)
00214     {
00215         // Create and reserve space for a temporary vector
00216         std::vector<Node<DIM>* > old_nodes;
00217         old_nodes.reserve(mNodes.size());
00218 
00219         // Store all non-deleted nodes in the temporary vector
00220         for (unsigned i=0; i<mNodes.size(); i++)
00221         {
00222             if ( !mNodes[i]->IsDeleted() )
00223             {
00224                 old_nodes.push_back(mNodes[i]);
00225             }
00226             else
00227             {
00228                 // Free node memory
00229                 delete mNodes[i];
00230             }
00231         }
00232 
00233         std::map<unsigned,TissueCell*> old_map = this->mLocationCellMap;
00234         mNodes.clear();
00235 
00236         // Clear maps
00237         this->mLocationCellMap.clear();
00238         this->mCellLocationMap.clear();
00239 
00240         // Update mNodes to new indices which go from 0 to NumNodes-1
00241         for (unsigned i=0; i<old_nodes.size(); i++)
00242         {
00243             // Get the living cell associated with the old node
00244             TissueCell* p_live_cell = old_map[old_nodes[i]->GetIndex()];
00245 
00246             // Set the node up
00247             mNodes.push_back(old_nodes[i]);
00248             mNodes[i]->SetIndex(i);
00249 
00250             // Set the maps up
00251             this->mLocationCellMap[i] = p_live_cell;
00252             this->mCellLocationMap[p_live_cell] = i;
00253         }
00254 
00255         // Remove current dead indices data
00256         Clear();
00257 
00258         Validate();
00259     }
00260 
00261     if (mpBoxCollection!=NULL)
00262     {
00263         delete mpBoxCollection;
00264     }
00265 
00266     FindMaxAndMin();
00267 
00268     // Something here to set up the domain size (max and min of each node position dimension)
00269     c_vector<double, 2*DIM> domain_size;
00270 
00271     for (unsigned i=0; i<DIM; i++)
00272     {
00273         domain_size(2*i) = mMinSpatialPositions(i);
00274         domain_size(2*i+1) = mMaxSpatialPositions(i);
00275     }
00276 
00277     double cut_off_length = TissueConfig::Instance()->GetMechanicsCutOffLength();
00278     if (cut_off_length==DBL_MAX)
00279     {
00280         std::string error =  std::string("NodeBasedTissue cannot create boxes if the cut-off length has not been set - ")
00281                            + std::string("Call UseCutoffPoint() on the force law, or SetMechanicsCutOffLength on TissueConfig");
00282         EXCEPTION(error);
00283     }
00284 
00285     // Add this parameter and suggest that mechanics systems set it.
00286     // Allocates memory for mpBoxCollection and does the splitting and putting nodes into boxes
00287     SplitUpIntoBoxes(TissueConfig::Instance()->GetMechanicsCutOffLength(), domain_size);
00288 
00289     mpBoxCollection->CalculateNodePairs(mNodes, mNodePairs);
00290 
00291     //assert(mNodePairs.size() > 0); // should be possible to have nodes with no connections
00292 }
00293 
00294 
00295 template<unsigned DIM>
00296 unsigned NodeBasedTissue<DIM>::RemoveDeadCells()
00297 {
00298     unsigned num_removed = 0;
00299 
00300     for (std::list<TissueCell>::iterator cell_iter = this->mCells.begin();
00301          cell_iter != this->mCells.end();
00302          ++cell_iter)
00303     {
00304         if (cell_iter->IsDead())
00305         {
00306             // Remove the node
00307             num_removed++;
00308             this->GetNodeCorrespondingToCell(*cell_iter)->MarkAsDeleted();
00309             mDeletedNodeIndices.push_back( this->mCellLocationMap[&(*cell_iter)] );
00310             cell_iter = this->mCells.erase(cell_iter);
00311             --cell_iter;
00312         }
00313     }
00314     return num_removed;
00315 }
00316 
00317 
00318 template<unsigned DIM>
00319 unsigned NodeBasedTissue<DIM>::AddNode(Node<DIM>* pNewNode)
00320 {
00321     if (mDeletedNodeIndices.empty())
00322     {
00323         pNewNode->SetIndex(mNodes.size());
00324         mNodes.push_back(pNewNode);
00325     }
00326     else
00327     {
00328         unsigned index = mDeletedNodeIndices.back();
00329         pNewNode->SetIndex(index);
00330         mDeletedNodeIndices.pop_back();
00331         delete mNodes[index];
00332         mNodes[index] = pNewNode;
00333     }
00334     mAddedNodes = true;
00335     return pNewNode->GetIndex();
00336 }
00337 
00338 
00339 template<unsigned DIM>
00340 unsigned NodeBasedTissue<DIM>::GetNumNodes()
00341 {
00342     return mNodes.size() - mDeletedNodeIndices.size();
00343 }
00344 
00345 
00346 template<unsigned DIM>
00347 BoxCollection<DIM>* NodeBasedTissue<DIM>::GetBoxCollection()
00348 {
00349     return mpBoxCollection;
00350 }
00351 
00352 
00353 template<unsigned DIM>
00354 std::set< std::pair<Node<DIM>*, Node<DIM>* > >& NodeBasedTissue<DIM>::rGetNodePairs()
00355 {
00356     if (mNodePairs.size()==0)
00357     {
00358         EXCEPTION("No node pairs set up, rGetNodePairs probably called before Update");
00359     }
00360     return mNodePairs;
00361 }
00362 
00363 
00365 // Explicit instantiation
00367 
00368 template class NodeBasedTissue<1>;
00369 template class NodeBasedTissue<2>;
00370 template class NodeBasedTissue<3>;
00371 
00372 
00373 // Serialization for Boost >= 1.36
00374 #include "SerializationExportWrapperForCpp.hpp"
00375 EXPORT_TEMPLATE_CLASS_SAME_DIMS(NodeBasedTissue)

Generated by  doxygen 1.6.2