1 #include "hyper_reduced_sampling_error_updated.h" 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" 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" 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" 27 template<
int dim,
int nstate>
29 const dealii::ParameterHandler ¶meter_handler_input)
33 template <
int dim,
int nstate>
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);
40 timer.enter_subsection (
"Iteration " + std::to_string(iteration));
47 auto ode_solver_type_HROM = Parameters::ODESolverParam::ODESolverEnum::hyper_reduced_petrov_galerkin_solver;
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;
59 for (
int k = 0; k < this->snapshot_parameters.rows(); k++){
60 constructor_NNLS_problem->update_snapshots(std::move(this->
fom_locations[k]));
63 this->
pcout <<
"Build Problem..."<< std::endl;
64 constructor_NNLS_problem->build_problem();
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++){
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;
84 ptr_weights = std::make_shared<Epetra_Vector>(NNLS_prob.get_solution());
86 MatrixXd rom_points = this->
nearest_neighbors->kPairwiseNearestNeighborsMidpoint();
87 this->
pcout <<
"ROM Points"<< std::endl;
88 this->
pcout << rom_points << std::endl;
96 this->
pcout <<
"Solving FOM at " << functional_ROM << std::endl;
102 auto ode_solver_type = Parameters::ODESolverParam::ODESolverEnum::implicit_solver;
104 flow_solver_FOM->ode_solver->allocate_ode_system();
105 flow_solver_FOM->run();
109 this->
pcout <<
"FUNCTIONAL FROM FOM" << std::endl;
110 this->
pcout << functional_FOM->evaluate_functional(
false,
false) << std::endl;
114 while(this->
max_error > this->all_parameters->reduced_order_param.adaptation_tolerance){
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);
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();
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];
132 flow_solver->dg->reduced_mesh_weights = weights_dealii;
133 flow_solver->dg->output_results_vtk(iteration);
135 timer.leave_subsection();
136 timer.enter_subsection (
"Iteration " + std::to_string(iteration+1));
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);
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();
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++){
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;
171 ptr_weights = std::make_shared<Epetra_Vector>(NNLS_prob.get_solution());
175 it->get()->compute_initial_rom_to_final_rom_error(this->
current_pod);
176 it->get()->compute_total_error();
181 rom_points = this->
nearest_neighbors->kNearestNeighborsMidpoint(max_error_params);
182 this->
pcout << rom_points << std::endl;
193 this->
pcout <<
"FUNCTIONAL FROM ROMs" << std::endl;
194 std::ofstream output_file(
"rom_functional" + std::to_string(iteration+1) +
".txt");
196 std::ostream_iterator<double> output_iterator(output_file,
"\n");
202 if (iteration > local_weights.MyLength()){
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);
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];
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();
223 flow_solver->dg->reduced_mesh_weights = weights_dealii;
224 flow_solver->dg->output_results_vtk(iteration);
226 timer.leave_subsection();
228 this->
pcout <<
"FUNCTIONAL FROM ROMs" << std::endl;
229 std::ofstream output_file(
"rom_functional.txt");
231 std::ostream_iterator<double> output_iterator(output_file,
"\n");
237 template <
int dim,
int nstate>
239 this->
pcout <<
"Updating RBF interpolation..." << std::endl;
243 VectorXd errors(n_rows);
251 this->
pcout << i << std::endl;
254 parameters.row(i) = it->get()->parameter.array();
255 errors(i) = it->get()->total_error;
261 MatrixXd parameters_scaled = scaler.
fit_transform(parameters);
264 std::string kernel =
"thin_plate_spline";
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);
277 RowVectorXd max_error_params(parameters.cols());
282 Eigen::RowVectorXd rom_unscaled = it->get()->parameter;
283 Eigen::RowVectorXd rom_scaled = scaler.
transform(rom_unscaled);
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);
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);
299 ROL::Ptr<std::vector<double>> x_ptr = ROL::makePtr<std::vector<double>>(dimension, 0.0);
302 for(
int j = 0 ; j < dimension ; j++){
303 (*x_ptr)[j] = rom_scaled(j);
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] <<
" ";
311 this->
pcout << std::endl;
313 ROL::StdVector<double> x(x_ptr);
316 algo.run(x, rbf, bcon,
false);
318 ROL::Ptr<std::vector<double>> x_min = x.getVector();
320 for(
int j = 0 ; j < dimension ; j++){
321 rom_scaled(j) = (*x_min)[j];
326 this->
pcout <<
"Parameters of optimization convergence: " << rom_unscaled_optim << std::endl;
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;
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;
347 return max_error_params;
351 template <
int dim,
int nstate>
353 bool error_greater_than_tolerance =
false;
356 for(
auto midpoint : rom_points.rowwise()){
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);} );
362 bool snapshot_exists =
false;
364 if(snap_param.isApprox(midpoint)){
365 snapshot_exists =
true;
370 std::unique_ptr<ProperOrthogonalDecomposition::ROMSolution<dim, nstate>> rom_solution =
solveSnapshotROM(midpoint, weights);
373 error_greater_than_tolerance =
true;
377 this->
pcout <<
"ROM already computed." << std::endl;
380 return error_greater_than_tolerance;
383 template <
int dim,
int nstate>
386 std::unique_ptr<dealii::TableHandler> rom_table = std::make_unique<dealii::TableHandler>();
388 for(
auto rom : rom_points.rowwise()){
389 for(
int i = 0 ; i < rom_points.cols() ; i++){
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);
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();
404 template <
int dim,
int nstate>
406 this->
pcout <<
"Solving HROM at " << parameter << std::endl;
412 auto ode_solver_type_ROM = Parameters::ODESolverParam::ODESolverEnum::hyper_reduced_petrov_galerkin_solver;
414 flow_solver_ROM->ode_solver->allocate_ode_system();
415 flow_solver_ROM->ode_solver->steady_state();
417 this->
pcout <<
"Done solving HROM." << std::endl;
422 this->
pcout <<
"Solving FOM at " << parameter << std::endl;
427 auto ode_solver_type = Parameters::ODESolverParam::ODESolverEnum::implicit_solver;
429 flow_solver_FOM->ode_solver->allocate_ode_system();
430 flow_solver_FOM->run();
435 this->
pcout <<
"Done solving FOM." << std::endl;
436 return functional_ROM->evaluate_functional(
false,
false) - functional_FOM->evaluate_functional(
false,
false);
439 template <
int dim,
int nstate>
441 this->
pcout <<
"Solving HROM at " << parameter << std::endl;
447 auto ode_solver_type_ROM = Parameters::ODESolverParam::ODESolverEnum::hyper_reduced_petrov_galerkin_solver;
449 flow_solver_ROM->ode_solver->allocate_ode_system();
450 flow_solver_ROM->ode_solver->steady_state();
452 this->
pcout <<
"Done solving HROM." << std::endl;
457 rom_functional.emplace_back(functional_ROM->evaluate_functional(
false,
false));
460 template <
int dim,
int nstate>
464 this->
pcout <<
"Verifying ROM points for recomputation." << std::endl;
466 MatrixXd rom_points(0,0);
468 rom_points.conservativeResize(rom_points.rows()+1, it->get()->parameter.cols());
469 rom_points.row(rom_points.rows()-1) = it->get()->parameter;
473 for(
auto point : rom_points.rowwise()) {
475 MatrixXd scaled_rom_points = scaler.
fit_transform(rom_points);
476 RowVectorXd scaled_point = scaler.
transform(point);
478 VectorXd distances = (scaled_rom_points.rowwise() - scaled_point).rowwise().squaredNorm();
480 std::vector<int> index(distances.size());
481 std::iota(index.begin(), index.end(), 0);
483 std::sort(index.begin(), index.end(),
484 [&](
const int &a,
const int &b) {
485 return distances[a] < distances[b];
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);
493 local_mean_error = local_mean_error / (rom_points.cols() + 1);
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);
503 template <
int dim,
int nstate>
505 this->
pcout <<
"Solving ROM at " << parameter << std::endl;
511 auto ode_solver_type = Parameters::ODESolverParam::ODESolverEnum::hyper_reduced_petrov_galerkin_solver;
513 flow_solver->ode_solver->allocate_ode_system();
514 flow_solver->ode_solver->steady_state();
518 functional->evaluate_functional(
true,
false,
false);
520 dealii::LinearAlgebra::distributed::Vector<double> solution(flow_solver->dg->solution);
521 dealii::LinearAlgebra::distributed::Vector<double> gradient(functional->dIdw);
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;
529 template <
int dim,
int nstate>
532 const Epetra_SerialComm sComm;
533 const int b_size = b.GlobalLength();
535 Epetra_Map single_core_b (b_size, b_size, 0, sComm);
536 Epetra_BlockMap old_map_b = b.Map();
538 Epetra_Import b_importer(single_core_b, old_map_b);
540 Epetra_Vector b_temp (single_core_b);
542 b_temp.Import(b, b_importer, Epetra_CombineMode::Insert);
546 template <
int dim,
int nstate>
548 std::unique_ptr<dealii::TableHandler> snapshot_table = std::make_unique<dealii::TableHandler>();
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();
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();
566 std::unique_ptr<dealii::TableHandler> rom_table = std::make_unique<dealii::TableHandler>();
573 rom_table->add_value(
"ROM_errors", it->get()->total_error);
574 rom_table->set_precision(
"ROM_errors", 16);
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();
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 ¶meter, Epetra_Vector weights) const
Solve reduced-order solution.
double max_error
Maximum error.
const dealii::ParameterHandler & parameter_handler
Parameter handler for storing the .prm file being ran.
double solveSnapshotROMandFOM(const RowVectorXd ¶meter, 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 ¶meter_handler_input)
Constructor.
dealii::LinearAlgebra::distributed::Vector< double > solveSnapshotFOM(const RowVectorXd ¶meter) const
Solve full-order snapshot.
Files for the baseline physics.
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 ¶meter_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 ¶meter) const
Reinitialize parameters.
Hyperreduced Adaptive Sampling with the updated error indicator.
int run_sampling() const override
Run test.
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.
Radial basis function interpolation.
void updateNearestExistingROMs(const RowVectorXd ¶meter, 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.
Scale data between 0 and 1.
void outputIterationData(std::string iteration) const override
Output for each iteration.
void solveFunctionalHROM(const RowVectorXd ¶meter, Epetra_Vector weights) const
Solve HROM and track functional.
std::shared_ptr< Epetra_Vector > ptr_weights
Ptr vector of ECSW Weights.