[P]arallel [Hi]gh-order [Li]brary for [P]DEs  Latest
Parallel High-Order Library for PDEs through hp-adaptive Discontinuous Galerkin methods
build_NNLS_problem.cpp
1 #include "build_NNLS_problem.h"
2 #include "reduced_order/pod_basis_offline.h"
3 #include "parameters/all_parameters.h"
4 #include "flow_solver/flow_solver.h"
5 #include "flow_solver/flow_solver_factory.h"
6 #include "ode_solver/ode_solver_factory.h"
7 #include "reduced_order/assemble_ECSW_residual.h"
8 #include "linear_solver/NNLS_solver.h"
9 #include "linear_solver/helper_functions.h"
10 #include "reduced_order/pod_adaptive_sampling.h"
11 #include "reduced_order/adaptive_sampling_base.h"
12 #include <iostream>
13 
14 namespace PHiLiP {
15 namespace Tests {
16 
17 template <int dim, int nstate>
19  const dealii::ParameterHandler &parameter_handler_input)
20  : TestsBase::TestsBase(parameters_input)
21  , parameter_handler(parameter_handler_input)
22 {}
23 
24 std::shared_ptr<Epetra_CrsMatrix> local_generate_test_basis(Parameters::ODESolverParam::ODESolverEnum ode_solver_type, Epetra_CrsMatrix &system_matrix, const Epetra_CrsMatrix &pod_basis){
26  if(ode_solver_type == ODEEnum::pod_galerkin_solver){
27  return std::make_shared<Epetra_CrsMatrix>(pod_basis);
28  }
29  else if(ode_solver_type == ODEEnum::pod_petrov_galerkin_solver){
30  Epetra_Map system_matrix_rowmap = system_matrix.RowMap();
31  Epetra_CrsMatrix petrov_galerkin_basis(Epetra_DataAccess::Copy, system_matrix_rowmap, pod_basis.NumGlobalCols());
32  EpetraExt::MatrixMatrix::Multiply(system_matrix, false, pod_basis, false, petrov_galerkin_basis, true);
33 
34  return std::make_shared<Epetra_CrsMatrix>(petrov_galerkin_basis);
35  }
36  else {
37  return nullptr;
38  }
39 }
40 
41 
42 template <int dim, int nstate>
44 {
45  Epetra_MpiComm Comm( MPI_COMM_WORLD );
46  // Create flow solver and adaptive sampling class instances
47  std::unique_ptr<FlowSolver::FlowSolver<dim,nstate>> flow_solver_petrov_galerkin = FlowSolver::FlowSolverFactory<dim,nstate>::select_flow_case(all_parameters, parameter_handler);
48  auto ode_solver_type = Parameters::ODESolverParam::ODESolverEnum::pod_petrov_galerkin_solver;
49  std::shared_ptr<AdaptiveSampling<dim,nstate>> parameter_sampling = std::make_unique<AdaptiveSampling<dim,nstate>>(all_parameters, parameter_handler);
50 
51  // Place minimum number of snapshots in the parameter space (3 snapshots in 1 parameter cases)
52  parameter_sampling->configureInitialParameterSpace();
53  parameter_sampling->placeInitialSnapshots();
54  parameter_sampling->current_pod->computeBasis();
55  MatrixXd snapshot_parameters = parameter_sampling->snapshot_parameters;
56 
57  // Create instance of NNLS Problem assembler
58  std::cout << "Construct instance of Assembler..."<< std::endl;
59  HyperReduction::AssembleECSWRes<dim,nstate> constructor_NNLS_problem(all_parameters, parameter_handler, flow_solver_petrov_galerkin->dg, parameter_sampling->current_pod, snapshot_parameters, ode_solver_type, Comm);
60 
61  // Add in FOM snapshots from sampling
62  constructor_NNLS_problem.fom_locations = parameter_sampling->fom_locations;
63 
64  std::cout << "Build Problem..."<< std::endl;
65  constructor_NNLS_problem.build_problem();
66 
67  /* UNCOMMENT TO SAVE THE RESIDUAL AND TEST BASIS FOR EACH OF THE SNAPSHOTS, used to feed MATLAB and build C/d
68  std::shared_ptr<DGBase<dim,double>> dg = flow_solver_petrov_galerkin->dg;
69  MatrixXd snapshotMatrix = parameter_sampling->current_pod->getSnapshotMatrix();
70  const Epetra_CrsMatrix epetra_pod_basis = parameter_sampling->current_pod->getPODBasis()->trilinos_matrix();
71  Epetra_CrsMatrix epetra_system_matrix = dg->system_matrix.trilinos_matrix();
72 
73  int N_e = dg->triangulation->n_active_cells(); // Number of elements (? should be the same as N ?)
74  int snap_num = 0;
75  for(auto snap_param : parameter_sampling->snapshot_parameters.rowwise()){
76  std::cout << "Extract Snapshot from matrix"<< std::endl;
77  dealii::LinearAlgebra::ReadWriteVector<double> snapshot_s;
78  snapshot_s.reinit(N_e);
79  for (int snap_row = 0; snap_row < N_e; snap_row++){
80  snapshot_s(snap_row) = snapshotMatrix(snap_row, snap_num);
81  }
82  dealii::LinearAlgebra::distributed::Vector<double> reference_solution(dg->solution);
83  reference_solution.import(snapshot_s, dealii::VectorOperation::values::insert);
84 
85  Parameters::AllParameters params = parameter_sampling->reinit_params(snap_param);
86 
87  std::unique_ptr<FlowSolver::FlowSolver<dim,nstate>> flow_solver = FlowSolver::FlowSolverFactory<dim,nstate>::select_flow_case(&params, parameter_handler);
88  dg = flow_solver->dg;
89 
90  std::cout << "Set dg solution to snapshot"<< std::endl;
91  dg->solution = reference_solution;
92  // reference_solution.print(std::cout, 7);
93  const bool compute_dRdW = true;
94  std::cout << "Re-compute the residual"<< std::endl;
95  dg->assemble_residual(compute_dRdW);
96 
97  std::cout << "Compute test basis with system matrix and pod basis"<< std::endl;
98  epetra_system_matrix = dg->system_matrix.trilinos_matrix();
99  std::shared_ptr<Epetra_CrsMatrix> epetra_test_basis = local_generate_test_basis(ode_solver_type, epetra_system_matrix, epetra_pod_basis);
100 
101 
102  std::cout << "Place residual in Epetra vector"<< std::endl;
103  // std::cout << "Residual"<< std::endl;
104  // dg->right_hand_side.print(std::cout);
105  Epetra_Vector epetra_right_hand_side(Epetra_DataAccess::Copy, epetra_system_matrix.RowMap(), dg->right_hand_side.begin());
106 
107 
108  snap_num +=1;
109 
110  std::ofstream out_file(std::to_string(snap_num) + "_residual.txt");
111  for(int i = 0 ; i < epetra_right_hand_side.GlobalLength() ; i++){
112  out_file << " " << std::setprecision(17) << epetra_right_hand_side[i] << " \n";
113  }
114  out_file.close();
115 
116  dealii::LAPACKFullMatrix<double> test_basis;
117  test_basis.reinit(epetra_test_basis->NumGlobalRows(), epetra_test_basis->NumGlobalCols());
118  for (int m = 0; m < epetra_test_basis->NumGlobalRows(); m++) {
119  double *row = (*epetra_test_basis)[m];
120  for (int n = 0; n < epetra_test_basis->NumGlobalCols(); n++) {
121  test_basis.set(m, n, row[n]);
122  }
123  }
124  std::ofstream basis_out_file(std::to_string(snap_num) + "_test_basis.txt");
125  unsigned int precision = 16;
126  test_basis.print_formatted(basis_out_file, precision);
127  }
128 
129  */
130  std::cout << "Load Matlab Results" << std::endl;
131  Eigen::MatrixXd C_MAT = load_csv<MatrixXd>("C.csv");
132  Eigen::MatrixXd d_MAT = load_csv<MatrixXd>("d.csv");
133  Eigen::MatrixXd x_MAT = load_csv<MatrixXd>("x.csv");
134 
135  const int rank = Comm.MyPID();
136  int rows = (constructor_NNLS_problem.A_T->trilinos_matrix()).NumGlobalCols();
137  Epetra_Map bMap(rows, (rank == 0) ? rows: 0, 0, Comm);
138  Epetra_Vector b_Epetra(bMap);
139  auto b = constructor_NNLS_problem.b;
140  unsigned int local_length = bMap.NumMyElements();
141  for(unsigned int i = 0 ; i < local_length ; i++){
142  b_Epetra[i] = b(i);
143  }
144 
145  // Build NNLS Solver with C and d
146  // Solver parameters
147  std::cout << "Create NNLS problem..."<< std::endl;
148  std::cout << all_parameters->hyper_reduction_param.NNLS_tol << std::endl;
149  std::cout << all_parameters->hyper_reduction_param.NNLS_max_iter << std::endl;
150  NNLSSolver NNLS_prob(all_parameters, parameter_handler, constructor_NNLS_problem.A_T->trilinos_matrix(), true, Comm, b_Epetra);
151  std::cout << "Solve NNLS problem..."<< std::endl;
152  // Solve NNLS problem (should return 1 if solver achieves the accuracy tau before the max number of iterations)
153  bool exit_con = NNLS_prob.solve();
154 
155  // Extract the weights
156  Epetra_Vector weights = NNLS_prob.get_solution();
157  Eigen::MatrixXd weights_eig(weights.GlobalLength(),1);
158  epetra_to_eig_vec(weights.GlobalLength(), weights , weights_eig);
159 
160  // Compare with the MATLAB results (expected to be close but not identical)
161  exit_con &= x_MAT.isApprox(weights_eig, 1E-2);
162 
163  std::cout << "ECSW Weights"<< std::endl;
164  std::cout << weights << std::endl;
165 
166  return !exit_con;
167 }
168 
169 #if PHILIP_DIM==1
171 #endif
172 
173 #if PHILIP_DIM!=1
175 #endif
176 } // Tests namespace
177 } // PHiLiP namespace
std::vector< dealii::LinearAlgebra::distributed::Vector< double > > fom_locations
Vector of parameter-ROMTestLocation pairs.
std::shared_ptr< dealii::TrilinosWrappers::SparseMatrix > A_T
Matrix for the NNLS Problem.
Files for the baseline physics.
Definition: ADTypes.hpp:10
Main parameter class that contains the various other sub-parameter classes.
static std::unique_ptr< FlowSolver< dim, nstate > > select_flow_case(const Parameters::AllParameters *const parameters_input, const dealii::ParameterHandler &parameter_handler_input)
Factory to return the correct flow solver given input file.
const Parameters::AllParameters *const all_parameters
Pointer to all parameters.
Definition: tests.h:20
dealii::LinearAlgebra::ReadWriteVector< double > b
RHS Vector for the NNLS Problem.
const dealii::ParameterHandler & parameter_handler
Dummy parameter handler because flowsolver requires it.
bool solve()
Call to solve NNLS problem.
BuildNNLSProblem(const Parameters::AllParameters *const parameters_input, const dealii::ParameterHandler &parameter_handler_input)
Constructor.
int run_test() const override
Run Assemble Problem ECSW.
Base class of all the tests.
Definition: tests.h:17
void build_problem() override
Fill entries of A and b.