//============================================================================== void ReferentialSkeleton::registerBodyNode(BodyNode* _bn) { std::unordered_map<const BodyNode*, IndexMap>::iterator it = mIndexMap.find(_bn); if( it == mIndexMap.end() ) { // Create an index map entry for this BodyNode, and only add the BodyNode's // index to it. IndexMap indexing; mBodyNodes.push_back(_bn); indexing.mBodyNodeIndex = mBodyNodes.size()-1; mIndexMap[_bn] = indexing; } else { IndexMap& indexing = it->second; if(INVALID_INDEX == indexing.mBodyNodeIndex) { mBodyNodes.push_back(_bn); indexing.mBodyNodeIndex = mBodyNodes.size()-1; } } updateCaches(); }
//============================================================================== void ReferentialSkeleton::registerJoint(Joint* _joint) { BodyNode* bn = _joint->getChildBodyNode(); std::unordered_map<const BodyNode*, IndexMap>::iterator it = mIndexMap.find(bn); if( it == mIndexMap.end() ) { // Create an index map entry for this Joint, and only add the Joint's index // to it IndexMap indexing; mJoints.push_back(_joint); indexing.mJointIndex = mJoints.size()-1; mIndexMap[bn] = indexing; } else { IndexMap& indexing = it->second; if(INVALID_INDEX == indexing.mJointIndex) { mJoints.push_back(_joint); indexing.mJointIndex = mJoints.size()-1; } } // Updating the caches isn't necessary after registering a joint right now, // but it might matter in the future, so it might be better to be safe than // sorry. updateCaches(); }
//============================================================================== void ReferentialSkeleton::unregisterBodyNode( BodyNode* _bn, bool _unregisterDofs) { if(nullptr == _bn) { dterr << "[ReferentialSkeleton::unregisterBodyNode] Attempting to " << "unregister a nullptr BodyNode. This is most likely a bug. Please " << "report this!\n"; assert(false); return; } std::unordered_map<const BodyNode*, IndexMap>::iterator it = mIndexMap.find(_bn); if( it == mIndexMap.end() ) { dterr << "[ReferentialSkeleton::unregisterBodyNode] Attempting to " << "unregister a BodyNode that is not referred to by this " << "ReferentialSkeleton. This is most likely a bug. Please report " << "this!\n"; assert(false); return; } IndexMap& indexing = it->second; std::size_t bnIndex = indexing.mBodyNodeIndex; mBodyNodes.erase(mBodyNodes.begin() + bnIndex); indexing.mBodyNodeIndex = INVALID_INDEX; for(std::size_t i=bnIndex; i < mBodyNodes.size(); ++i) { // Re-index all the BodyNodes in this ReferentialSkeleton which came after // the one that was removed. IndexMap& alteredIndexing = mIndexMap[mBodyNodes[i]]; alteredIndexing.mBodyNodeIndex = i; } if(_unregisterDofs) { for(std::size_t i=0; i < indexing.mDofIndices.size(); ++i) { if(indexing.mDofIndices[i] != INVALID_INDEX) unregisterDegreeOfFreedom(_bn, i); } } if(indexing.isExpired()) mIndexMap.erase(it); updateCaches(); }
void Console::show() { if (_visible) return; if (_neverShown) _console->print("Type 'exit' to return to the game. Type 'help' for a list of commands."); _console->show(); _visible = true; _neverShown = false; updateCaches(); showCallback(); }
//============================================================================== void ReferentialSkeleton::unregisterJoint(BodyNode* _child) { if(nullptr == _child) { dterr << "[ReferentialSkeleton::unregisterJoint] Attempting to unregister " << "a Joint from a nullptr BodyNode. This is most likely a bug. " << "Please report this!\n"; assert(false); return; } Joint* joint = _child->getParentJoint(); std::unordered_map<const BodyNode*, IndexMap>::iterator it = mIndexMap.find(_child); if( it == mIndexMap.end() || INVALID_INDEX == it->second.mJointIndex) { dterr << "[ReferentialSkeleton::unregisterJoint] Attempting to unregister " << "a Joint named [" << joint->getName() << "] (" << joint << "), " << "which is the parent Joint of BodyNode [" << _child->getName() << "] (" << _child << "), but the Joint is not currently in this " << "ReferentialSkeleton! This is most likely a bug. Please report " << "this!\n"; assert(false); return; } std::size_t jointIndex = it->second.mJointIndex; mJoints.erase(mJoints.begin() + jointIndex); it->second.mJointIndex = INVALID_INDEX; for(std::size_t i = jointIndex; i < mJoints.size(); ++i) { // Re-index all of the Joints in this ReferentialSkeleton which came after // the Joint that was removed. JointPtr alteredJoint = mJoints[i]; IndexMap& indexing = mIndexMap[alteredJoint.getBodyNodePtr()]; indexing.mJointIndex = i; } if(it->second.isExpired()) mIndexMap.erase(it); // Updating the caches isn't necessary after unregistering a joint right now, // but it might matter in the future, so it might be better to be safe than // sorry. updateCaches(); }
//============================================================================== void ReferentialSkeleton::unregisterDegreeOfFreedom( BodyNode* _bn, std::size_t _localIndex) { if(nullptr == _bn) { dterr << "[ReferentialSkeleton::unregisterDegreeOfFreedom] Attempting to " << "unregister a DegreeOfFreedom from a nullptr BodyNode. This is " << "most likely a bug. Please report this!\n"; assert(false); return; } std::unordered_map<const BodyNode*, IndexMap>::iterator it = mIndexMap.find(_bn); if( it == mIndexMap.end() || it->second.mDofIndices.size() <= _localIndex || it->second.mDofIndices[_localIndex] == INVALID_INDEX) { dterr << "[ReferentialSkeleton::unregisterDegreeOfFreedom] Attempting to " << "unregister DegreeOfFreedom #" << _localIndex << " of a BodyNode " << "named [" << _bn->getName() << "] (" << _bn << "), but it is not " << "currently in the ReferentialSkeleton! This is most likely a bug. " << "Please report this!\n"; assert(false); return; } std::size_t dofIndex = it->second.mDofIndices[_localIndex]; mDofs.erase(mDofs.begin() + dofIndex); it->second.mDofIndices[_localIndex] = INVALID_INDEX; for(std::size_t i = dofIndex; i < mDofs.size(); ++i) { // Re-index all the DOFs in this ReferentialSkeleton which came after the // DOF that was removed. DegreeOfFreedomPtr dof = mDofs[i]; IndexMap& indexing = mIndexMap[dof.getBodyNodePtr()]; indexing.mDofIndices[dof.getLocalIndex()] = i; } if(it->second.isExpired()) mIndexMap.erase(it); updateCaches(); }
//============================================================================== void ReferentialSkeleton::registerDegreeOfFreedom(DegreeOfFreedom* _dof) { BodyNode* bn = _dof->getChildBodyNode(); std::size_t localIndex = _dof->getIndexInJoint(); std::unordered_map<const BodyNode*, IndexMap>::iterator it = mIndexMap.find(bn); if( it == mIndexMap.end() ) { // Create an index map entry for this DegreeOfFreedom, and only add the // DegreeOfFreedom's index to it IndexMap indexing; indexing.mDofIndices.resize(localIndex+1, INVALID_INDEX); mDofs.push_back(_dof); indexing.mDofIndices[localIndex] = mDofs.size()-1; mIndexMap[bn] = indexing; } else { IndexMap& indexing = it->second; if(indexing.mDofIndices.size() < localIndex+1) indexing.mDofIndices.resize(localIndex+1, INVALID_INDEX); if(INVALID_INDEX == indexing.mDofIndices[localIndex]) { mDofs.push_back(_dof); indexing.mDofIndices[localIndex] = mDofs.size()-1; } } updateCaches(); }
const Elem * DiracKernel::addPoint(Point p, unsigned id) { if (id != libMesh::invalid_uint) { // OK, the user gave us an ID, let's see if we already have it... point_cache_t::iterator it = _point_cache.find(id); // Was the point found in a _point_cache on at least one processor? unsigned int i_found_it = static_cast<unsigned int>(it != _point_cache.end()); unsigned int we_found_it = i_found_it; comm().max(we_found_it); // If the point was found in a cache, but not my cache, I'm not responsible for it. if (we_found_it && !i_found_it) return NULL; // Now that we only cache local data, some processors may enter // this if statement and some may not. Therefore we can't call // any parallel_only() functions inside this if statement. if (i_found_it) { // We have something cached, now make sure it's actually the same Point. // TODO: we should probably use this same comparison in the DiracKernelInfo code! Point cached_point = (it->second).second; if (cached_point.relative_fuzzy_equals(p)) { // Find the cached element associated to this point const Elem * cached_elem = (it->second).first; // If the cached element's processor ID doesn't match ours, we // are no longer responsible for caching it. This can happen // due to adaptivity... if (cached_elem->processor_id() != processor_id()) { // Update the caches, telling them to drop the cached Elem. // Analogously to the rest of the DiracKernel system, we // also return NULL because the Elem is non-local. updateCaches(cached_elem, NULL, p, id); return NULL; } bool active = cached_elem->active(); bool contains_point = cached_elem->contains_point(p); // If the cached Elem is active and the point is still // contained in it, call the other addPoint() method and // return its result. if (active && contains_point) { // FIXME/TODO: // A given Point can be located in multiple elements if it // is on an edge or a node in the grid. How are we handling // that case? In other words, the same id would need to // appear multiple times in the _point_cache object... addPoint(cached_elem, p, id); return cached_elem; } // Is the Elem not active (been refined) but still contains the point? // Then search in its active children and update the caches. else if (!active && contains_point) { // Get the list of active children std::vector<const Elem*> active_children; cached_elem->active_family_tree(active_children); // Linear search through active children for the one that contains p for (unsigned c=0; c<active_children.size(); ++c) if (active_children[c]->contains_point(p)) { updateCaches(cached_elem, active_children[c], p, id); addPoint(active_children[c], p, id); return active_children[c]; } // If we got here without returning, it means the Point was // found in the parent element, but not in any of the active // children... this is not possible under normal // circumstances, so something must have gone seriously // wrong! mooseError("Error, Point not found in any of the active children!"); } else if ( // Is the Elem active but the point is not contained in it any // longer? (For example, did the Mesh move out from under // it?) Then we fall back to the expensive Point Locator // lookup. TODO: we could try and do something more optimized // like checking if any of the active neighbors contains the // point. Update the caches. (active && !contains_point) || // The Elem has been refined *and* the Mesh has moved out // from under it, we fall back to doing the expensive Point // Locator lookup. TODO: We could try and look in the // active children of this Elem's neighbors for the Point. // Update the caches. (!active && !contains_point)) { const Elem * elem = _dirac_kernel_info.findPoint(p, _mesh); updateCaches(cached_elem, elem, p, id); addPoint(elem, p, id); return elem; } else mooseError("We'll never get here!"); } else mooseError("Cached Dirac point " << cached_point << " already exists with ID: " << id << " and does not match point " << p); } } // If we made it here, we either didn't have the point already cached or // id == libMesh::invalid_uint. So now do the more expensive PointLocator lookup, // possibly cache the result, and call the other addPoint() method. const Elem * elem = _dirac_kernel_info.findPoint(p, _mesh); // Only add the point to the cache on this processor if the Elem is local if (elem && (elem->processor_id() == processor_id()) && (id != libMesh::invalid_uint)) { // Add the point to the cache... _point_cache[id] = std::make_pair(elem, p); // ... and to the reverse cache. std::vector<std::pair<Point, unsigned> > & points = _reverse_point_cache[elem]; points.push_back(std::make_pair(p, id)); } // Call the other addPoint() method. This method ignores non-local // and NULL elements automatically. addPoint(elem, p, id); return elem; }
const Elem * DiracKernel::addPointWithValidId(Point p, unsigned id) { // The Elem we'll eventually return. We can't return early on some // processors, because we may need to call parallel_only() functions in // the remainder of this scope. const Elem * return_elem = NULL; // May be set if the Elem is found in our cache, otherwise stays as NULL. const Elem * cached_elem = NULL; // OK, the user gave us an ID, let's see if we already have it... point_cache_t::iterator it = _point_cache.find(id); // Was the point found in a _point_cache on at least one processor? unsigned int i_found_it = static_cast<unsigned int>(it != _point_cache.end()); unsigned int we_found_it = i_found_it; comm().max(we_found_it); // If nobody found it in their local caches, it means we need to // do the PointLocator look-up and update the caches. This is // safe, because all processors have the same value of we_found_it. if (!we_found_it) { const Elem * elem = _dirac_kernel_info.findPoint(p, _mesh); // Only add the point to the cache on this processor if the Elem is local if (elem && (elem->processor_id() == processor_id())) { // Add the point to the cache... _point_cache[id] = std::make_pair(elem, p); // ... and to the reverse cache. std::vector<std::pair<Point, unsigned>> & points = _reverse_point_cache[elem]; points.push_back(std::make_pair(p, id)); } // Call the other addPoint() method. This method ignores non-local // and NULL elements automatically. addPoint(elem, p, id); return_elem = elem; } // If the point was found in a cache, but not my cache, I'm not // responsible for it. // // We can't return early here: then we aren't allowed to call any more // parallel_only() functions in the remainder of this function! if (we_found_it && !i_found_it) return_elem = NULL; // This flag may be set by the processor that cached the Elem because it // needs to call findPoint() (due to moving mesh, etc.). If so, we will // call it at the end of the while loop below. bool i_need_find_point = false; // Now that we only cache local data, some processors may enter // this if statement and some may not. Therefore we can't call // any parallel_only() functions inside this if statement. while (i_found_it) { // We have something cached, now make sure it's actually the same Point. // TODO: we should probably use this same comparison in the DiracKernelInfo code! Point cached_point = (it->second).second; if (cached_point.relative_fuzzy_equals(p)) { // Find the cached element associated to this point cached_elem = (it->second).first; // If the cached element's processor ID doesn't match ours, we // are no longer responsible for caching it. This can happen // due to adaptivity... if (cached_elem->processor_id() != processor_id()) { // Update the caches, telling them to drop the cached Elem. // Analogously to the rest of the DiracKernel system, we // also return NULL because the Elem is non-local. updateCaches(cached_elem, NULL, p, id); return_elem = NULL; break; // out of while loop } bool active = cached_elem->active(); bool contains_point = cached_elem->contains_point(p); // If the cached Elem is active and the point is still // contained in it, call the other addPoint() method and // return its result. if (active && contains_point) { addPoint(cached_elem, p, id); return_elem = cached_elem; break; // out of while loop } // Is the Elem not active (been refined) but still contains the point? // Then search in its active children and update the caches. else if (!active && contains_point) { // Get the list of active children std::vector<const Elem *> active_children; cached_elem->active_family_tree(active_children); // Linear search through active children for the one that contains p for (unsigned c = 0; c < active_children.size(); ++c) if (active_children[c]->contains_point(p)) { updateCaches(cached_elem, active_children[c], p, id); addPoint(active_children[c], p, id); return_elem = active_children[c]; break; // out of for loop } // If we got here without setting return_elem, it means the Point was // found in the parent element, but not in any of the active // children... this is not possible under normal // circumstances, so something must have gone seriously // wrong! if (!return_elem) mooseError("Error, Point not found in any of the active children!"); break; // out of while loop } else if ( // Is the Elem active but the point is not contained in it any // longer? (For example, did the Mesh move out from under // it?) Then we fall back to the expensive Point Locator // lookup. TODO: we could try and do something more optimized // like checking if any of the active neighbors contains the // point. Update the caches. (active && !contains_point) || // The Elem has been refined *and* the Mesh has moved out // from under it, we fall back to doing the expensive Point // Locator lookup. TODO: We could try and look in the // active children of this Elem's neighbors for the Point. // Update the caches. (!active && !contains_point)) { i_need_find_point = true; break; // out of while loop } else mooseError("We'll never get here!"); } // if (cached_point.relative_fuzzy_equals(p)) else mooseError("Cached Dirac point ", cached_point, " already exists with ID: ", id, " and does not match point ", p); // We only want one iteration of this while loop at maximum. i_found_it = false; } // while (i_found_it) // We are back to all processors here because we do not return // early in the code above... // Does we need to call findPoint() on all processors. unsigned int we_need_find_point = static_cast<unsigned int>(i_need_find_point); comm().max(we_need_find_point); if (we_need_find_point) { // findPoint() is a parallel-only function const Elem * elem = _dirac_kernel_info.findPoint(p, _mesh); updateCaches(cached_elem, elem, p, id); addPoint(elem, p, id); return_elem = elem; } return return_elem; }