void NodeBasedCellPopulation<DIM>::UpdateMapsAfterRemesh(NodeMap& map) { if (!map.IsIdentityMap()) { UpdateParticlesAfterReMesh(map); // Update the mappings between cells and location indices ///\todo we want to make mCellLocationMap private - we need to find a better way of doing this std::map<Cell*, unsigned> old_map = this->mCellLocationMap; // Remove any dead pointers from the maps (needed to avoid archiving errors) this->mLocationCellMap.clear(); this->mCellLocationMap.clear(); for (std::list<CellPtr>::iterator it = this->mCells.begin(); it != this->mCells.end(); ++it) { unsigned old_node_index = old_map[(*it).get()]; // This shouldn't ever happen, as the cell vector only contains living cells assert(!map.IsDeleted(old_node_index)); unsigned new_node_index = map.GetNewIndex(old_node_index); this->SetCellUsingLocationIndex(new_node_index,*it); } this->Validate(); } }
void MeshBasedCellPopulationWithGhostNodes<DIM>::UpdateGhostNodesAfterReMesh(NodeMap& rMap) { // Copy mIsGhostNode to a temporary vector std::vector<bool> ghost_nodes_before_remesh = mIsGhostNode; // Reinitialise mIsGhostNode mIsGhostNode.clear(); mIsGhostNode.resize(this->GetNumNodes()); // Update mIsGhostNode using the node map for (unsigned old_index=0; old_index<rMap.GetSize(); old_index++) { if (!rMap.IsDeleted(old_index)) { unsigned new_index = rMap.GetNewIndex(old_index); mIsGhostNode[new_index] = ghost_nodes_before_remesh[old_index]; } } }
void Cylindrical2dMesh::ReMesh(NodeMap& rMap) { unsigned old_num_all_nodes = GetNumAllNodes(); rMap.Resize(old_num_all_nodes); rMap.ResetToIdentity(); // Flag the deleted nodes as deleted in the map for (unsigned i=0; i<old_num_all_nodes; i++) { if (mNodes[i]->IsDeleted()) { rMap.SetDeleted(i); } } CreateHaloNodes(); // Create mirrored nodes for the normal remesher to work with CreateMirrorNodes(); /* * The mesh now has messed up boundary elements, but this * doesn't matter as the ReMesh() below doesn't read them in * and reconstructs the boundary elements. * * Call ReMesh() on the parent class. Note that the mesh now has lots * of extra nodes which will be deleted, hence the name 'big_map'. */ NodeMap big_map(GetNumAllNodes()); MutableMesh<2,2>::ReMesh(big_map); /* * If the big_map isn't the identity map, the little map ('map') needs to be * altered accordingly before being passed to the user. Not sure how this all * works, so deal with this bridge when we get to it. */ assert(big_map.IsIdentityMap()); // Re-index the vectors according to the big nodemap, and set up the maps. mImageToLeftOriginalNodeMap.clear(); mImageToRightOriginalNodeMap.clear(); assert(mLeftOriginals.size() == mLeftImages.size()); assert(mRightOriginals.size() == mRightImages.size()); for (unsigned i=0; i<mLeftOriginals.size(); i++) { mLeftOriginals[i] = big_map.GetNewIndex(mLeftOriginals[i]); mLeftImages[i] = big_map.GetNewIndex(mLeftImages[i]); mImageToLeftOriginalNodeMap[mLeftImages[i]] = mLeftOriginals[i]; } for (unsigned i=0; i<mRightOriginals.size(); i++) { mRightOriginals[i] = big_map.GetNewIndex(mRightOriginals[i]); mRightImages[i] = big_map.GetNewIndex(mRightImages[i]); mImageToRightOriginalNodeMap[mRightImages[i]] = mRightOriginals[i]; } for (unsigned i=0; i<mTopHaloNodes.size(); i++) { mTopHaloNodes[i] = big_map.GetNewIndex(mTopHaloNodes[i]); mBottomHaloNodes[i] = big_map.GetNewIndex(mBottomHaloNodes[i]); } /* * Check that elements crossing the periodic boundary have been meshed * in the same way at each side. */ CorrectNonPeriodicMesh(); /* * Take the double-sized mesh, with its new boundary elements, and * remove the relevant nodes, elements and boundary elements to leave * a proper periodic mesh. */ ReconstructCylindricalMesh(); DeleteHaloNodes(); /* * Create a random boundary element between two nodes of the first * element if it is not deleted. This is a temporary measure to get * around re-index crashing when there are no boundary elements. */ unsigned num_elements = GetNumAllElements(); bool boundary_element_made = false; unsigned elem_index = 0; while (elem_index<num_elements && !boundary_element_made) { Element<2,2>* p_element = GetElement(elem_index); if (!p_element->IsDeleted()) { boundary_element_made = true; std::vector<Node<2>*> nodes; nodes.push_back(p_element->GetNode(0)); nodes.push_back(p_element->GetNode(1)); BoundaryElement<1,2>* p_boundary_element = new BoundaryElement<1,2>(0, nodes); p_boundary_element->RegisterWithNodes(); mBoundaryElements.push_back(p_boundary_element); this->mBoundaryElementWeightedDirections.push_back(zero_vector<double>(2)); this->mBoundaryElementJacobianDeterminants.push_back(0.0); } elem_index++; } // Now call ReIndex() to remove the temporary nodes which are marked as deleted NodeMap reindex_map(GetNumAllNodes()); ReIndex(reindex_map); assert(!reindex_map.IsIdentityMap()); // maybe don't need this /* * Go through the reindex map and use it to populate the original NodeMap * (the one that is returned to the user). */ for (unsigned i=0; i<rMap.GetSize(); i++) // only going up to be size of map, not size of reindex_map { if (reindex_map.IsDeleted(i)) { /* * i < num_original_nodes and node is deleted, this should correspond to * a node that was labelled as before the remeshing, so should have already * been set as deleted in the map above. */ assert(rMap.IsDeleted(i)); } else { rMap.SetNewIndex(i, reindex_map.GetNewIndex(i)); } } // We can now clear the index vectors and maps; they are only used for remeshing mLeftOriginals.clear(); mLeftImages.clear(); mImageToLeftOriginalNodeMap.clear(); mRightOriginals.clear(); mRightImages.clear(); mImageToRightOriginalNodeMap.clear(); mLeftPeriodicBoundaryElementIndices.clear(); mRightPeriodicBoundaryElementIndices.clear(); }