//==============================================================================
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();
}
Exemple #4
0
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();
}
Exemple #8
0
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;
}
Exemple #9
0
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;
}