[P]arallel [Hi]gh-order [Li]brary for [P]DEs  Latest
Parallel High-Order Library for PDEs through hp-adaptive Discontinuous Galerkin methods
hyper_reduced_sampling_error_updated.cpp
1 #include "hyper_reduced_sampling_error_updated.h"
2 #include <iostream>
3 #include <filesystem>
4 #include "functional/functional.h"
5 #include <deal.II/lac/trilinos_sparse_matrix.h>
6 #include <deal.II/lac/vector_operation.h>
7 #include "reduced_order_solution.h"
8 #include "flow_solver/flow_solver.h"
9 #include "flow_solver/flow_solver_factory.h"
10 #include <cmath>
11 #include "rbf_interpolation.h"
12 #include "ROL_Algorithm.hpp"
13 #include "ROL_LineSearchStep.hpp"
14 #include "ROL_StatusTest.hpp"
15 #include "ROL_Stream.hpp"
16 #include "ROL_Bounds.hpp"
17 #include "halton.h"
18 #include "min_max_scaler.h"
19 #include "pod_adaptive_sampling.h"
20 #include "assemble_ECSW_residual.h"
21 #include "assemble_ECSW_jacobian.h"
22 #include "linear_solver/NNLS_solver.h"
23 #include "linear_solver/helper_functions.h"
24 
25 namespace PHiLiP {
26 
27 template<int dim, int nstate>
29  const dealii::ParameterHandler &parameter_handler_input)
30  : AdaptiveSamplingBase<dim, nstate>(parameters_input, parameter_handler_input)
31 { }
32 
33 template <int dim, int nstate>
35 {
36  this->pcout << "Starting adaptive sampling process" << std::endl;
37  auto stream = this->pcout;
38  dealii::TimerOutput timer(stream,dealii::TimerOutput::summary,dealii::TimerOutput::wall_times);
39  int iteration = 0;
40  timer.enter_subsection ("Iteration " + std::to_string(iteration));
41 
42  std::unique_ptr<FlowSolver::FlowSolver<dim,nstate>> flow_solver = FlowSolver::FlowSolverFactory<dim,nstate>::select_flow_case(this->all_parameters, this->parameter_handler);
43 
44  this->placeInitialSnapshots();
45  this->current_pod->computeBasis();
46 
47  auto ode_solver_type_HROM = Parameters::ODESolverParam::ODESolverEnum::hyper_reduced_petrov_galerkin_solver;
48 
49  // Find C and d for NNLS Problem
50  Epetra_MpiComm Comm( MPI_COMM_WORLD );
51  this->pcout << "Construct instance of Assembler..."<< std::endl;
52  std::unique_ptr<HyperReduction::AssembleECSWBase<dim,nstate>> constructor_NNLS_problem;
53  if (this->all_parameters->hyper_reduction_param.training_data == "residual")
54  constructor_NNLS_problem = std::make_unique<HyperReduction::AssembleECSWRes<dim,nstate>>(this->all_parameters, this->parameter_handler, flow_solver->dg, this->current_pod, this->snapshot_parameters, ode_solver_type_HROM, Comm);
55  else {
56  constructor_NNLS_problem = std::make_unique<HyperReduction::AssembleECSWJac<dim,nstate>>(this->all_parameters, this->parameter_handler, flow_solver->dg, this->current_pod, this->snapshot_parameters, ode_solver_type_HROM, Comm);
57  }
58 
59  for (int k = 0; k < this->snapshot_parameters.rows(); k++){
60  constructor_NNLS_problem->update_snapshots(std::move(this->fom_locations[k]));
61  }
62 
63  this->pcout << "Build Problem..."<< std::endl;
64  constructor_NNLS_problem->build_problem();
65 
66  // Transfer b vector (RHS of NNLS problem) to Epetra structure
67  const int rank = Comm.MyPID();
68  int rows = (constructor_NNLS_problem->A_T->trilinos_matrix()).NumGlobalCols();
69  Epetra_Map bMap(rows, (rank == 0) ? rows: 0, 0, Comm);
70  Epetra_Vector b_Epetra(bMap);
71  auto b = constructor_NNLS_problem->b;
72  unsigned int local_length = bMap.NumMyElements();
73  for(unsigned int i = 0 ; i < local_length ; i++){
74  b_Epetra[i] = b(i);
75  }
76 
77  // Solve NNLS Problem for ECSW weights
78  this->pcout << "Create NNLS problem..."<< std::endl;
79  NNLSSolver NNLS_prob(this->all_parameters, this->parameter_handler, constructor_NNLS_problem->A_T->trilinos_matrix(), true, Comm, b_Epetra);
80  this->pcout << "Solve NNLS problem..."<< std::endl;
81  bool exit_con = NNLS_prob.solve();
82  this->pcout << exit_con << std::endl;
83 
84  ptr_weights = std::make_shared<Epetra_Vector>(NNLS_prob.get_solution());
85 
86  MatrixXd rom_points = this->nearest_neighbors->kPairwiseNearestNeighborsMidpoint();
87  this->pcout << "ROM Points"<< std::endl;
88  this->pcout << rom_points << std::endl;
89 
90  this->placeROMLocations(rom_points, *ptr_weights);
91 
92  RowVectorXd max_error_params = this->getMaxErrorROM();
93 
94  RowVectorXd functional_ROM = this->readROMFunctionalPoint();
95 
96  this->pcout << "Solving FOM at " << functional_ROM << std::endl;
97 
98  Parameters::AllParameters params = this->reinit_params(functional_ROM);
99  std::unique_ptr<FlowSolver::FlowSolver<dim,nstate>> flow_solver_FOM = FlowSolver::FlowSolverFactory<dim,nstate>::select_flow_case(&params, this->parameter_handler);
100 
101  // Solve implicit solution
102  auto ode_solver_type = Parameters::ODESolverParam::ODESolverEnum::implicit_solver;
103  flow_solver_FOM->ode_solver = PHiLiP::ODE::ODESolverFactory<dim, double>::create_ODESolver_manual(ode_solver_type, flow_solver_FOM->dg);
104  flow_solver_FOM->ode_solver->allocate_ode_system();
105  flow_solver_FOM->run();
106 
107  // Create functional
108  std::shared_ptr<Functional<dim,nstate,double>> functional_FOM = FunctionalFactory<dim,nstate,double>::create_Functional(params.functional_param, flow_solver_FOM->dg);
109  this->pcout << "FUNCTIONAL FROM FOM" << std::endl;
110  this->pcout << functional_FOM->evaluate_functional(false, false) << std::endl;
111 
112  solveFunctionalHROM(functional_ROM, *ptr_weights);
113 
114  while(this->max_error > this->all_parameters->reduced_order_param.adaptation_tolerance){
115  Epetra_Vector local_weights = allocateVectorToSingleCore(*ptr_weights);
116  this->outputIterationData(std::to_string(iteration));
117 
118  std::unique_ptr<dealii::TableHandler> weights_table = std::make_unique<dealii::TableHandler>();
119  for(int i = 0 ; i < local_weights.MyLength() ; i++){
120  weights_table->add_value("ECSW Weights", local_weights[i]);
121  weights_table->set_precision("ECSW Weights", 16);
122  }
123 
124  std::ofstream weights_table_file("weights_table_iteration_" + std::to_string(iteration) + ".txt");
125  weights_table->write_text(weights_table_file, dealii::TableHandler::TextOutputFormat::org_mode_table);
126  weights_table_file.close();
127 
128  dealii::Vector<double> weights_dealii(ptr_weights->MyLength());
129  for(int j = 0 ; j < ptr_weights->MyLength() ; j++){
130  weights_dealii[j] = (*ptr_weights)[j];
131  }
132  flow_solver->dg->reduced_mesh_weights = weights_dealii;
133  flow_solver->dg->output_results_vtk(iteration);
134 
135  timer.leave_subsection();
136  timer.enter_subsection ("Iteration " + std::to_string(iteration+1));
137 
138  this->pcout << "Sampling snapshot at " << max_error_params << std::endl;
139  dealii::LinearAlgebra::distributed::Vector<double> fom_solution = this->solveSnapshotFOM(max_error_params);
140  this->snapshot_parameters.conservativeResize(this->snapshot_parameters.rows()+1, this->snapshot_parameters.cols());
141  this->snapshot_parameters.row(this->snapshot_parameters.rows()-1) = max_error_params;
142  this->nearest_neighbors->update_snapshots(this->snapshot_parameters, fom_solution);
143  this->current_pod->addSnapshot(fom_solution);
144  this->fom_locations.emplace_back(fom_solution);
145  this->current_pod->computeBasis();
146 
147  // Find C and d for NNLS Problem
148  this->pcout << "Update Assembler..."<< std::endl;
149  constructor_NNLS_problem->update_POD_snaps(this->current_pod, this->snapshot_parameters);
150  constructor_NNLS_problem->update_snapshots(fom_solution);
151  this->pcout << "Build Problem..."<< std::endl;
152  constructor_NNLS_problem->build_problem();
153 
154  // Transfer b vector (RHS of NNLS problem) to Epetra structure
155  int rows = (constructor_NNLS_problem->A_T->trilinos_matrix()).NumGlobalCols();
156  Epetra_Map bMap(rows, (rank == 0) ? rows: 0, 0, Comm);
157  Epetra_Vector b_Epetra(bMap);
158  auto b = constructor_NNLS_problem->b;
159  unsigned int local_length = bMap.NumMyElements();
160  for(unsigned int i = 0 ; i < local_length ; i++){
161  b_Epetra[i] = b(i);
162  }
163 
164  // Solve NNLS Problem for ECSW weights
165  this->pcout << "Create NNLS problem..."<< std::endl;
166  NNLSSolver NNLS_prob(this->all_parameters, this->parameter_handler, constructor_NNLS_problem->A_T->trilinos_matrix(), true, Comm, b_Epetra);
167  this->pcout << "Solve NNLS problem..."<< std::endl;
168  bool exit_con = NNLS_prob.solve();
169  this->pcout << exit_con << std::endl;
170 
171  ptr_weights = std::make_shared<Epetra_Vector>(NNLS_prob.get_solution());
172 
173  // Update previous ROM errors with updated current_pod
174  for(auto it = hrom_locations.begin(); it != hrom_locations.end(); ++it){
175  it->get()->compute_initial_rom_to_final_rom_error(this->current_pod);
176  it->get()->compute_total_error();
177  }
178 
179  this->updateNearestExistingROMs(max_error_params, *ptr_weights);
180 
181  rom_points = this->nearest_neighbors->kNearestNeighborsMidpoint(max_error_params);
182  this->pcout << rom_points << std::endl;
183 
184  this->placeROMLocations(rom_points, *ptr_weights);
185 
186  // Update max error
187  max_error_params = this->getMaxErrorROM();
188 
189  this->pcout << "Max error is: " << this->max_error << std::endl;
190 
191  solveFunctionalHROM(functional_ROM, *ptr_weights);
192 
193  this->pcout << "FUNCTIONAL FROM ROMs" << std::endl;
194  std::ofstream output_file("rom_functional" + std::to_string(iteration+1) +".txt");
195 
196  std::ostream_iterator<double> output_iterator(output_file, "\n");
197  std::copy(std::begin(rom_functional), std::end(rom_functional), output_iterator);
198 
199  iteration++;
200 
201  // Exit statement for loop if the total number of iterations is greater than the FOM dimension N (i.e. the reduced-order basis dimension n is equal to N)
202  if (iteration > local_weights.MyLength()){
203  break;
204  }
205  }
206 
207  Epetra_Vector local_weights = allocateVectorToSingleCore(*ptr_weights);
208  this->outputIterationData("final");
209  std::unique_ptr<dealii::TableHandler> weights_table = std::make_unique<dealii::TableHandler>();
210  for(int i = 0 ; i < local_weights.MyLength() ; i++){
211  weights_table->add_value("ECSW Weights", local_weights[i]);
212  weights_table->set_precision("ECSW Weights", 16);
213  }
214 
215  dealii::Vector<double> weights_dealii(local_weights.MyLength());
216  for(int j = 0 ; j < local_weights.MyLength() ; j++){
217  weights_dealii[j] = local_weights[j];
218  }
219  std::ofstream weights_table_file("weights_table_iteration_final.txt");
220  weights_table->write_text(weights_table_file, dealii::TableHandler::TextOutputFormat::org_mode_table);
221  weights_table_file.close();
222 
223  flow_solver->dg->reduced_mesh_weights = weights_dealii;
224  flow_solver->dg->output_results_vtk(iteration);
225 
226  timer.leave_subsection();
227 
228  this->pcout << "FUNCTIONAL FROM ROMs" << std::endl;
229  std::ofstream output_file("rom_functional.txt");
230 
231  std::ostream_iterator<double> output_iterator(output_file, "\n");
232  std::copy(std::begin(rom_functional), std::end(rom_functional), output_iterator);
233 
234  return 0;
235 }
236 
237 template <int dim, int nstate>
239  this->pcout << "Updating RBF interpolation..." << std::endl;
240 
241  int n_rows = this->snapshot_parameters.rows() + hrom_locations.size();
242  MatrixXd parameters(n_rows, this->snapshot_parameters.cols());
243  VectorXd errors(n_rows);
244 
245  int i;
246  // Loop through FOM snapshot locations and add zero error to errors vector
247  for(i = 0 ; i < this->snapshot_parameters.rows() ; i++){
248  errors(i) = 0;
249  parameters.row(i) = this->snapshot_parameters.row(i);
250  }
251  this->pcout << i << std::endl;
252  // Loop through ROM points and add total error to errors vector (both FOM snaps and ROM points are used to build RBF)
253  for(auto it = hrom_locations.begin(); it != hrom_locations.end(); ++it){
254  parameters.row(i) = it->get()->parameter.array();
255  errors(i) = it->get()->total_error;
256  i++;
257  }
258 
259  // Must scale both axes between [0,1] for the 2d rbf interpolation to work optimally
261  MatrixXd parameters_scaled = scaler.fit_transform(parameters);
262 
263  // Construct radial basis function
264  std::string kernel = "thin_plate_spline";
266 
267  // Set parameters.
268  ROL::ParameterList parlist;
269  parlist.sublist("Step").sublist("Line Search").sublist("Line-Search Method").set("Type","Backtracking");
270  parlist.sublist("Step").sublist("Line Search").sublist("Descent Method").set("Type","Quasi-Newton Method");
271  parlist.sublist("Step").sublist("Line Search").sublist("Secant").set("Type","Limited-Memory BFGS");
272  parlist.sublist("Status Test").set("Gradient Tolerance",1.e-10);
273  parlist.sublist("Status Test").set("Step Tolerance",1.e-14);
274  parlist.sublist("Status Test").set("Iteration Limit",100);
275 
276  // Find max error and parameters by minimizing function starting at each ROM location
277  RowVectorXd max_error_params(parameters.cols());
278  this->max_error = 0;
279 
280  for(auto it = hrom_locations.begin(); it != hrom_locations.end(); ++it){
281 
282  Eigen::RowVectorXd rom_unscaled = it->get()->parameter;
283  Eigen::RowVectorXd rom_scaled = scaler.transform(rom_unscaled);
284 
285  //start bounds
286  int dimension = parameters.cols();
287  ROL::Ptr<std::vector<double>> l_ptr = ROL::makePtr<std::vector<double>>(dimension,0.0);
288  ROL::Ptr<std::vector<double>> u_ptr = ROL::makePtr<std::vector<double>>(dimension,1.0);
289  ROL::Ptr<ROL::Vector<double>> lo = ROL::makePtr<ROL::StdVector<double>>(l_ptr);
290  ROL::Ptr<ROL::Vector<double>> up = ROL::makePtr<ROL::StdVector<double>>(u_ptr);
291  ROL::Bounds<double> bcon(lo,up);
292  //end bounds
293 
294  ROL::Ptr<ROL::Step<double>> step = ROL::makePtr<ROL::LineSearchStep<double>>(parlist);
295  ROL::Ptr<ROL::StatusTest<double>> status = ROL::makePtr<ROL::StatusTest<double>>(parlist);
296  ROL::Algorithm<double> algo(step,status,false);
297 
298  // Iteration Vector
299  ROL::Ptr<std::vector<double>> x_ptr = ROL::makePtr<std::vector<double>>(dimension, 0.0);
300 
301  // Set Initial Guess
302  for(int j = 0 ; j < dimension ; j++){
303  (*x_ptr)[j] = rom_scaled(j);
304  }
305 
306  this->pcout << "Unscaled parameter: " << rom_unscaled << std::endl;
307  this->pcout << "Scaled parameter: ";
308  for(int j = 0 ; j < dimension ; j++){
309  this->pcout << (*x_ptr)[j] << " ";
310  }
311  this->pcout << std::endl;
312 
313  ROL::StdVector<double> x(x_ptr);
314 
315  // Run Algorithm
316  algo.run(x, rbf, bcon,false);
317 
318  ROL::Ptr<std::vector<double>> x_min = x.getVector();
319 
320  for(int j = 0 ; j < dimension ; j++){
321  rom_scaled(j) = (*x_min)[j];
322  }
323 
324  RowVectorXd rom_unscaled_optim = scaler.inverse_transform(rom_scaled);
325 
326  this->pcout << "Parameters of optimization convergence: " << rom_unscaled_optim << std::endl;
327 
328  double error = std::abs(rbf.evaluate(rom_scaled));
329  this->pcout << "RBF error at optimization convergence: " << error << std::endl;
330  if(error > this->max_error){
331  this->pcout << "RBF error is greater than current max error. Updating max error." << std::endl;
332  this->max_error = error;
333  max_error_params = rom_unscaled_optim;
334  this->pcout << "RBF Max error: " << this->max_error << std::endl;
335  }
336  }
337 
338  // Check if max_error_params is a ROM point
339  for(auto it = hrom_locations.begin(); it != hrom_locations.end(); ++it){
340  if(max_error_params.isApprox(it->get()->parameter)){
341  this->pcout << "Max error location is approximately the same as a ROM location. Removing ROM location." << std::endl;
342  hrom_locations.erase(it);
343  break;
344  }
345  }
346 
347  return max_error_params;
348 }
349 
350 
351 template <int dim, int nstate>
352 bool HyperreducedSamplingErrorUpdated<dim, nstate>::placeROMLocations(const MatrixXd& rom_points, Epetra_Vector weights) const{
353  bool error_greater_than_tolerance = false;
354  std::unique_ptr<FlowSolver::FlowSolver<dim,nstate>> flow_solver = FlowSolver::FlowSolverFactory<dim,nstate>::select_flow_case(this->all_parameters, this->parameter_handler);
355 
356  for(auto midpoint : rom_points.rowwise()){
357 
358  // Check if ROM point already exists as another ROM point
359  auto element = std::find_if(hrom_locations.begin(), hrom_locations.end(), [&midpoint](std::unique_ptr<ProperOrthogonalDecomposition::HROMTestLocation<dim,nstate>>& location){ return location->parameter.isApprox(midpoint);} );
360 
361  // Check if ROM point already exists as a snapshot
362  bool snapshot_exists = false;
363  for(auto snap_param : this->snapshot_parameters.rowwise()){
364  if(snap_param.isApprox(midpoint)){
365  snapshot_exists = true;
366  }
367  }
368 
369  if(element == hrom_locations.end() && snapshot_exists == false){
370  std::unique_ptr<ProperOrthogonalDecomposition::ROMSolution<dim, nstate>> rom_solution = solveSnapshotROM(midpoint, weights);
371  hrom_locations.emplace_back(std::make_unique<ProperOrthogonalDecomposition::HROMTestLocation<dim,nstate>>(midpoint, std::move(rom_solution), flow_solver->dg, weights));
372  if(abs(hrom_locations.back()->total_error) > this->all_parameters->reduced_order_param.adaptation_tolerance){
373  error_greater_than_tolerance = true;
374  }
375  }
376  else{
377  this->pcout << "ROM already computed." << std::endl;
378  }
379  }
380  return error_greater_than_tolerance;
381 }
382 
383 template <int dim, int nstate>
384 void HyperreducedSamplingErrorUpdated<dim, nstate>::trueErrorROM(const MatrixXd& rom_points, Epetra_Vector weights) const{
385 
386  std::unique_ptr<dealii::TableHandler> rom_table = std::make_unique<dealii::TableHandler>();
387 
388  for(auto rom : rom_points.rowwise()){
389  for(int i = 0 ; i < rom_points.cols() ; i++){
390  rom_table->add_value(this->all_parameters->reduced_order_param.parameter_names[i], rom(i));
391  rom_table->set_precision(this->all_parameters->reduced_order_param.parameter_names[i], 16);
392  }
393  double error = solveSnapshotROMandFOM(rom, weights);
394  this->pcout << "Error in the functional: " << error << std::endl;
395  rom_table->add_value("ROM_errors", error);
396  rom_table->set_precision("ROM_errors", 16);
397  }
398 
399  std::ofstream rom_table_file("true_error_table_iteration_HROM_post_sampling.txt");
400  rom_table->write_text(rom_table_file, dealii::TableHandler::TextOutputFormat::org_mode_table);
401  rom_table_file.close();
402 }
403 
404 template <int dim, int nstate>
405 double HyperreducedSamplingErrorUpdated<dim, nstate>::solveSnapshotROMandFOM(const RowVectorXd& parameter, Epetra_Vector weights) const{
406  this->pcout << "Solving HROM at " << parameter << std::endl;
407  Parameters::AllParameters params = this->reinit_params(parameter);
408 
409  std::unique_ptr<FlowSolver::FlowSolver<dim,nstate>> flow_solver_ROM = FlowSolver::FlowSolverFactory<dim,nstate>::select_flow_case(&params, this->parameter_handler);
410 
411  // Solve implicit solution
412  auto ode_solver_type_ROM = Parameters::ODESolverParam::ODESolverEnum::hyper_reduced_petrov_galerkin_solver;
413  flow_solver_ROM->ode_solver = PHiLiP::ODE::ODESolverFactory<dim, double>::create_ODESolver_manual(ode_solver_type_ROM, flow_solver_ROM->dg, this->current_pod, weights);
414  flow_solver_ROM->ode_solver->allocate_ode_system();
415  flow_solver_ROM->ode_solver->steady_state();
416 
417  this->pcout << "Done solving HROM." << std::endl;
418 
419  // Create functional
420  std::shared_ptr<Functional<dim,nstate,double>> functional_ROM = FunctionalFactory<dim,nstate,double>::create_Functional(params.functional_param, flow_solver_ROM->dg);
421 
422  this->pcout << "Solving FOM at " << parameter << std::endl;
423 
424  std::unique_ptr<FlowSolver::FlowSolver<dim,nstate>> flow_solver_FOM = FlowSolver::FlowSolverFactory<dim,nstate>::select_flow_case(&params, this->parameter_handler);
425 
426  // Solve implicit solution
427  auto ode_solver_type = Parameters::ODESolverParam::ODESolverEnum::implicit_solver;
428  flow_solver_FOM->ode_solver = PHiLiP::ODE::ODESolverFactory<dim, double>::create_ODESolver_manual(ode_solver_type, flow_solver_FOM->dg);
429  flow_solver_FOM->ode_solver->allocate_ode_system();
430  flow_solver_FOM->run();
431 
432  // Create functional
433  std::shared_ptr<Functional<dim,nstate,double>> functional_FOM = FunctionalFactory<dim,nstate,double>::create_Functional(params.functional_param, flow_solver_FOM->dg);
434 
435  this->pcout << "Done solving FOM." << std::endl;
436  return functional_ROM->evaluate_functional(false, false) - functional_FOM->evaluate_functional(false, false);
437 }
438 
439 template <int dim, int nstate>
440 void HyperreducedSamplingErrorUpdated<dim, nstate>::solveFunctionalHROM(const RowVectorXd& parameter, Epetra_Vector weights) const{
441  this->pcout << "Solving HROM at " << parameter << std::endl;
442  Parameters::AllParameters params = this->reinit_params(parameter);
443 
444  std::unique_ptr<FlowSolver::FlowSolver<dim,nstate>> flow_solver_ROM = FlowSolver::FlowSolverFactory<dim,nstate>::select_flow_case(&params, this->parameter_handler);
445 
446  // Solve
447  auto ode_solver_type_ROM = Parameters::ODESolverParam::ODESolverEnum::hyper_reduced_petrov_galerkin_solver;
448  flow_solver_ROM->ode_solver = PHiLiP::ODE::ODESolverFactory<dim, double>::create_ODESolver_manual(ode_solver_type_ROM, flow_solver_ROM->dg, this->current_pod, weights);
449  flow_solver_ROM->ode_solver->allocate_ode_system();
450  flow_solver_ROM->ode_solver->steady_state();
451 
452  this->pcout << "Done solving HROM." << std::endl;
453 
454  // Create functional
455  std::shared_ptr<Functional<dim,nstate,double>> functional_ROM = FunctionalFactory<dim,nstate,double>::create_Functional(params.functional_param, flow_solver_ROM->dg);
456 
457  rom_functional.emplace_back(functional_ROM->evaluate_functional(false, false));
458 }
459 
460 template <int dim, int nstate>
461 void HyperreducedSamplingErrorUpdated<dim, nstate>::updateNearestExistingROMs(const RowVectorXd& /*parameter*/, Epetra_Vector weights) const{
462  std::unique_ptr<FlowSolver::FlowSolver<dim,nstate>> flow_solver = FlowSolver::FlowSolverFactory<dim,nstate>::select_flow_case(this->all_parameters, this->parameter_handler);
463 
464  this->pcout << "Verifying ROM points for recomputation." << std::endl;
465  // Assemble ROM points in a matrix
466  MatrixXd rom_points(0,0);
467  for(auto it = hrom_locations.begin(); it != hrom_locations.end(); ++it){
468  rom_points.conservativeResize(rom_points.rows()+1, it->get()->parameter.cols());
469  rom_points.row(rom_points.rows()-1) = it->get()->parameter;
470  }
471 
472  // Get distances between each ROM point and all other ROM points
473  for(auto point : rom_points.rowwise()) {
475  MatrixXd scaled_rom_points = scaler.fit_transform(rom_points);
476  RowVectorXd scaled_point = scaler.transform(point);
477 
478  VectorXd distances = (scaled_rom_points.rowwise() - scaled_point).rowwise().squaredNorm();
479 
480  std::vector<int> index(distances.size());
481  std::iota(index.begin(), index.end(), 0);
482 
483  std::sort(index.begin(), index.end(),
484  [&](const int &a, const int &b) {
485  return distances[a] < distances[b];
486  });
487 
488  this->pcout << "Searching ROM points near: " << point << std::endl;
489  double local_mean_error = 0;
490  for (int i = 1; i < rom_points.cols() + 2; i++) {
491  local_mean_error = local_mean_error + std::abs(hrom_locations[index[i]]->total_error);
492  }
493  local_mean_error = local_mean_error / (rom_points.cols() + 1);
494  if ((std::abs(hrom_locations[index[0]]->total_error) > this->all_parameters->reduced_order_param.recomputation_coefficient * local_mean_error) || (std::abs(hrom_locations[index[0]]->total_error) < (1/this->all_parameters->reduced_order_param.recomputation_coefficient) * local_mean_error)) {
495  this->pcout << "Total error greater than tolerance. Recomputing ROM solution" << std::endl;
496  std::unique_ptr<ProperOrthogonalDecomposition::ROMSolution<dim, nstate>> rom_solution = solveSnapshotROM(hrom_locations[index[0]]->parameter, weights);
497  std::unique_ptr<ProperOrthogonalDecomposition::HROMTestLocation<dim, nstate>> rom_location = std::make_unique<ProperOrthogonalDecomposition::HROMTestLocation<dim, nstate>>(hrom_locations[index[0]]->parameter, std::move(rom_solution), flow_solver->dg, weights);
498  hrom_locations[index[0]] = std::move(rom_location);
499  }
500  }
501 }
502 
503 template <int dim, int nstate>
504 std::unique_ptr<ProperOrthogonalDecomposition::ROMSolution<dim,nstate>> HyperreducedSamplingErrorUpdated<dim, nstate>::solveSnapshotROM(const RowVectorXd& parameter, Epetra_Vector weights) const{
505  this->pcout << "Solving ROM at " << parameter << std::endl;
506  Parameters::AllParameters params = this->reinit_params(parameter);
507 
508  std::unique_ptr<FlowSolver::FlowSolver<dim,nstate>> flow_solver = FlowSolver::FlowSolverFactory<dim,nstate>::select_flow_case(&params, this->parameter_handler);
509 
510  // Solve implicit solution
511  auto ode_solver_type = Parameters::ODESolverParam::ODESolverEnum::hyper_reduced_petrov_galerkin_solver;
512  flow_solver->ode_solver = PHiLiP::ODE::ODESolverFactory<dim, double>::create_ODESolver_manual(ode_solver_type, flow_solver->dg, this->current_pod, weights);
513  flow_solver->ode_solver->allocate_ode_system();
514  flow_solver->ode_solver->steady_state();
515 
516  // Create functional
517  std::shared_ptr<Functional<dim,nstate,double>> functional = FunctionalFactory<dim,nstate,double>::create_Functional(params.functional_param, flow_solver->dg);
518  functional->evaluate_functional( true, false, false);
519 
520  dealii::LinearAlgebra::distributed::Vector<double> solution(flow_solver->dg->solution);
521  dealii::LinearAlgebra::distributed::Vector<double> gradient(functional->dIdw);
522 
523  std::unique_ptr<ProperOrthogonalDecomposition::ROMSolution<dim,nstate>> rom_solution = std::make_unique<ProperOrthogonalDecomposition::ROMSolution<dim, nstate>>(params, solution, gradient);
524  this->pcout << "Done solving ROM." << std::endl;
525 
526  return rom_solution;
527 }
528 
529 template <int dim, int nstate>
531  // Gather Vector Information
532  const Epetra_SerialComm sComm;
533  const int b_size = b.GlobalLength();
534  // Create new map for one core and gather old map
535  Epetra_Map single_core_b (b_size, b_size, 0, sComm);
536  Epetra_BlockMap old_map_b = b.Map();
537  // Create Epetra_importer object
538  Epetra_Import b_importer(single_core_b, old_map_b);
539  // Create new b vector
540  Epetra_Vector b_temp (single_core_b);
541  // Load the data from vector b (Multi core) into b_temp (Single core)
542  b_temp.Import(b, b_importer, Epetra_CombineMode::Insert);
543  return b_temp;
544 }
545 
546 template <int dim, int nstate>
548  std::unique_ptr<dealii::TableHandler> snapshot_table = std::make_unique<dealii::TableHandler>();
549 
550  std::ofstream solution_out_file("solution_snapshots_iteration_" + iteration + ".txt");
551  unsigned int precision = 16;
552  this->current_pod->dealiiSnapshotMatrix.print_formatted(solution_out_file, precision);
553  solution_out_file.close();
554 
555  for(auto parameters : this->snapshot_parameters.rowwise()){
556  for(int i = 0 ; i < this->snapshot_parameters.cols() ; i++){
557  snapshot_table->add_value(this->all_parameters->reduced_order_param.parameter_names[i], parameters(i));
558  snapshot_table->set_precision(this->all_parameters->reduced_order_param.parameter_names[i], 16);
559  }
560  }
561 
562  std::ofstream snapshot_table_file("snapshot_table_iteration_" + iteration + ".txt");
563  snapshot_table->write_text(snapshot_table_file, dealii::TableHandler::TextOutputFormat::org_mode_table);
564  snapshot_table_file.close();
565 
566  std::unique_ptr<dealii::TableHandler> rom_table = std::make_unique<dealii::TableHandler>();
567 
568  for(auto it = hrom_locations.begin(); it != hrom_locations.end(); ++it){
569  for(int i = 0 ; i < this->snapshot_parameters.cols() ; i++){
570  rom_table->add_value(this->all_parameters->reduced_order_param.parameter_names[i], it->get()->parameter(i));
571  rom_table->set_precision(this->all_parameters->reduced_order_param.parameter_names[i], 16);
572  }
573  rom_table->add_value("ROM_errors", it->get()->total_error);
574  rom_table->set_precision("ROM_errors", 16);
575  }
576 
577  std::ofstream rom_table_file("rom_table_iteration_" + iteration + ".txt");
578  rom_table->write_text(rom_table_file, dealii::TableHandler::TextOutputFormat::org_mode_table);
579  rom_table_file.close();
580 }
581 
582 #if PHILIP_DIM==1
584 #endif
585 
586 #if PHILIP_DIM!=1
588 #endif
589 
590 }
static std::shared_ptr< ODESolverBase< dim, real, MeshType > > create_ODESolver_manual(Parameters::ODESolverParam::ODESolverEnum ode_solver_type, std::shared_ptr< DGBase< dim, real, MeshType > > dg_input)
Creates either implicit or explicit ODE solver based on manual input (no POD basis given) ...
std::unique_ptr< ProperOrthogonalDecomposition::ROMSolution< dim, nstate > > solveSnapshotROM(const RowVectorXd &parameter, Epetra_Vector weights) const
Solve reduced-order solution.
const dealii::ParameterHandler & parameter_handler
Parameter handler for storing the .prm file being ran.
double solveSnapshotROMandFOM(const RowVectorXd &parameter, Epetra_Vector weights) const
Solve FOM and ROM, return error in functional between the models.
std::vector< std::string > parameter_names
Names of parameters.
double evaluate(const RowVectorXd &evaluate_coordinate) const
Evaluate RBF.
dealii::ConditionalOStream pcout
ConditionalOStream.
RowVectorXd readROMFunctionalPoint() const
Find point to solve for functional from param file.
std::shared_ptr< ProperOrthogonalDecomposition::NearestNeighbors > nearest_neighbors
Nearest neighbors of snapshots.
HyperreducedSamplingErrorUpdated(const PHiLiP::Parameters::AllParameters *const parameters_input, const dealii::ParameterHandler &parameter_handler_input)
Constructor.
dealii::LinearAlgebra::distributed::Vector< double > solveSnapshotFOM(const RowVectorXd &parameter) const
Solve full-order snapshot.
Files for the baseline physics.
Definition: ADTypes.hpp:10
std::vector< double > rom_functional
Functional value predicted by the rom at each sammpling iteration at parameter location specified in ...
ReducedOrderModelParam reduced_order_param
Contains parameters for the Reduced-Order model.
Main parameter class that contains the various other sub-parameter classes.
MatrixXd fit_transform(const MatrixXd &snapshot_parameters)
Fit and transform data.
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.
int recomputation_coefficient
Recomputation parameter for adaptive sampling algorithm.
Parameters::AllParameters reinit_params(const RowVectorXd &parameter) const
Reinitialize parameters.
Hyperreduced Adaptive Sampling with the updated error indicator.
std::shared_ptr< ProperOrthogonalDecomposition::OnlinePOD< dim > > current_pod
Most up to date POD basis.
Class to compute and store adjoint-based error estimates with hyperreduction.
Epetra_Vector allocateVectorToSingleCore(const Epetra_Vector &b) const
Copy all elements in matrix A to all cores.
void placeInitialSnapshots() const
Placement of initial snapshots.
std::string training_data
Training data (Residual-based vs Jacobian-based)
static std::shared_ptr< Functional< dim, nstate, real, MeshType > > create_Functional(PHiLiP::Parameters::AllParameters const *const param, std::shared_ptr< PHiLiP::DGBase< dim, real, MeshType > > dg)
Create standard functional object from constant parameter file.
MatrixXd inverse_transform(const MatrixXd &snapshot_parameters)
Unscale data.
MatrixXd transform(const MatrixXd &snapshot_parameters)
Transform data to previously fitted dataset.
bool placeROMLocations(const MatrixXd &rom_points, Epetra_Vector weights) const
Placement of ROMs.
std::vector< std::unique_ptr< ProperOrthogonalDecomposition::HROMTestLocation< dim, nstate > > > hrom_locations
Vector of parameter-HROMTestLocation pairs.
std::vector< dealii::LinearAlgebra::distributed::Vector< double > > fom_locations
Vector of parameter-ROMTestLocation pairs.
void trueErrorROM(const MatrixXd &rom_points, Epetra_Vector weights) const
Compute true/actual error at all ROM points (error in functional between FOM and ROM solution) ...
RowVectorXd getMaxErrorROM() const override
Compute RBF and find max error.
FunctionalParam functional_param
Contains parameters for functional.
void updateNearestExistingROMs(const RowVectorXd &parameter, Epetra_Vector weights) const
Updates nearest ROM points to snapshot if error discrepancy is above tolerance.
MatrixXd snapshot_parameters
Matrix of snapshot parameters.
double adaptation_tolerance
Tolerance for POD adaptation.
HyperReductionParam hyper_reduction_param
Contains parameters for Hyperreduction.
const Parameters::AllParameters *const all_parameters
Pointer to all parameters.
void outputIterationData(std::string iteration) const override
Output for each iteration.
void solveFunctionalHROM(const RowVectorXd &parameter, Epetra_Vector weights) const
Solve HROM and track functional.
std::shared_ptr< Epetra_Vector > ptr_weights
Ptr vector of ECSW Weights.