void RBEIMEvaluation::initialize_eim_theta_objects() { // Initialize the rb_theta objects that access the solution from this rb_eim_evaluation _rb_eim_theta_objects.clear(); for(unsigned int i=0; i<get_n_basis_functions(); i++) { _rb_eim_theta_objects.push_back( build_eim_theta(i).release() ); } }
void RBEIMEvaluation::rb_solve(DenseVector<Number> & EIM_rhs) { LOG_SCOPE("rb_solve()", "RBEIMEvaluation"); if(EIM_rhs.size() > get_n_basis_functions()) libmesh_error_msg("ERROR: N cannot be larger than the number of basis functions in rb_solve"); if(EIM_rhs.size()==0) libmesh_error_msg("ERROR: N must be greater than 0 in rb_solve"); const unsigned int N = EIM_rhs.size(); DenseMatrix<Number> interpolation_matrix_N; interpolation_matrix.get_principal_submatrix(N, interpolation_matrix_N); interpolation_matrix_N.lu_solve(EIM_rhs, RB_solution); }
void RBEIMEvaluation::rb_solve(DenseVector<Number>& EIM_rhs) { START_LOG("rb_solve()", "RBEIMEvaluation"); if(EIM_rhs.size() > 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(EIM_rhs.size()==0) { libMesh::err << "ERROR: N must be greater than 0 in rb_solve" << std::endl; libmesh_error(); } const unsigned int N = EIM_rhs.size(); DenseMatrix<Number> interpolation_matrix_N; interpolation_matrix.get_principal_submatrix(N, interpolation_matrix_N); interpolation_matrix_N.lu_solve(EIM_rhs, RB_solution); STOP_LOG("rb_solve()", "RBEIMEvaluation"); }
void RBEIMEvaluation::legacy_write_offline_data_to_files(const std::string & directory_name, const bool read_binary_data) { LOG_SCOPE("legacy_write_offline_data_to_files()", "RBEIMEvaluation"); Parent::legacy_write_offline_data_to_files(directory_name); // Get the number of basis functions unsigned int n_bfs = get_n_basis_functions(); // The writing mode: ENCODE for binary, WRITE for ASCII XdrMODE mode = read_binary_data ? ENCODE : WRITE; // The suffix to use for all the files that are written out const std::string suffix = read_binary_data ? ".xdr" : ".dat"; if(this->processor_id() == 0) { std::ostringstream file_name; // Next write out the interpolation_matrix file_name.str(""); file_name << directory_name << "/interpolation_matrix" << suffix; Xdr interpolation_matrix_out(file_name.str(), mode); for(unsigned int i=0; i<n_bfs; i++) { for(unsigned int j=0; j<=i; j++) { interpolation_matrix_out << interpolation_matrix(i,j); } } // Next write out interpolation_points file_name.str(""); file_name << directory_name << "/interpolation_points" << suffix; Xdr interpolation_points_out(file_name.str(), mode); for(unsigned int i=0; i<n_bfs; i++) { interpolation_points_out << interpolation_points[i](0); if(LIBMESH_DIM >= 2) interpolation_points_out << interpolation_points[i](1); if(LIBMESH_DIM >= 3) interpolation_points_out << interpolation_points[i](2); } interpolation_points_out.close(); // Next write out interpolation_points_var file_name.str(""); file_name << directory_name << "/interpolation_points_var" << suffix; Xdr interpolation_points_var_out(file_name.str(), mode); for(unsigned int i=0; i<n_bfs; i++) { interpolation_points_var_out << interpolation_points_var[i]; } interpolation_points_var_out.close(); } // Write out the elements associated with the interpolation points. // This uses mesh I/O, hence we have to do it on all processors. legacy_write_out_interpolation_points_elem(directory_name); }
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.; } }
void RBEvaluation::write_offline_data_to_files(const std::string& directory_name, const bool write_binary_data) { START_LOG("write_offline_data_to_files()", "RBEvaluation"); // Get the number of basis functions unsigned int n_bfs = get_n_basis_functions(); // The writing mode: ENCODE for binary, WRITE for ASCII XdrMODE mode = write_binary_data ? ENCODE : WRITE; // The suffix to use for all the files that are written out const std::string suffix = write_binary_data ? ".xdr" : ".dat"; if(this->processor_id() == 0) { // Make a directory to store all the data files mkdir(directory_name.c_str(), 0777); // if( mkdir(directory_name.c_str(), 0777) == -1) // { // libMesh::out << "In RBEvaluation::write_offline_data_to_files, directory " // << directory_name << " already exists, overwriting contents." << std::endl; // } // First, write out how many basis functions we have generated std::ostringstream file_name; { file_name << directory_name << "/n_bfs" << suffix; Xdr n_bfs_out(file_name.str(), mode); n_bfs_out << n_bfs; n_bfs_out.close(); } // Write out the parameter ranges file_name.str(""); file_name << directory_name << "/parameter_ranges" << suffix; std::string continuous_param_file_name = file_name.str(); // Write out the discrete parameter values file_name.str(""); file_name << directory_name << "/discrete_parameter_values" << suffix; std::string discrete_param_file_name = file_name.str(); write_parameter_data_to_files(continuous_param_file_name, discrete_param_file_name, write_binary_data); // Write out Fq representor norm data file_name.str(""); file_name << directory_name << "/Fq_innerprods" << suffix; Xdr RB_Fq_innerprods_out(file_name.str(), mode); unsigned int Q_f_hat = rb_theta_expansion->get_n_F_terms()*(rb_theta_expansion->get_n_F_terms()+1)/2; for(unsigned int i=0; i<Q_f_hat; i++) { RB_Fq_innerprods_out << Fq_representor_innerprods[i]; } RB_Fq_innerprods_out.close(); // Write out output data for(unsigned int n=0; n<rb_theta_expansion->get_n_outputs(); n++) { file_name.str(""); file_name << directory_name << "/output_"; file_name << std::setw(3) << std::setprecision(0) << std::setfill('0') << std::right << n; file_name << "_dual_innerprods" << suffix; Xdr output_dual_innerprods_out(file_name.str(), mode); unsigned int Q_l_hat = rb_theta_expansion->get_n_output_terms(n)*(rb_theta_expansion->get_n_output_terms(n)+1)/2; for(unsigned int q=0; q<Q_l_hat; q++) { output_dual_innerprods_out << output_dual_innerprods[n][q]; } output_dual_innerprods_out.close(); } // Write out output data to multiple files for(unsigned int n=0; n<rb_theta_expansion->get_n_outputs(); n++) { for(unsigned int q_l=0; q_l<rb_theta_expansion->get_n_output_terms(n); q_l++) { file_name.str(""); file_name << directory_name << "/output_"; file_name << std::setw(3) << std::setprecision(0) << std::setfill('0') << std::right << n; file_name << "_"; file_name << std::setw(3) << std::setprecision(0) << std::setfill('0') << std::right << q_l; file_name << suffix; Xdr output_n_out(file_name.str(), mode); for(unsigned int j=0; j<n_bfs; j++) { output_n_out << RB_output_vectors[n][q_l](j); } output_n_out.close(); } } if(compute_RB_inner_product) { // Next write out the inner product matrix file_name.str(""); file_name << directory_name << "/RB_inner_product_matrix" << suffix; Xdr RB_inner_product_matrix_out(file_name.str(), mode); for(unsigned int i=0; i<n_bfs; i++) { for(unsigned int j=0; j<n_bfs; j++) { RB_inner_product_matrix_out << RB_inner_product_matrix(i,j); } } RB_inner_product_matrix_out.close(); } // Next write out the Fq vectors for(unsigned int q_f=0; q_f<rb_theta_expansion->get_n_F_terms(); q_f++) { file_name.str(""); file_name << directory_name << "/RB_F_"; file_name << std::setw(3) << std::setprecision(0) << std::setfill('0') << std::right << q_f; file_name << suffix; Xdr RB_Fq_f_out(file_name.str(), mode); for(unsigned int i=0; i<n_bfs; i++) { RB_Fq_f_out << RB_Fq_vector[q_f](i); } RB_Fq_f_out.close(); } // Next write out the Aq matrices for(unsigned int q_a=0; q_a<rb_theta_expansion->get_n_A_terms(); q_a++) { file_name.str(""); file_name << directory_name << "/RB_A_"; file_name << std::setw(3) << std::setprecision(0) << std::setfill('0') << std::right << q_a; file_name << suffix; Xdr RB_Aq_a_out(file_name.str(), mode); for(unsigned int i=0; i<n_bfs; i++) { for(unsigned int j=0; j<n_bfs; j++) { RB_Aq_a_out << RB_Aq_vector[q_a](i,j); } } RB_Aq_a_out.close(); } // Next write out Fq_Aq representor norm data file_name.str(""); file_name << directory_name << "/Fq_Aq_innerprods" << suffix; Xdr RB_Fq_Aq_innerprods_out(file_name.str(), mode); 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_bfs; i++) { RB_Fq_Aq_innerprods_out << Fq_Aq_representor_innerprods[q_f][q_a][i]; } } } RB_Fq_Aq_innerprods_out.close(); // Next write out Aq_Aq representor norm data file_name.str(""); file_name << directory_name << "/Aq_Aq_innerprods" << suffix; Xdr RB_Aq_Aq_innerprods_out(file_name.str(), mode); unsigned int Q_a_hat = rb_theta_expansion->get_n_A_terms()*(rb_theta_expansion->get_n_A_terms()+1)/2; for(unsigned int i=0; i<Q_a_hat; i++) { for(unsigned int j=0; j<n_bfs; j++) { for(unsigned int l=0; l<n_bfs; l++) { RB_Aq_Aq_innerprods_out << Aq_Aq_representor_innerprods[i][j][l]; } } } RB_Aq_Aq_innerprods_out.close(); // Also, write out the greedily selected parameters { file_name.str(""); file_name << directory_name << "/greedy_params" << suffix; Xdr greedy_params_out(file_name.str(), mode); for(unsigned int i=0; i<greedy_param_list.size(); i++) { RBParameters::const_iterator it = greedy_param_list[i].begin(); RBParameters::const_iterator it_end = greedy_param_list[i].end(); for( ; it != it_end; ++it) { // Need to make a copy of the value so that it's not const // Xdr is not templated on const's Real param_value = it->second; greedy_params_out << param_value; } } greedy_params_out.close(); } } STOP_LOG("write_offline_data_to_files()", "RBEvaluation"); }
Real RBEvaluation::rb_solve(unsigned int N) { START_LOG("rb_solve()", "RBEvaluation"); if(N > get_n_basis_functions()) libmesh_error_msg("ERROR: N cannot be larger than the number of basis functions in rb_solve"); const RBParameters& mu = get_parameters(); // Resize (and clear) the solution vector RB_solution.resize(N); // Assemble the RB system DenseMatrix<Number> RB_system_matrix(N,N); RB_system_matrix.zero(); DenseMatrix<Number> RB_Aq_a; for(unsigned int q_a=0; q_a<rb_theta_expansion->get_n_A_terms(); q_a++) { RB_Aq_vector[q_a].get_principal_submatrix(N, RB_Aq_a); RB_system_matrix.add(rb_theta_expansion->eval_A_theta(q_a, mu), RB_Aq_a); } // Assemble the RB rhs DenseVector<Number> RB_rhs(N); RB_rhs.zero(); DenseVector<Number> RB_Fq_f; for(unsigned int q_f=0; q_f<rb_theta_expansion->get_n_F_terms(); q_f++) { RB_Fq_vector[q_f].get_principal_subvector(N, RB_Fq_f); RB_rhs.add(rb_theta_expansion->eval_F_theta(q_f, mu), RB_Fq_f); } // Solve the linear system if(N > 0) { RB_system_matrix.lu_solve(RB_rhs, RB_solution); } // Evaluate RB outputs DenseVector<Number> RB_output_vector_N; for(unsigned int n=0; n<rb_theta_expansion->get_n_outputs(); n++) { RB_outputs[n] = 0.; for(unsigned int q_l=0; q_l<rb_theta_expansion->get_n_output_terms(n); q_l++) { RB_output_vectors[n][q_l].get_principal_subvector(N, RB_output_vector_N); RB_outputs[n] += rb_theta_expansion->eval_output_theta(n,q_l,mu)*RB_output_vector_N.dot(RB_solution); } } if(evaluate_RB_error_bound) // Calculate the error bounds { // Evaluate the dual norm of the residual for RB_solution_vector Real epsilon_N = compute_residual_dual_norm(N); // Get lower bound for coercivity constant const Real alpha_LB = get_stability_lower_bound(); // alpha_LB needs to be positive to get a valid error bound libmesh_assert_greater ( alpha_LB, 0. ); // Evaluate the (absolute) error bound Real abs_error_bound = epsilon_N / residual_scaling_denom(alpha_LB); // Now compute the output error bounds for(unsigned int n=0; n<rb_theta_expansion->get_n_outputs(); n++) { RB_output_error_bounds[n] = abs_error_bound * eval_output_dual_norm(n, mu); } STOP_LOG("rb_solve()", "RBEvaluation"); return abs_error_bound; } else // Don't calculate the error bounds { STOP_LOG("rb_solve()", "RBEvaluation"); // Just return -1. if we did not compute the error bound return -1.; } }
void RBEIMEvaluation::write_offline_data_to_files(const std::string& directory_name, const bool read_binary_data) { START_LOG("write_offline_data_to_files()", "RBEIMEvaluation"); Parent::write_offline_data_to_files(directory_name); // Get the number of basis functions unsigned int n_bfs = get_n_basis_functions(); // The writing mode: ENCODE for binary, WRITE for ASCII XdrMODE mode = read_binary_data ? ENCODE : WRITE; // The suffix to use for all the files that are written out const std::string suffix = read_binary_data ? ".xdr" : ".dat"; if(libMesh::processor_id() == 0) { OStringStream file_name; // Next write out the interpolation_matrix file_name.str(""); file_name << directory_name << "/interpolation_matrix" << suffix; Xdr interpolation_matrix_out(file_name.str(), mode); for(unsigned int i=0; i<n_bfs; i++) { for(unsigned int j=0; j<=i; j++) { interpolation_matrix_out << interpolation_matrix(i,j); } } // Also, write out the "extra" row file_name.str(""); file_name << directory_name << "/extra_interpolation_matrix_row" << suffix; Xdr extra_interpolation_matrix_row_out(file_name.str(), mode); for(unsigned int j=0; j<n_bfs; j++) { extra_interpolation_matrix_row_out << extra_interpolation_matrix_row(j); } extra_interpolation_matrix_row_out.close(); // Next write out interpolation_points file_name.str(""); file_name << directory_name << "/interpolation_points" << suffix; Xdr interpolation_points_out(file_name.str(), mode); for(unsigned int i=0; i<n_bfs; i++) { interpolation_points_out << interpolation_points[i](0); if(LIBMESH_DIM >= 2) interpolation_points_out << interpolation_points[i](1); if(LIBMESH_DIM >= 3) interpolation_points_out << interpolation_points[i](2); } interpolation_points_out.close(); // Also, write out the "extra" interpolation point file_name.str(""); file_name << directory_name << "/extra_interpolation_point" << suffix; Xdr extra_interpolation_point_out(file_name.str(), mode); extra_interpolation_point_out << extra_interpolation_point(0); if(LIBMESH_DIM >= 2) extra_interpolation_point_out << extra_interpolation_point(1); if(LIBMESH_DIM >= 3) extra_interpolation_point_out << extra_interpolation_point(2); extra_interpolation_point_out.close(); // Next write out interpolation_points_var file_name.str(""); file_name << directory_name << "/interpolation_points_var" << suffix; Xdr interpolation_points_var_out(file_name.str(), mode); for(unsigned int i=0; i<n_bfs; i++) { interpolation_points_var_out << interpolation_points_var[i]; } interpolation_points_var_out.close(); // Also, write out the "extra" interpolation variable file_name.str(""); file_name << directory_name << "/extra_interpolation_point_var" << suffix; Xdr extra_interpolation_point_var_out(file_name.str(), mode); extra_interpolation_point_var_out << extra_interpolation_point_var; extra_interpolation_point_var_out.close(); } STOP_LOG("write_offline_data_to_files()", "RBEIMEvaluation"); }
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.; } }