1 #include "pod_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_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 <deal.II/base/timer.h> 23 template<
int dim,
int nstate>
25 const dealii::ParameterHandler ¶meter_handler_input)
29 template <
int dim,
int nstate>
32 this->
pcout <<
"Starting adaptive sampling process" << std::endl;
33 auto stream = this->
pcout;
34 dealii::TimerOutput timer(stream,dealii::TimerOutput::summary,dealii::TimerOutput::wall_times);
36 timer.enter_subsection (
"Iteration " + std::to_string(iteration));
40 MatrixXd rom_points = this->
nearest_neighbors->kPairwiseNearestNeighborsMidpoint();
41 this->
pcout << rom_points << std::endl;
49 this->
pcout <<
"Solving FOM at " << functional_ROM << std::endl;
55 auto ode_solver_type = Parameters::ODESolverParam::ODESolverEnum::implicit_solver;
57 flow_solver_FOM->ode_solver->allocate_ode_system();
58 flow_solver_FOM->run();
62 this->
pcout <<
"FUNCTIONAL FROM FOM" << std::endl;
63 this->
pcout << functional_FOM->evaluate_functional(
false,
false) << std::endl;
70 timer.leave_subsection();
71 timer.enter_subsection (
"Iteration " + std::to_string(iteration+1));
73 this->
pcout <<
"Sampling snapshot at " << max_error_params << std::endl;
74 dealii::LinearAlgebra::distributed::Vector<double> fom_solution = this->
solveSnapshotFOM(max_error_params);
84 it->get()->compute_initial_rom_to_final_rom_error(this->
current_pod);
85 it->get()->compute_total_error();
90 rom_points = this->
nearest_neighbors->kNearestNeighborsMidpoint(max_error_params);
91 this->
pcout << rom_points << std::endl;
102 this->
pcout <<
"FUNCTIONAL FROM ROMs" << std::endl;
103 std::ofstream output_file(
"rom_functional" + std::to_string(iteration+1) +
".txt");
105 std::ostream_iterator<double> output_iterator(output_file,
"\n");
113 timer.leave_subsection();
115 this->
pcout <<
"FUNCTIONAL FROM ROMs" << std::endl;
116 std::ofstream output_file(
"rom_functional.txt");
118 std::ostream_iterator<double> output_iterator(output_file,
"\n");
124 template <
int dim,
int nstate>
126 bool error_greater_than_tolerance =
false;
127 for(
auto midpoint : rom_points.rowwise()){
130 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);} );
133 bool snapshot_exists =
false;
135 if(snap_param.isApprox(midpoint)){
136 snapshot_exists =
true;
140 if(element == this->
rom_locations.end() && snapshot_exists ==
false){
141 std::unique_ptr<ProperOrthogonalDecomposition::ROMSolution<dim, nstate>> rom_solution =
solveSnapshotROM(midpoint);
144 error_greater_than_tolerance =
true;
148 this->
pcout <<
"ROM already computed." << std::endl;
151 return error_greater_than_tolerance;
154 template <
int dim,
int nstate>
157 std::unique_ptr<dealii::TableHandler> rom_table = std::make_unique<dealii::TableHandler>();
159 for(
auto rom : rom_points.rowwise()){
160 for(
int i = 0 ; i < rom_points.cols() ; i++){
165 this->
pcout <<
"Error in the functional: " << error << std::endl;
166 rom_table->add_value(
"ROM_errors", error);
167 rom_table->set_precision(
"ROM_errors", 16);
170 std::ofstream rom_table_file(
"true_error_table_iteration_ROM_post_sampling.txt");
171 rom_table->write_text(rom_table_file, dealii::TableHandler::TextOutputFormat::org_mode_table);
172 rom_table_file.close();
175 template <
int dim,
int nstate>
177 this->
pcout <<
"Solving ROM at " << parameter << std::endl;
183 auto ode_solver_type_ROM = Parameters::ODESolverParam::ODESolverEnum::pod_petrov_galerkin_solver;
185 flow_solver_ROM->ode_solver->allocate_ode_system();
186 flow_solver_ROM->ode_solver->steady_state();
188 this->
pcout <<
"Done solving ROM." << std::endl;
193 this->
pcout <<
"Solving FOM at " << parameter << std::endl;
198 auto ode_solver_type = Parameters::ODESolverParam::ODESolverEnum::implicit_solver;
200 flow_solver_FOM->ode_solver->allocate_ode_system();
201 flow_solver_FOM->run();
206 this->
pcout <<
"Done solving FOM." << std::endl;
207 return functional_ROM->evaluate_functional(
false,
false) - functional_FOM->evaluate_functional(
false,
false);
210 template <
int dim,
int nstate>
212 this->
pcout <<
"Solving ROM at " << parameter << std::endl;
218 auto ode_solver_type_ROM = Parameters::ODESolverParam::ODESolverEnum::pod_petrov_galerkin_solver;
220 flow_solver_ROM->ode_solver->allocate_ode_system();
221 flow_solver_ROM->ode_solver->steady_state();
223 this->
pcout <<
"Done solving ROM." << std::endl;
228 rom_functional.emplace_back(functional_ROM->evaluate_functional(
false,
false));
231 template <
int dim,
int nstate>
234 this->
pcout <<
"Verifying ROM points for recomputation." << std::endl;
236 MatrixXd rom_points(0,0);
238 rom_points.conservativeResize(rom_points.rows()+1, it->get()->parameter.cols());
239 rom_points.row(rom_points.rows()-1) = it->get()->parameter;
243 for(
auto point : rom_points.rowwise()) {
245 MatrixXd scaled_rom_points = scaler.
fit_transform(rom_points);
246 RowVectorXd scaled_point = scaler.
transform(point);
248 VectorXd distances = (scaled_rom_points.rowwise() - scaled_point).rowwise().squaredNorm();
250 std::vector<int> index(distances.size());
251 std::iota(index.begin(), index.end(), 0);
253 std::sort(index.begin(), index.end(),
254 [&](
const int &a,
const int &b) {
255 return distances[a] < distances[b];
258 this->
pcout <<
"Searching ROM points near: " << point << std::endl;
259 double local_mean_error = 0;
260 for (
int i = 1; i < rom_points.cols() + 2; i++) {
261 local_mean_error = local_mean_error + std::abs(this->
rom_locations[index[i]]->total_error);
263 local_mean_error = local_mean_error / (rom_points.cols() + 1);
265 this->
pcout <<
"Total error greater than tolerance. Recomputing ROM solution" << std::endl;
266 std::unique_ptr<ProperOrthogonalDecomposition::ROMSolution<dim, nstate>> rom_solution =
solveSnapshotROM(this->
rom_locations[index[0]]->parameter);
267 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));
273 template <
int dim,
int nstate>
275 this->
pcout <<
"Solving ROM at " << parameter << std::endl;
281 auto ode_solver_type = Parameters::ODESolverParam::ODESolverEnum::pod_petrov_galerkin_solver;
283 flow_solver->ode_solver->allocate_ode_system();
284 flow_solver->ode_solver->steady_state();
288 functional->evaluate_functional(
true,
false,
false);
290 dealii::LinearAlgebra::distributed::Vector<double> solution(flow_solver->dg->solution);
291 dealii::LinearAlgebra::distributed::Vector<double> gradient(functional->dIdw);
293 std::unique_ptr<ProperOrthogonalDecomposition::ROMSolution<dim,nstate>> rom_solution = std::make_unique<ProperOrthogonalDecomposition::ROMSolution<dim, nstate>>(params, solution, gradient);
294 this->
pcout <<
"Done solving ROM." << std::endl;
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.
void trueErrorROM(const MatrixXd &rom_points) const
Compute true/actual error at all ROM points (error in functional between FOM and ROM solution) ...
void updateNearestExistingROMs(const RowVectorXd ¶meter) const
Updates nearest ROM points to snapshot if error discrepancy is above tolerance.
const dealii::ParameterHandler & parameter_handler
Parameter handler for storing the .prm file being ran.
std::vector< std::string > parameter_names
Names of parameters.
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::unique_ptr< ProperOrthogonalDecomposition::ROMSolution< dim, nstate > > solveSnapshotROM(const RowVectorXd ¶meter) const
Solve reduced-order solution.
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.
bool placeROMLocations(const MatrixXd &rom_points) const
Placement of ROMs.
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.
AdaptiveSampling(const PHiLiP::Parameters::AllParameters *const parameters_input, const dealii::ParameterHandler ¶meter_handler_input)
Constructor.
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.
std::shared_ptr< ProperOrthogonalDecomposition::OnlinePOD< dim > > current_pod
Most up to date POD basis.
virtual void outputIterationData(std::string iteration) const
Output for each iteration.
void placeInitialSnapshots() const
Placement of initial snapshots.
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.
double solveSnapshotROMandFOM(const RowVectorXd ¶meter) const
Solve FOM and ROM, return error in functional between the models.
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.
FunctionalParam functional_param
Contains parameters for functional.
int run_sampling() const override
Run Sampling Procedure.
MatrixXd snapshot_parameters
Matrix of snapshot parameters.
double adaptation_tolerance
Tolerance for POD adaptation.
void solveFunctionalROM(const RowVectorXd ¶meter) const
Solve ROM and track functional.
const Parameters::AllParameters *const all_parameters
Pointer to all parameters.
Scale data between 0 and 1.
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.