void IntrepidSideCell<MDArray>::mapToCellPhysicalFrame( const MDArray& parametric_coords, MDArray& physical_coords ) { DTK_REQUIRE( 2 == parametric_coords.rank() ); DTK_REQUIRE( 3 == physical_coords.rank() ); DTK_REQUIRE( parametric_coords.dimension(1) == Teuchos::as<int>(this->d_topology.getDimension()) ); DTK_REQUIRE( physical_coords.dimension(0) == this->d_cell_node_coords.dimension(0) ); DTK_REQUIRE( physical_coords.dimension(1) == parametric_coords.dimension(0) ); DTK_REQUIRE( physical_coords.dimension(2) == Teuchos::as<int>(d_parent_topology.getDimension()) ); MDArray mapped_coords( parametric_coords.dimension(0), d_parent_topology.getDimension() ); Intrepid::CellTools<Scalar>::mapToReferenceSubcell( mapped_coords, parametric_coords, this->d_topology.getDimension(), d_side_id, d_parent_topology ); Intrepid::CellTools<Scalar>::mapToPhysicalFrame( physical_coords, mapped_coords, this->d_cell_node_coords, d_parent_topology ); }
void StringFunction::operator()(MDArray& input_phy_points, MDArray& output_values, const stk::mesh::Bucket& bucket, const MDArray& parametric_coordinates, double time_value_optional) { PRINT("tmp srk StringFunction::operator(bucket) getName()= " << getName() << " input_phy_points= " << input_phy_points << " output_values= " << output_values); VERIFY_OP(input_phy_points.rank(), ==, 3, "StringFunction::operator() must pass in input_phy_points(numCells, numPointsPerCell, spaceDim)"); int nPoints = input_phy_points.dimension(1); int nSpaceDim = input_phy_points.dimension(2); int nOutDim = output_values.dimension(2); MDArray input_phy_points_one(1, nPoints, nSpaceDim); MDArray output_values_one (1, nPoints, nOutDim); const unsigned num_elements_in_bucket = bucket.size(); for (unsigned iElement = 0; iElement < num_elements_in_bucket; iElement++) { stk::mesh::Entity& element = bucket[iElement]; for (int iPoint = 0; iPoint<nPoints; iPoint++) { for (int iSpaceDim=0; iSpaceDim < nSpaceDim; iSpaceDim++) { input_phy_points_one(0, iPoint, iSpaceDim) = input_phy_points(iElement, iPoint, iSpaceDim); } } (*this)(input_phy_points_one, output_values_one, element, parametric_coordinates, time_value_optional); for (int iPoint = 0; iPoint<nPoints; iPoint++) { for (int iDOF = 0; iDOF < nOutDim; iDOF++) { output_values(iElement, iPoint, iDOF) = output_values_one(0, iPoint, iDOF); } } } }
/// Dimensions of parametric_coordinates and input_phy_points are required to be ([P],[D]) /// output_values: ([P], [DOF]) void StringFunction::operator()(MDArray& input_phy_points, MDArray& output_values, const stk::mesh::Entity& element, const MDArray& parametric_coordinates, double time_value_optional) { PRINT("tmp srk StringFunction::operator(element) getName()= " << getName() << " input_phy_points= " << input_phy_points << " output_values= " << output_values); argsAreValid(input_phy_points, output_values); argsAreValid(parametric_coordinates, output_values); m_element = &element; m_have_element = true; VERIFY_OP(parametric_coordinates.rank(), ==, 2, "StringFunction::operator() parametric_coordinates rank bad"); m_parametric_coordinates = MDArray(1, parametric_coordinates.dimension(1)); int nPoints=parametric_coordinates.dimension(0); int spaceDim = parametric_coordinates.dimension(1); for (int iPoint = 0; iPoint < nPoints; iPoint++) { for (int iSpace=0; iSpace < spaceDim; iSpace++) m_parametric_coordinates(0, iSpace)=parametric_coordinates(iPoint, iSpace); (*this)(input_phy_points, output_values, time_value_optional); } // reset this else we won't be able to reuse this object correctly m_have_element = false; m_element = 0; // * Dimensions of parametric_coordinates are required to be ([P],[D]) //FieldFunction:: void operator()(const stk::mesh::Entity *element, const MDArray& parametric_coordinates, MDArray& out); }
void StringFunction::operator()(MDArray& inp, MDArray& out, double time_value_optional) { EXCEPTWATCH; argsAreValid(inp, out); PRINT("tmp srk StringFunction::operator() getName()= " << getName() << " inp= " << inp << " out= " << out); int domain_rank = m_domain_dimensions.size(); int codomain_rank = m_codomain_dimensions.size(); // FIXME move to argsAreValid VERIFY_OP(domain_rank, ==, 1, "StringFunction::operator(): must specify domain Dimensions as rank 1 (for now)"); VERIFY_OP(codomain_rank, ==, 1, "StringFunction::operator(): must specify codomain Dimensions as rank 1 (for now)"); int inp_rank = inp.rank(); int out_rank = out.rank(); int inp_offset = inp_rank - domain_rank; int out_offset = out_rank - codomain_rank; // returns 1,1,1,... etc. if that dimension doesn't exist enum { maxRank = 3}; VERIFY_OP_ON(inp_rank, <=, maxRank, "StringFunction::operator() input array rank too large"); VERIFY_OP_ON(out_rank, <=, maxRank, "StringFunction::operator() output array rank too large"); int n_inp_points[maxRank] = {1,1,1}; int n_out_points[maxRank] = {1,1,1}; first_dimensions(inp, inp_offset, n_inp_points, maxRank); first_dimensions(out, out_offset, n_out_points, maxRank); int nInDim = m_domain_dimensions[0]; int nOutDim = m_codomain_dimensions[0]; MDArray inp_loc(nInDim); MDArray out_loc(nOutDim); int iDim[maxRank-1] = {0,0}; double *xyzt[] = {&m_x, &m_y, &m_z, &m_t}; PRINT("getName()= " << getName() << " n_inp_points= " << n_inp_points[0] << " " << n_inp_points[1] << " " << n_inp_points[2] << " nInDim= " << nInDim); m_t = time_value_optional; for (iDim[0] = 0; iDim[0] < n_inp_points[0]; iDim[0]++) { for (iDim[1] = 0; iDim[1] < n_inp_points[1]; iDim[1]++) { for (int id = 0; id < nInDim; id++) { switch (inp_rank) { case 3: inp_loc(id) = inp(iDim[0], iDim[1], id); *xyzt[id] = inp(iDim[0], iDim[1], id); break; case 2: inp_loc(id) = inp(iDim[0], id); *xyzt[id] = inp(iDim[0], id); break; case 1: inp_loc(id) = inp( id); *xyzt[id] = inp( id); break; } } if (m_func_to_value.size()) { evalFunctions(inp_loc, time_value_optional); } //Save the evaluations slightly differently whether it's a scalar or vector valued function if ((int)m_v.size() != nOutDim) { m_v.resize(nOutDim); } PRINT("getName()= " << getName() << " about to evaluate m_functionExpr... iDim[0] = " << iDim[0] << " iDim[1]= " << iDim[1]); if(nOutDim == 1) m_v[0] = m_functionExpr.evaluate(); else m_functionExpr.evaluate(); PRINT("getName()= " << getName() << " done to evaluate m_functionExpr... iDim[0] = " << iDim[0] << " iDim[1]= " << iDim[1]); for (int iOutDim = 0; iOutDim < nOutDim; iOutDim++) { switch (out_rank) { case 1: out(iOutDim) = m_v[iOutDim]; break; case 2: out(iDim[0], iOutDim) = m_v[iOutDim]; break; case 3: out(iDim[0], iDim[1], iOutDim) = m_v[iOutDim]; break; default: VERIFY_1("StringFunction::operator() bad output rank"); } } } } PRINT("getName()= " << getName() << " done in operator()"); }
void NewtonSolver<NonlinearProblem>::solve( MDArray& u, NonlinearProblem& problem, const double tolerance, const int max_iters ) { DTK_REQUIRE( 2 == u.rank() ); // Allocate nonlinear residual, Jacobian, Newton update, and work arrays. int d0 = u.dimension(0); int d1 = u.dimension(1); MDArray F( d0, d1 ); MDArray J( d0, d1, d1 ); MDArray J_inv( d0, d1, d1 ); MDArray update( d0, d1 ); MDArray u_old = u; MDArray conv_check( d0 ); // Compute the initial state. NPT::updateState( problem, u ); // Computen the initial nonlinear residual and scale by -1 to get -F(u). NPT::evaluateResidual( problem, u, F ); Intrepid::RealSpaceTools<Scalar>::scale( F, -Teuchos::ScalarTraits<Scalar>::one() ); // Compute the initial Jacobian. NPT::evaluateJacobian( problem, u, J ); // Check for degeneracy of the Jacobian. If it is degenerate then the // problem is ill conditioned and return very large numbers in the state // vector that correspond to no solution. MDArray det( 1 ); Intrepid::RealSpaceTools<Scalar>::det( det, J ); if ( std::abs(det(0)) < tolerance ) { for ( int m = 0; m < d0; ++m ) { for ( int n = 0; n < d1; ++n ) { u(m,n) = std::numeric_limits<Scalar>::max(); } } return; } // Nonlinear solve. for ( int k = 0; k < max_iters; ++k ) { // Solve the linear model, delta_u = J^-1 * -F(u). Intrepid::RealSpaceTools<Scalar>::inverse( J_inv, J ); Intrepid::RealSpaceTools<Scalar>::matvec( update, J_inv, F ); // Update the solution, u += delta_u. Intrepid::RealSpaceTools<Scalar>::add( u, update ); // Check for convergence. Intrepid::RealSpaceTools<Scalar>::subtract( u_old, u ); Intrepid::RealSpaceTools<Scalar>::vectorNorm( conv_check, u_old, Intrepid::NORM_TWO ); if ( tolerance > conv_check(0) ) { break; } // Reset for the next iteration. u_old = u; // Update any state-dependent data from the last iteration using the // new solution vector. NPT::updateState( problem, u ); // Compute the nonlinear residual and scale by -1 to get -F(u). NPT::evaluateResidual( problem, u, F ); Intrepid::RealSpaceTools<Scalar>::scale( F, -Teuchos::ScalarTraits<Scalar>::one() ); // Compute the Jacobian. NPT::evaluateJacobian( problem, u, J ); } // Check for convergence. DTK_ENSURE( tolerance > conv_check(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; } } }