Real RBEvaluation::compute_residual_dual_norm(const unsigned int N) { START_LOG("compute_residual_dual_norm()", "RBEvaluation"); const RBParameters& mu = get_parameters(); // Use the stored representor inner product values // to evaluate the residual norm Number residual_norm_sq = 0.; unsigned int q=0; for(unsigned int q_f1=0; q_f1<rb_theta_expansion->get_n_F_terms(); q_f1++) { for(unsigned int q_f2=q_f1; q_f2<rb_theta_expansion->get_n_F_terms(); q_f2++) { Real delta = (q_f1==q_f2) ? 1. : 2.; residual_norm_sq += delta * libmesh_real( rb_theta_expansion->eval_F_theta(q_f1, mu) * libmesh_conj(rb_theta_expansion->eval_F_theta(q_f2, mu)) * Fq_representor_innerprods[q] ); q++; } } for(unsigned int q_f=0; q_f<rb_theta_expansion->get_n_F_terms(); q_f++) { for(unsigned int q_a=0; q_a<rb_theta_expansion->get_n_A_terms(); q_a++) { for(unsigned int i=0; i<N; i++) { Real delta = 2.; residual_norm_sq += delta * libmesh_real( rb_theta_expansion->eval_F_theta(q_f, mu) * libmesh_conj(rb_theta_expansion->eval_A_theta(q_a, mu)) * libmesh_conj(RB_solution(i)) * Fq_Aq_representor_innerprods[q_f][q_a][i] ); } } } q=0; for(unsigned int q_a1=0; q_a1<rb_theta_expansion->get_n_A_terms(); q_a1++) { for(unsigned int q_a2=q_a1; q_a2<rb_theta_expansion->get_n_A_terms(); q_a2++) { Real delta = (q_a1==q_a2) ? 1. : 2.; for(unsigned int i=0; i<N; i++) { for(unsigned int j=0; j<N; j++) { residual_norm_sq += delta * libmesh_real( libmesh_conj(rb_theta_expansion->eval_A_theta(q_a1, mu)) * rb_theta_expansion->eval_A_theta(q_a2, mu) * libmesh_conj(RB_solution(i)) * RB_solution(j) * Aq_Aq_representor_innerprods[q][i][j] ); } } q++; } } if(libmesh_real(residual_norm_sq) < 0.) { // libMesh::out << "Warning: Square of residual norm is negative " // << "in RBSystem::compute_residual_dual_norm()" << std::endl; // Sometimes this is negative due to rounding error, // but when this occurs the error is on the order of 1.e-10, // so shouldn't affect error bound much... residual_norm_sq = std::abs(residual_norm_sq); } STOP_LOG("compute_residual_dual_norm()", "RBEvaluation"); return std::sqrt( libmesh_real(residual_norm_sq) ); }
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.; } }