示例#1
0
    void StringFunction::evalFunctions(MDArray& inp, double time_value_optional)
    {
      EXCEPTWATCH;
      std::map<Function *, std::vector<double> >::iterator it = m_func_to_value.begin();
      const std::map<Function *, std::vector<double> >::iterator it_end = m_func_to_value.end();

      //Evaluate the function and store the answer in its bound location
      for(; it != it_end; ++it)
        {
          Function& func = *it->first;

          PRINTQ(func.getName());

          // check to avoid infinite recursion
          if (&func == this)
            {
              std::ostringstream msg;
              msg << "StringFunction::evalFunctions: infinite recursion by self-referential string function, name= " << m_name;
              VERIFY_1(msg.str());
            }

          VERIFY_OP(func.getNewDomain().rank(), ==, 1, "StringFunction::evalFunctions: functions must be defined with domain/codomain of rank 1 for now");
          VERIFY_OP(func.getNewCodomain().rank(), ==, 1, "StringFunction::evalFunctions: functions must be defined with domain/codomain of rank 1 for now");
          int numCells = 1;

          MDArray f_inp = MDArray(numCells, func.getNewDomain().dimension(0));
          MDArray f_out = MDArray(numCells, func.getNewCodomain().dimension(0));

          int nInDim = last_dimension(f_inp);
          // FIXME - do we really need the extra array?
          for (int iDim = 0; iDim < nInDim; iDim++)
            {
              f_inp(0, iDim) = inp( iDim);
            }

          if (m_have_element)
            {
              func(f_inp, f_out, *m_element, m_parametric_coordinates, time_value_optional); 
            }
          else
            {
              func(f_inp, f_out); 
            }

          int nOutDim = last_dimension(f_out);

          for (int iDim = 0; iDim < nOutDim; iDim++)
            {
              (it->second)[iDim] = f_out(0, iDim);
            }

        }
    }
示例#2
0
void Search_Range::nearest_sphere_recurse( One_Tree *tree )
{
  Near_Workspace &ws = near_workspace;

  // debug
  const bool debug = false;
  assert(ws._num_calls <  num_nodes() );
  ++ws._num_calls;
  
  const size_t d = tree->_d;
  double x_lo, x_hi;
  old_lo_hi(d, x_lo, x_hi);

  // walk until the path to x_lo and x_hi diverge
  // this might update x_lo and x_hi with a new closest
  Tree_Node *n = find_split( tree, x_lo, x_hi, true );

  if (debug)
  {
    std::cout << "Search_Range [" << x_lo << ", " << x_hi << "] coordinate " << tree->_d << ". ";
    std::cout << "Diverges at node ";
    Range_Tree::print_single_node( n, tree );
    // std::cout << std::endl;
  }

  // never split, nothing is in range
  if (!n)
  {
    if (debug)
      std::cout << " no nearest sphere was in range." << std::endl;
    return;
  }

  // If n is a leaf, then immediately recurse by dimension on its subtree.
  // For efficiency we just check the distance immediately, since the result is the same.
  if (n->is_leaf())
  {
    if (debug)
      std::cout << " fathomed at leaf node." << std::endl;
    new_lo_hi( n->_sphere, d, x_lo, x_hi);
    return;
  }

  // go down right and left sides, checking subtrees
  // right
  {
    if (debug)
    {
      std::cout << "  Searching Right subtree " << std::endl;
    }
    Tree_Node * r = n->_right;
    while( r )
    {
      new_old_lo_hi( r->_sphere, d, x_lo, x_hi);

      const double &x = _spheres[ r->_sphere ][ d ];
      
      if ( r->is_leaf() )
        break;

      // discard right->right?
      if ( x > x_hi )
        r = r->_left;
      else
      {
        // recurse on left
        if (r->_left->_subtree)
        {
          if (debug) std::cout << "recursively searching left subtree. " << std::endl;
          nearest_sphere_recurse( r->_left->_subtree );
        }
        // fathomed at last dimension
        else
        {
          if (debug)
          {
            std::cout << "Search_Range [" << x_lo << ", " << x_hi << "] coordinate " << tree->_d << ". ";
            std::cout << " Nearest all leaves, left subtree, rooted at node ";
            print_single_node(r->_left, tree);
            std::cout << std::endl;
          }
          assert( last_dimension(tree) || r->_left->is_leaf() );
          // go down left (recurse) but with current dimension
          nearest_sphere_leaves( r->_left, d );
        }
        
        r = r->_right;
      }
    }
  }
  // left
  {
    if (debug)
    {
      std::cout << "Search_Range [" << x_lo << ", " << x_hi << "] coordinate " << tree->_d << ". ";
      std::cout << "Searching Left subtree " << std::endl;
    }
    Tree_Node * lft = n->_left;
    while( lft )
    {
      new_old_lo_hi( lft->_sphere, d, x_lo, x_hi);
      
      if (lft->is_leaf())
        break;

      const double &x = _spheres[ lft->_sphere ][ tree->_d ];
      if ( x_lo > x )
        lft = lft->_right;
      else
      {
        // right tree is (was) in the range
        if ( lft->_right )
        {
          if ( lft->_right->_subtree )
            nearest_sphere_recurse( lft->_right->_subtree );
          // fathomed at last dimension
          else
          {
            if (debug)
            {
              std::cout << "Search_Range [" << x_lo << ", " << x_hi << "] coordinate " << tree->_d << ". ";
              std::cout << " Nearest all leaves, right subtree, rooted at node ";
              print_single_node(lft->_right, tree);
              std::cout << std::endl;
            }
            assert( last_dimension(tree) || lft->_right->is_leaf() );
            // go down right (recurse) but with current dimension
            nearest_sphere_leaves( lft->_right, d );
          }
        }
        lft = lft->_left;
        // null if it was a leaf
      }
    }
  }
}
示例#3
0
void Search_Range::trim_line_anchored_recurse( One_Tree *tree )
{

  // walk until the path to x_lo and x_hi diverge
  double x_lo, x_hi;
  Tree_Node *n = find_split( tree, x_lo, x_hi );

  // nothing was in range, no spheres near enough to possibly trim the line segment
  if (!n)
    return;

  // leaf, only one sphere in range, trim with it now
  if (n->is_leaf())
  {
    trim_leaf( n->_sphere );
    return;
  }

   // go down right and left sides
  // right
  {
    Tree_Node * r = n->_right;
    while( r )
    {
      assert( r->is_wellformed() );
      const double &x = _spheres[ r->_sphere ][ tree->_d ];
      if ( x_hi > x )
      {
        // left tree is in the range
        if ( r->_left )
        {
          assert( r->_left->is_wellformed() );
          if (r->_left->_subtree)
            trim_line_anchored_recurse( r->_left->_subtree );
          // fathomed at last dimension
          else
          {
            assert( last_dimension(tree)  );
            trim_all_leaves( r->_left );
            get_line_neighborhood( tree->_d, x_lo, x_hi );
          }
        }
        // leaf
        else
        {
          assert( r->is_leaf() );
          trim_leaf( r->_sphere );
          get_line_neighborhood( tree->_d, x_lo, x_hi );
        }
        r = r->_right;
        // null if it was a leaf
      }
      else
        r = r->_left;
        // if r == 0, then its parent was a leaf and out of range
    }
  }
  // left
  {
    Tree_Node * lft = n->_left;
    while( lft )
    {
      assert( lft->is_wellformed() );
      const double &x = _spheres[ lft->_sphere ][ tree->_d ];
      if ( x_lo <= x )
      {
        // right tree is in the range
        if ( lft->_right )
        {
          assert( lft->_right->is_wellformed() );
          if ( lft->_right->_subtree )
            trim_line_anchored_recurse( lft->_right->_subtree );
          // fathomed at last dimension
          else
          {
            assert( last_dimension(tree)  );
            trim_all_leaves( lft->_right );
            get_line_neighborhood( tree->_d, x_lo, x_hi );
          }
        }
        // leaf
        else
        {
          assert( lft->is_leaf() );
          trim_leaf( lft->_sphere );
          get_line_neighborhood( tree->_d, x_lo, x_hi );
        }
        lft = lft->_left; 
        // null if it was a leaf
      }
      else
      {
        lft = lft->_right;
        // if lft == 0, then its old value (parent) was a leaf and out of range
      }
    }
  }
}
示例#4
0
bool Search_Range::no_near_spheres_recurse( One_Tree *tree ) 
{

  Near_Workspace &ws = near_workspace;

  // debug
  assert(ws._num_calls <= num_nodes() );
  ++ws._num_calls;
  
  double x_lo = ws._p[tree->_d] - ws._thresh;
  double x_hi = ws._p[tree->_d] + ws._thresh;

  // walk until the path to x_lo and x_hi diverge
  Tree_Node *n = find_split( tree, x_lo, x_hi);

  // nothing in range
  if (!n)
    return true;

  // only one sphere in range, check it now
  if (n->is_leaf())
    return no_near_leaf(n->_sphere);

  // go down right and left sides
  // right
  {
    Tree_Node * r = n->_right;
    while( r )
    {
      assert( r->is_wellformed() );
      const double &x = _spheres[ r->_sphere ][ tree->_d ];
      if ( x_hi > x )
      {
        // left tree is in the range
        if ( r->_left )
        {
          assert( r->_left->is_wellformed() );
          if (r->_left->_subtree)
          {
            if (!no_near_spheres_recurse( r->_left->_subtree ))
              return false;
          }
          // fathomed at last dimension
          else
          {
            assert( last_dimension(tree)  );
            // check entire subtree explicitly
            if (!no_near_leaves( r->_left ))
              return false;
          }
        }
        // leaf
        else
        {
          // check leaf sphere
          assert(r->is_leaf());
          if (!no_near_leaf( r->_sphere ))
            return false;
        }
        r = r->_right;
        // null if it was a leaf
      }
      else
        r = r->_left;
        // if r == 0, then its parent was a leaf and out of range
    }
  }
  // left
  {
    Tree_Node * lft = n->_left;
    while( lft )
    {
      assert( lft->is_wellformed() );
      const double &x = _spheres[ lft->_sphere ][ tree->_d ];
      if ( x_lo <= x )
      {
        // right tree is in the range
        if ( lft->_right )
        {
          assert( lft->is_wellformed() );
          if ( lft->_right->_subtree )
          {
            if (!no_near_spheres_recurse( lft->_right->_subtree ))
              return false;
          }
          // fathomed at last dimension
          else
          {
            assert( last_dimension(tree)  );
            if (!no_near_leaves( lft->_right ))
              return false;
          }
        }
        // leaf
        else
        {
          assert( lft->is_leaf() );
          if (!no_near_leaf( lft->_sphere ))
            return false;
        }
        lft = lft->_left; 
        // null if it was a leaf
      }
      else
      {
        lft = lft->_right;
        // if lft == 0, then its old value (parent) was a leaf and out of range
      }
    }
  }
  return true;
}
示例#5
0
void Search_Range::all_near_spheres_recurse( One_Tree *tree )
{
  const bool debug = false;
  
  Near_Workspace &ws = near_workspace;

  // debug
  assert(ws._num_calls <  num_nodes() );
  ++ws._num_calls;
  
  const size_t d = tree->_d;
  double x_lo = ws._p[d] - ws._thresh;
  double x_hi = ws._p[d] + ws._thresh;

  // walk until the path to x_lo and x_hi diverge
  Tree_Node *n = find_split( tree, x_lo, x_hi );
  if (debug)
  {
    std::cout << "Search_Range [" << x_lo << ", " << x_hi << "] coordinate " << tree->_d << ". ";
    std::cout << "Diverges at node ";
    Range_Tree::print_single_node( n, tree );
    // std::cout << std::endl;
  }

  // never split, nothing is in range
  if (!n)
  {
    if (debug)
      std::cout << " no spheres were in range." << std::endl;
    return;
  }

  // If n is a leaf, then immediately recurse by dimension on its subtree.
  // For efficiency we just check the distance immediately, since the result is the same.
  if (n->is_leaf())
  {
    if (debug)
      std::cout << " fathomed at leaf node." << std::endl;
    add_leaf(n->_sphere);
    return;
  }

    // go down right and left sides, reporting subtrees
  // right
  {
    if (debug)
    {
      std::cout << "  Searching Right subtree " << std::endl;
    }
    Tree_Node * r = n->_right;
    while( r )
    {
      const double &x = _spheres[ r->_sphere ][ d ];
      if ( x_hi > x )
      {
        // left tree is in the range
        if ( r->_left )
        {
          if (r->_left->_subtree)
            all_near_spheres_recurse( r->_left->_subtree );
          // fathomed at last dimension
          else
          {
            if (debug)
            {
              std::cout << "Search_Range [" << x_lo << ", " << x_hi << "] coordinate " << tree->_d << ". ";
              std::cout << " Adding left subtree rooted at node ";
              print_single_node(r->_left, tree);
              std::cout << std::endl;
            }
            assert( last_dimension(tree) || r->_left->is_leaf() );
            add_all_leaves( r->_left );
          }
        }
        // leaf
        else
        {
          assert( r->is_leaf() );
          if (debug)
          {
            std::cout << "Search_Range [" << x_lo << ", " << x_hi << "] coordinate " << tree->_d << ". ";
            std::cout << " Adding leaf node ";
            print_single_node(r, tree);
            std::cout << std::endl;
          }
          add_leaf( r->_sphere );
        }
        r = r->_right;
        // null if it was a leaf
      }
      else
        r = r->_left;
        // if r == 0, then its parent was a leaf and out of range
    }
  }
  // left
  {
    if (debug)
    {
      std::cout << "Search_Range [" << x_lo << ", " << x_hi << "] coordinate " << tree->_d << ". ";
      std::cout << "Searching Left subtree " << std::endl;
    }
    Tree_Node * lft = n->_left;
    while( lft )
    {
      const double &x = _spheres[ lft->_sphere ][ tree->_d ];
      if ( x_lo <= x )
      {
        // right tree is in the range
        if ( lft->_right )
        {
          if ( lft->_right->_subtree )
            all_near_spheres_recurse( lft->_right->_subtree );
          // fathomed at last dimension
          else
          {
            if (debug)
            {
              std::cout << "Search_Range [" << x_lo << ", " << x_hi << "] coordinate " << tree->_d << ". ";
              std::cout << " Adding right subtree rooted at node ";
              print_single_node(lft->_right, tree);
              std::cout << std::endl;
            }
            assert( last_dimension(tree) || lft->_right->is_leaf() );
            add_all_leaves( lft->_right );
          }
        }
        // leaf
        else
        {
          assert( lft->is_leaf() );
          if (debug)
          {
            std::cout << "Search_Range [" << x_lo << ", " << x_hi << "] coordinate " << tree->_d << ". ";
            std::cout << " Adding leaf node ";
            print_single_node(lft, tree);
            std::cout << std::endl;
          }
          add_leaf( lft->_sphere );
        }
        lft = lft->_left; 
        // null if it was a leaf
      }
      else
      {
        lft = lft->_right;
        // if lft == 0, then its old value (parent) was a leaf and out of range
      }
    }
  }
}
示例#6
0
    /** Evaluate the function at this input point (or points) returning value(s) in output_field_values
     *
     *   In the following, the arrays are dimensioned using the notation (from Intrepid's doc):
     *
     *   [C]         - num. integration domains (cells/elements)
     *   [F]         - num. Intrepid "fields" (number of bases within an element == num. nodes typically)
     *   [P]         - num. integration (or interpolation) points within the element
     *   [D]         - spatial dimension
     *   [D1], [D2]  - spatial dimension
     *
     *   Locally, we introduce this notation:
     *
     *   [DOF]       - number of degrees-of-freedom per node of the interpolated stk Field.  For example, a vector field in 3D has [DOF] = 3
     *
     *  Dimensions of input_phy_points are required to be either ([D]) or ([P],[D])
     *  Dimensions of output_field_values are required to be ([DOF]) or ([P],[DOF]) respectively
     *
     *  [R] is used for the rank of MDArray's
     */
    void FieldFunction::operator()(MDArray& input_phy_points, MDArray& output_field_values, double time)
    {
      EXCEPTWATCH;
      argsAreValid(input_phy_points, output_field_values);

      m_found_on_local_owned_part = false;

      //// single point only (for now)
      unsigned found_it = 0;

      int D_ = last_dimension(input_phy_points);
      MDArray found_parametric_coordinates_one(1, D_);
      setup_searcher(D_);

      MDArray output_field_values_local = output_field_values;
      int R_output = output_field_values.rank();

      int R_input = input_phy_points.rank();
      int P_ = (R_input == 1 ? 1 : input_phy_points.dimension(R_input-2));

      // FIXME for tensor valued fields
      int DOF_ = last_dimension(output_field_values_local);

      MDArray input_phy_points_one(1,D_);
      MDArray output_field_values_one(1,DOF_);

      int C_ = 1;
      if (R_input == 3)
        {
          C_ = input_phy_points.dimension(0);
        }
      for (int iC = 0; iC < C_; iC++)
        {
          for (int iP = 0; iP < P_; iP++)
            {
              for (int iD = 0; iD < D_; iD++)
                {
                  switch(R_input)
                    {
                    case 1: input_phy_points_one(0, iD) = input_phy_points(iD); break;
                    case 2: input_phy_points_one(0, iD) = input_phy_points(iP, iD); break;
                    case 3: input_phy_points_one(0, iD) = input_phy_points(iC, iP, iD); break;
                    default: VERIFY_1("bad rank");
                    }
                }

              const stk_classic::mesh::Entity *found_element = 0;
              {
                EXCEPTWATCH;
                //if (m_searchType==STK_SEARCH) std::cout << "find" << std::endl;
                found_element = m_searcher->findElement(input_phy_points_one, found_parametric_coordinates_one, found_it, m_cachedElement);
                //if (m_searchType==STK_SEARCH)                std::cout << "find..done found_it=" << found_it << std::endl;
              }

              // if found element on the local owned part, evaluate
              if (found_it)
                {
                  m_found_on_local_owned_part = true;
                  if (( EXTRA_PRINT) && m_searchType==STK_SEARCH)
                    std::cout << "FieldFunction::operator() found element # = " << found_element->identifier() << std::endl;

                  (*this)(input_phy_points_one, output_field_values_one, *found_element, found_parametric_coordinates_one);

                  for (int iDOF = 0; iDOF < DOF_; iDOF++)
                    {
                      switch (R_output)
                        {
                        case 1: output_field_values_local( iDOF)        = output_field_values_one(0, iDOF); break;
                        case 2: output_field_values_local(iP, iDOF)     = output_field_values_one(0, iDOF); break;
                        case 3: output_field_values_local(iC, iP, iDOF) = output_field_values_one(0, iDOF); break;
                        default: VERIFY_1("bad rank");
                        }
                    }
                }
              else
                {
                  if (!m_parallelEval)
                    {
                      std::cout << "P[" << Util::get_rank() << "] FieldFunction::operator() found_it = " << found_it << " points= "
                                << input_phy_points_one
                                << std::endl;

                      throw std::runtime_error("FieldFunction::operator() in local eval mode and didn't find element - logic error");
                    }
                  double max_val = std::numeric_limits<double>::max();
                  output_field_values_local.initialize(max_val);
                }

              // make sure it is found somewhere
              if (m_parallelEval)
                {
                  all_reduce( m_bulkData->parallel() , ReduceMax<1>( & found_it ) );
                }

              if (EXTRA_PRINT) std::cout << "FieldFunction::operator() global found_it = " << found_it << std::endl;

              if (!found_it)
                {
                  throw std::runtime_error("FieldFunction::operator() couldn't find element");
                }

              if (m_parallelEval)
                {
                  stk_percept_global_lex_min( m_bulkData->parallel(), output_field_values.size(), &output_field_values_local[0], &output_field_values[0]);
                }
              else
                {
                  output_field_values = output_field_values_local;
                }
              m_cachedElement = found_element;
            }
        }

    }