1 #include "hyper_reduced_adaptive_sampling.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/reduced_order_solution.h" 8 #include "flow_solver/flow_solver.h" 9 #include "flow_solver/flow_solver_factory.h" 11 #include "reduced_order/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 "reduced_order/halton.h" 18 #include "reduced_order/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){
117 std::unique_ptr<dealii::TableHandler> weights_table = std::make_unique<dealii::TableHandler>();
118 for(
int i = 0 ; i < local_weights.MyLength() ; i++){
119 weights_table->add_value(
"ECSW Weights", local_weights[i]);
120 weights_table->set_precision(
"ECSW Weights", 16);
123 std::ofstream weights_table_file(
"weights_table_iteration_" + std::to_string(iteration) +
".txt");
124 weights_table->write_text(weights_table_file, dealii::TableHandler::TextOutputFormat::org_mode_table);
125 weights_table_file.close();
127 dealii::Vector<double> weights_dealii(local_weights.MyLength());
128 for(
int j = 0 ; j < local_weights.MyLength() ; j++){
129 weights_dealii[j] = local_weights[j];
131 flow_solver->dg->reduced_mesh_weights = weights_dealii;
132 flow_solver->dg->output_results_vtk(iteration);
134 timer.leave_subsection();
135 timer.enter_subsection (
"Iteration " + std::to_string(iteration+1));
137 this->
pcout <<
"Sampling snapshot at " << max_error_params << std::endl;
138 dealii::LinearAlgebra::distributed::Vector<double> fom_solution = this->
solveSnapshotFOM(max_error_params);
139 this->snapshot_parameters.conservativeResize(this->snapshot_parameters.rows()+1, this->snapshot_parameters.cols());
140 this->snapshot_parameters.row(this->snapshot_parameters.rows()-1) = max_error_params;
141 this->
nearest_neighbors->update_snapshots(this->snapshot_parameters, fom_solution);
147 this->
pcout <<
"Update Assembler..."<< std::endl;
148 constructor_NNLS_problem->update_POD_snaps(this->
current_pod, this->snapshot_parameters);
149 constructor_NNLS_problem->update_snapshots(fom_solution);
150 this->
pcout <<
"Build Problem..."<< std::endl;
151 constructor_NNLS_problem->build_problem();
154 int rows = (constructor_NNLS_problem->A_T->trilinos_matrix()).NumGlobalCols();
155 Epetra_Map bMap(rows, (rank == 0) ? rows: 0, 0, Comm);
156 Epetra_Vector b_Epetra(bMap);
157 auto b = constructor_NNLS_problem->b;
158 unsigned int local_length = bMap.NumMyElements();
159 for(
unsigned int i = 0 ; i < local_length ; i++){
164 this->
pcout <<
"Create NNLS problem..."<< std::endl;
165 NNLSSolver NNLS_prob (this->all_parameters, this->parameter_handler, constructor_NNLS_problem->A_T->trilinos_matrix(),
true, Comm, b_Epetra);
166 this->
pcout <<
"Solve NNLS problem..."<< std::endl;
167 bool exit_con = NNLS_prob.solve();
168 this->
pcout << exit_con << std::endl;
170 ptr_weights = std::make_shared<Epetra_Vector>(NNLS_prob.get_solution());
174 it->get()->compute_initial_rom_to_final_rom_error(this->
current_pod);
175 it->get()->compute_total_error();
180 rom_points = this->
nearest_neighbors->kNearestNeighborsMidpoint(max_error_params);
181 this->
pcout << rom_points << std::endl;
192 this->
pcout <<
"FUNCTIONAL FROM ROMs" << std::endl;
193 std::ofstream output_file(
"rom_functional" + std::to_string(iteration+1) +
".txt");
195 std::ostream_iterator<double> output_iterator(output_file,
"\n");
201 if (iteration > local_weights.MyLength()){
208 std::unique_ptr<dealii::TableHandler> weights_table = std::make_unique<dealii::TableHandler>();
209 for(
int i = 0 ; i < local_weights.MyLength() ; i++){
210 weights_table->add_value(
"ECSW Weights", local_weights[i]);
211 weights_table->set_precision(
"ECSW Weights", 16);
214 dealii::Vector<double> weights_dealii(local_weights.MyLength());
215 for(
int j = 0 ; j < local_weights.MyLength() ; j++){
216 weights_dealii[j] = local_weights[j];
218 std::ofstream weights_table_file(
"weights_table_iteration_final.txt");
219 weights_table->write_text(weights_table_file, dealii::TableHandler::TextOutputFormat::org_mode_table);
220 weights_table_file.close();
222 flow_solver->dg->reduced_mesh_weights = weights_dealii;
223 flow_solver->dg->output_results_vtk(iteration);
225 timer.leave_subsection();
227 this->
pcout <<
"FUNCTIONAL FROM ROMs" << std::endl;
228 std::ofstream output_file(
"rom_functional.txt");
230 std::ostream_iterator<double> output_iterator(output_file,
"\n");
236 template <
int dim,
int nstate>
238 bool error_greater_than_tolerance =
false;
239 for(
auto midpoint : rom_points.rowwise()){
242 auto element = std::find_if(this->
rom_locations.begin(), this->
rom_locations.end(), [&midpoint](std::unique_ptr<ProperOrthogonalDecomposition::ROMTestLocation<dim,nstate>>& location){
return location->parameter.isApprox(midpoint);} );
245 bool snapshot_exists =
false;
247 if(snap_param.isApprox(midpoint)){
248 snapshot_exists =
true;
252 if(element == this->
rom_locations.end() && snapshot_exists ==
false){
253 std::unique_ptr<ProperOrthogonalDecomposition::ROMSolution<dim, nstate>> rom_solution =
solveSnapshotROM(midpoint, weights);
256 error_greater_than_tolerance =
true;
260 this->
pcout <<
"ROM already computed." << std::endl;
263 return error_greater_than_tolerance;
266 template <
int dim,
int nstate>
269 std::unique_ptr<dealii::TableHandler> rom_table = std::make_unique<dealii::TableHandler>();
271 for(
auto rom : rom_points.rowwise()){
272 for(
int i = 0 ; i < rom_points.cols() ; i++){
277 this->
pcout <<
"Error in the functional: " << error << std::endl;
278 rom_table->add_value(
"ROM_errors", error);
279 rom_table->set_precision(
"ROM_errors", 16);
282 std::ofstream rom_table_file(
"true_error_table_iteration_HROM_post_sampling.txt");
283 rom_table->write_text(rom_table_file, dealii::TableHandler::TextOutputFormat::org_mode_table);
284 rom_table_file.close();
287 template <
int dim,
int nstate>
289 this->
pcout <<
"Solving HROM at " << parameter << std::endl;
295 auto ode_solver_type_ROM = Parameters::ODESolverParam::ODESolverEnum::hyper_reduced_petrov_galerkin_solver;
297 flow_solver_ROM->ode_solver->allocate_ode_system();
298 flow_solver_ROM->ode_solver->steady_state();
300 this->
pcout <<
"Done solving HROM." << std::endl;
305 this->
pcout <<
"Solving FOM at " << parameter << std::endl;
310 auto ode_solver_type = Parameters::ODESolverParam::ODESolverEnum::implicit_solver;
312 flow_solver_FOM->ode_solver->allocate_ode_system();
313 flow_solver_FOM->run();
318 this->
pcout <<
"Done solving FOM." << std::endl;
319 return functional_ROM->evaluate_functional(
false,
false) - functional_FOM->evaluate_functional(
false,
false);
322 template <
int dim,
int nstate>
324 this->
pcout <<
"Solving HROM at " << parameter << std::endl;
330 auto ode_solver_type_ROM = Parameters::ODESolverParam::ODESolverEnum::hyper_reduced_petrov_galerkin_solver;
332 flow_solver_ROM->ode_solver->allocate_ode_system();
333 flow_solver_ROM->ode_solver->steady_state();
335 this->
pcout <<
"Done solving HROM." << std::endl;
340 rom_functional.emplace_back(functional_ROM->evaluate_functional(
false,
false));
343 template <
int dim,
int nstate>
346 this->
pcout <<
"Verifying ROM points for recomputation." << std::endl;
348 MatrixXd rom_points(0,0);
350 rom_points.conservativeResize(rom_points.rows()+1, it->get()->parameter.cols());
351 rom_points.row(rom_points.rows()-1) = it->get()->parameter;
355 for(
auto point : rom_points.rowwise()) {
357 MatrixXd scaled_rom_points = scaler.
fit_transform(rom_points);
358 RowVectorXd scaled_point = scaler.
transform(point);
360 VectorXd distances = (scaled_rom_points.rowwise() - scaled_point).rowwise().squaredNorm();
362 std::vector<int> index(distances.size());
363 std::iota(index.begin(), index.end(), 0);
365 std::sort(index.begin(), index.end(),
366 [&](
const int &a,
const int &b) {
367 return distances[a] < distances[b];
370 this->
pcout <<
"Searching ROM points near: " << point << std::endl;
371 double local_mean_error = 0;
372 for (
int i = 1; i < rom_points.cols() + 2; i++) {
373 local_mean_error = local_mean_error + std::abs(this->
rom_locations[index[i]]->total_error);
375 local_mean_error = local_mean_error / (rom_points.cols() + 1);
377 this->
pcout <<
"Total error greater than tolerance. Recomputing ROM solution" << std::endl;
378 std::unique_ptr<ProperOrthogonalDecomposition::ROMSolution<dim, nstate>> rom_solution =
solveSnapshotROM(this->
rom_locations[index[0]]->parameter, weights);
379 std::unique_ptr<ProperOrthogonalDecomposition::ROMTestLocation<dim, nstate>> rom_location = std::make_unique<ProperOrthogonalDecomposition::ROMTestLocation<dim, nstate>>(this->
rom_locations[index[0]]->parameter, std::move(rom_solution));
385 template <
int dim,
int nstate>
387 this->
pcout <<
"Solving ROM at " << parameter << std::endl;
393 auto ode_solver_type_HROM = Parameters::ODESolverParam::ODESolverEnum::hyper_reduced_petrov_galerkin_solver;
395 flow_solver->ode_solver->allocate_ode_system();
396 flow_solver->ode_solver->steady_state();
400 functional->evaluate_functional(
true,
false,
false);
402 dealii::LinearAlgebra::distributed::Vector<double> solution(flow_solver->dg->solution);
403 dealii::LinearAlgebra::distributed::Vector<double> gradient(functional->dIdw);
405 std::unique_ptr<ProperOrthogonalDecomposition::ROMSolution<dim,nstate>> rom_solution = std::make_unique<ProperOrthogonalDecomposition::ROMSolution<dim, nstate>>(params, solution, gradient);
406 this->
pcout <<
"Done solving ROM." << std::endl;
411 template <
int dim,
int nstate>
414 const Epetra_SerialComm sComm;
415 const int b_size = b.GlobalLength();
417 Epetra_Map single_core_b (b_size, b_size, 0, sComm);
418 Epetra_BlockMap old_map_b = b.Map();
420 Epetra_Import b_importer(single_core_b, old_map_b);
422 Epetra_Vector b_temp (single_core_b);
424 b_temp.Import(b, b_importer, Epetra_CombineMode::Insert);
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) ...
double max_error
Maximum error.
const dealii::ParameterHandler & parameter_handler
Parameter handler for storing the .prm file being ran.
std::vector< std::string > parameter_names
Names of parameters.
void solveFunctionalHROM(const RowVectorXd ¶meter, Epetra_Vector weights) const
Solve ROM and track functional.
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.
std::vector< double > rom_functional
Functional value predicted by the rom at each sammpling iteration at parameter location specified in ...
dealii::LinearAlgebra::distributed::Vector< double > solveSnapshotFOM(const RowVectorXd ¶meter) const
Solve full-order snapshot.
Files for the baseline physics.
double solveSnapshotROMandFOM(const RowVectorXd ¶meter, Epetra_Vector weights) const
Solve FOM and ROM, return error in functional between the models.
ReducedOrderModelParam reduced_order_param
Contains parameters for the Reduced-Order model.
Main parameter class that contains the various other sub-parameter classes.
Class to compute and store adjoint-based error estimates.
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.
HyperreducedAdaptiveSampling(const PHiLiP::Parameters::AllParameters *const parameters_input, const dealii::ParameterHandler ¶meter_handler_input)
Constructor.
std::shared_ptr< ProperOrthogonalDecomposition::OnlinePOD< dim > > current_pod
Most up to date POD basis.
bool placeROMLocations(const MatrixXd &rom_points, Epetra_Vector weights) const
Placement of ROMs.
virtual void outputIterationData(std::string iteration) const
Output for each iteration.
void placeInitialSnapshots() const
Placement of initial snapshots.
std::unique_ptr< ProperOrthogonalDecomposition::ROMSolution< dim, nstate > > solveSnapshotROM(const RowVectorXd ¶meter, Epetra_Vector weights) const
Solve reduced-order solution.
int run_sampling() const override
Run test.
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 transform(const MatrixXd &snapshot_parameters)
Transform data to previously fitted dataset.
std::vector< dealii::LinearAlgebra::distributed::Vector< double > > fom_locations
Vector of parameter-ROMTestLocation pairs.
Epetra_Vector allocateVectorToSingleCore(const Epetra_Vector &b) const
Copy all elements in matrix A to all cores.
FunctionalParam functional_param
Contains parameters for functional.
Hyperreduced adaptive sampling.
MatrixXd snapshot_parameters
Matrix of snapshot parameters.
std::shared_ptr< Epetra_Vector > ptr_weights
Ptr vector of ECSW Weights.
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 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) ...
void updateNearestExistingROMs(const RowVectorXd ¶meter, Epetra_Vector weights) const
Updates nearest ROM points to snapshot if error discrepancy is above tolerance.
std::vector< std::unique_ptr< ProperOrthogonalDecomposition::ROMTestLocation< dim, nstate > > > rom_locations
Vector of parameter-ROMTestLocation pairs.
virtual RowVectorXd getMaxErrorROM() const
Compute RBF and find max error.