Real RBEIMEvaluation::rb_solve(unsigned int N) { // Short-circuit if we are using the same parameters and value of N if( (_previous_parameters == get_parameters()) && (_previous_N == N) ) { return _previous_error_bound; } // Otherwise, update _previous parameters, _previous_N _previous_parameters = get_parameters(); _previous_N = N; LOG_SCOPE("rb_solve()", "RBEIMEvaluation"); if(N > get_n_basis_functions()) libmesh_error_msg("ERROR: N cannot be larger than the number of basis functions in rb_solve"); if(N==0) libmesh_error_msg("ERROR: N must be greater than 0 in rb_solve"); // Get the rhs by sampling parametrized_function // at the first N interpolation_points DenseVector<Number> EIM_rhs(N); for(unsigned int i=0; i<N; i++) { EIM_rhs(i) = evaluate_parametrized_function(interpolation_points_var[i], interpolation_points[i], *interpolation_points_elem[i]); } DenseMatrix<Number> interpolation_matrix_N; interpolation_matrix.get_principal_submatrix(N, interpolation_matrix_N); interpolation_matrix_N.lu_solve(EIM_rhs, RB_solution); // Optionally evaluate an a posteriori error bound. The EIM error estimate // recommended in the literature is based on using "next" EIM point, so // we skip this if N == get_n_basis_functions() if(evaluate_RB_error_bound && (N != get_n_basis_functions())) { // Compute the a posteriori error bound // First, sample the parametrized function at x_{N+1} Number g_at_next_x = evaluate_parametrized_function(interpolation_points_var[N], interpolation_points[N], *interpolation_points_elem[N]); // Next, evaluate the EIM approximation at x_{N+1} Number EIM_approx_at_next_x = 0.; for(unsigned int j=0; j<N; j++) { EIM_approx_at_next_x += RB_solution(j) * interpolation_matrix(N,j); } Real error_estimate = std::abs(g_at_next_x - EIM_approx_at_next_x); _previous_error_bound = error_estimate; return error_estimate; } else // Don't evaluate an error bound { _previous_error_bound = -1.; return -1.; } }
Real RBEIMEvaluation::rb_solve(unsigned int N) { // Short-circuit if we are using the same parameters and value of N if( (_previous_parameters == get_parameters()) && (_previous_N == N) ) { return _previous_error_bound; } // Otherwise, update _previous parameters, _previous_N _previous_parameters = get_parameters(); _previous_N = N; START_LOG("rb_solve()", "RBEIMEvaluation"); if(N > get_n_basis_functions()) { libMesh::err << "ERROR: N cannot be larger than the number " << "of basis functions in rb_solve" << std::endl; libmesh_error(); } if(N==0) { libMesh::err << "ERROR: N must be greater than 0 in rb_solve" << std::endl; libmesh_error(); } // Get the rhs by sampling parametrized_function // at the first N interpolation_points DenseVector<Number> EIM_rhs(N); for(unsigned int i=0; i<N; i++) { EIM_rhs(i) = evaluate_parametrized_function(interpolation_points_var[i], interpolation_points[i]); } DenseMatrix<Number> interpolation_matrix_N; interpolation_matrix.get_principal_submatrix(N, interpolation_matrix_N); interpolation_matrix_N.lu_solve(EIM_rhs, RB_solution); // Evaluate an a posteriori error bound if(evaluate_RB_error_bound) { // Compute the a posteriori error bound // First, sample the parametrized function at x_{N+1} Number g_at_next_x; if(N == get_n_basis_functions()) g_at_next_x = evaluate_parametrized_function(extra_interpolation_point_var, extra_interpolation_point); else g_at_next_x = evaluate_parametrized_function(interpolation_points_var[N], interpolation_points[N]); // Next, evaluate the EIM approximation at x_{N+1} Number EIM_approx_at_next_x = 0.; for(unsigned int j=0; j<N; j++) { if(N == get_n_basis_functions()) { EIM_approx_at_next_x += RB_solution(j) * extra_interpolation_matrix_row(j); } else { EIM_approx_at_next_x += RB_solution(j) * interpolation_matrix(N,j); } } Real error_estimate = std::abs(g_at_next_x - EIM_approx_at_next_x); STOP_LOG("rb_solve()", "RBEIMEvaluation"); _previous_error_bound = error_estimate; return error_estimate; } else // Don't evaluate an error bound { STOP_LOG("rb_solve()", "RBEIMEvaluation"); _previous_error_bound = -1.; return -1.; } }