17 #include "BasisGenerator.h"
18 #include "svd/StaticSVD.h"
19 #include "svd/RandomizedSVD.h"
20 #include "svd/IncrementalSVDStandard.h"
21 #include "svd/IncrementalSVDFastUpdate.h"
22 #include "svd/IncrementalSVDBrand.h"
29 BasisGenerator::BasisGenerator(
32 const std::string& basis_file_name,
35 d_incremental(incremental),
38 d_write_snapshots(options.write_snapshots)
40 CAROM_VERIFY(options.
dim > 0);
57 if (!basis_file_name.empty()) {
69 d_next_sample_time = 0.0;
92 MPI_Initialized(&mpi_init);
94 MPI_Comm_size(MPI_COMM_WORLD, &d_num_procs);
119 CAROM_VERIFY(time >= 0.0);
122 if(d_update_right_SV)
125 return time >= d_next_sample_time;
134 bool add_without_increase)
136 CAROM_VERIFY(u_in != 0);
137 CAROM_VERIFY(
d_svd->getNumSamples() <
d_svd->getMaxNumSamples());
140 Vector u_vec(u_in, getDim(),
true);
141 if (u_vec.
norm() == 0.0) {
142 printf(
"WARNING: BasisGenerator::takeSample skipped trivial sample.\n");
146 return d_svd->takeSample(u_in, add_without_increase);
151 const std::string& kind,
156 CAROM_ASSERT(!base_file_name.empty());
157 CAROM_VERIFY(kind ==
"basis" || kind ==
"snapshot");
163 const Vector* singular_vals;
165 if (kind ==
"basis") {
169 else if (kind ==
"snapshot") {
175 if (col_min < 0) col_min = 0;
176 if (col_max > num_cols-1) col_max = num_cols-1;
178 CAROM_VERIFY(col_max >= col_min);
180 for (
int j = col_min; j <= col_max; j++) {
181 double* u_in =
new double[num_rows];
182 for (
int i = 0; i < num_rows; i++) {
183 if (kind ==
"basis") {
184 u_in[i] = mat->
item(i,j) * singular_vals->
item(j);
187 u_in[i] = mat->
item(i,j);
190 d_svd->takeSample(u_in,
false);
197 const std::string& kind,
210 CAROM_VERIFY(u_in != 0);
211 CAROM_VERIFY(rhs_in != 0);
212 CAROM_VERIFY(time >= 0);
218 Vector u_vec(u_in, dim,
true);
219 if (u_vec.
norm() == 0.0) {
220 return d_next_sample_time;
239 Vector rhs_vec(rhs_in, dim,
true);
243 basisl = basis->
mult(l);
253 double local_norm = 0.0;
254 for (
int i = 0; i < dim; ++i) {
255 double val = fabs(eta->
item(i) + d_dt*eta_dot->
item(i));
256 if (val > local_norm) {
262 if (d_num_procs == 1) {
263 global_norm = local_norm;
266 MPI_Allreduce(&local_norm,
275 double tmp = d_sampling_time_step_scale*sqrt(d_tol/global_norm);
276 if (tmp < d_min_sampling_time_step_scale) {
277 d_dt *= d_min_sampling_time_step_scale;
279 else if (tmp > d_max_sampling_time_step_scale) {
280 d_dt *= d_max_sampling_time_step_scale;
288 else if (d_dt > d_max_time_between_samples) {
289 d_dt = d_max_time_between_samples;
293 d_next_sample_time = time + d_dt;
294 return d_next_sample_time;
301 BasisGenerator::resetDt(
312 const double energyFractionThreshold,
314 const std::string & cutoffOutputPath,
320 CAROM_VERIFY(rom_dim <= sing_vals->dim());
323 for (
int sv = first_sv; sv < sing_vals->
dim(); ++sv) {
324 sum += (*sing_vals)(sv);
327 int p = std::floor(-std::log10(energyFractionThreshold));
328 std::vector<double> energy_fractions(p);
330 for (
int i = 0; i < p; ++i) {
331 energy_fractions[i] = 1 - std::pow(10, -1 - i);
335 bool reached_cutoff =
false;
336 double partialSum = 0.0;
339 std::ostream* output_stream;
341 if (!cutoffOutputPath.empty()) {
342 output_stream =
new std::ofstream(cutoffOutputPath);
344 output_stream = &std::cout;
347 for (
int sv = first_sv; sv < sing_vals->
dim(); ++sv) {
348 partialSum += (*sing_vals)(sv);
349 for (
int i = count; i < p; ++i)
351 if (partialSum / sum > 1.0 - std::pow(10, -1 - i))
353 *output_stream <<
"For energy fraction: 0.";
354 for (
int j = 0; j < i+1; ++j) *output_stream <<
"9";
355 *output_stream <<
", take first " << sv+1 <<
" of "
356 << sing_vals->
dim() <<
" basis vectors" << std::endl;
364 if (!reached_cutoff && partialSum / sum > 1.0 - energyFractionThreshold)
367 reached_cutoff =
true;
371 if (!reached_cutoff) cutoff = sing_vals->
dim();
372 *output_stream << std::fixed << std::setprecision(p+1);
373 *output_stream <<
"For energy fraction: " << 1.0 - energyFractionThreshold <<
375 << cutoff <<
" of " << sing_vals->
dim() <<
" basis vectors" << std::endl;
377 if (!cutoffOutputPath.empty()) {
378 static_cast<std::ofstream*
>(output_stream)->close();
379 delete output_stream;
void loadSampleRange(const std::string &base_file_name, const std::string &kind="basis", int col_min=0, int col_max=1e9, Database::formats db_format=Database::formats::HDF5)
Load previously saved sample (basis or state) within a column range.
BasisReader * d_basis_reader
Reader of basis vectors.
bool isNextSample(double time)
Returns true if it is time for the next svd sample.
BasisWriter * d_basis_writer
Writer of basis vectors.
const Matrix * getSpatialBasis()
Returns the basis vectors for the current time interval as a Matrix.
void loadSamples(const std::string &base_file_name, const std::string &kind="basis", int cut_off=1e9, Database::formats db_format=Database::formats::HDF5)
Load previously saved sample (basis or state).
boost::shared_ptr< SVD > d_svd
Pointer to the abstract SVD algorithm object.
~BasisGenerator()
Destructor.
double computeNextSampleTime(double *u_in, double *rhs_in, double time)
Computes next time an svd sample is needed.
void finalSummary(const double energyFractionThreshold, int &cutoff, const std::string &cutoffOutputPath="", const int first_sv=0)
Prints the summary of recommended numbers of basis vectors.
const Vector * getSingularValues()
Returns the singular values for the current time interval as a Vector.
bool takeSample(double *u_in, bool add_without_increase=false)
Sample the new state, u_in, at the given time.
Vector * getSingularValues()
Returns the singular values for the requested time.
Matrix * getSnapshotMatrix()
Returns the snapshot matrix for the requested time.
Matrix * getSpatialBasis()
Returns the spatial basis vectors as a Matrix.
formats
Implemented database file formats. Add to this enum each time a new database format is implemented.
int numColumns() const
Returns the number of columns in the Matrix. This method will return the same value from each process...
Matrix * transposeMult(const Matrix &other) const
Multiplies the transpose of this Matrix with other and returns the product, reference version.
Matrix * mult(const Matrix &other) const
Multiplies this Matrix with other and returns the product, reference version.
const double & item(int row, int col) const
Const Matrix member access. Matrix data is stored in row-major format.
int numRows() const
Returns the number of rows of the Matrix on this processor.
bool fast_update_brand
If true use the exact Brand's algorithm for the incremental SVD.
double max_time_between_samples
The upper bound on time between samples of the incremental SVD algorithm.
int dim
The dimension of the system on this processor.
double max_sampling_time_step_scale
The maximum overall scale factor to apply to time step of the incremental SVD algorithm.
int max_num_samples
The maximum number of samples.
double singular_value_tol
The singular value tolerance used in the SVD algorithm.
double linearity_tol
The tolerance of the incremental SVD algorithm to determine whether or not a sample is linearly depen...
double sampling_tol
The sampling control tolerance of the incremental SVD algorithm. Limits error in projection of soluti...
double min_sampling_time_step_scale
The minimum overall scale factor to apply to time step of the incremental SVD algorithm.
bool randomized
Whether to use the randomized SVD algorithm.
bool update_right_SV
Whether to update the right singular values.
bool fast_update
If true use the fast update version of the incremental SVD algorithm.
double initial_dt
The initial simulation time step of the incremental SVD algorithm.
int max_basis_dimension
The maximum dimension of the basis.
double sampling_time_step_scale
The scaling factor to apply to sampling algorithm of the incremental SVD algorithm.
double norm() const
Form the norm of this.
Vector * minus(const Vector &other) const
Subtracts other and this and returns the result, reference version.
const double & item(int i) const
Const Vector member access.
int dim() const
Returns the dimension of the Vector on this processor.