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); } } }
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 } } } }
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 } } } }
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; }
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 } } } }
/** 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; } } }