11 #include "linalg/Matrix.h"
12 #include "Utilities.h"
18 #include "STSampling.h"
33 void SampleTemporalIndices(
const Matrix & s_basis,
34 const Matrix & t_basis,
35 const int num_f_basis_vectors_used,
39 const int num_samples_req,
40 const bool excludeFinalTime)
42 CAROM_VERIFY(!t_basis.distributed());
45 CAROM_VERIFY(0 < num_f_basis_vectors_used
46 && num_f_basis_vectors_used <= s_basis.numColumns()
47 && num_f_basis_vectors_used <= t_basis.numColumns());
48 CAROM_VERIFY(num_samples_req > 0);
49 const int num_basis_vectors =
50 std::min(num_f_basis_vectors_used, s_basis.numColumns());
51 const int num_samples = num_samples_req;
52 const int numExcluded = excludeFinalTime ? 1 : 0;
53 CAROM_VERIFY(num_samples <= t_basis.numRows() - numExcluded);
54 const int s_size = s_basis.numRows();
55 const int t_size = t_basis.numRows();
57 const int ns_mod_nr = num_samples % num_basis_vectors;
62 Matrix M(num_basis_vectors, num_basis_vectors,
65 std::set<int> samples;
67 std::vector<double> error(s_size * t_size);
68 std::vector<double> MZphi(num_basis_vectors);
71 for (
int s=0; s<s_size; ++s)
73 for (
int t=0; t<t_size; ++t)
74 error[t + (s*t_size)] = s_basis.item(s, 0) * t_basis.item(t, 0);
77 for (
int i=0; i<num_basis_vectors; ++i)
79 CAROM_VERIFY(samples.size() == ns);
86 M.setSize(ns * s_size, i);
89 for (
auto t : samples)
91 for (
int s = 0; s < s_size; ++s)
93 const int row = ti + (s*ns);
94 for (
int col = 0; col < i; ++col)
96 M.item(row, col) = s_basis.item(s, col) * t_basis.item(t, col);
104 M.transposePseudoinverse();
113 for (
int j = 0; j < i; ++j) MZphi[j] = 0.0;
116 for (
auto t : samples)
118 for (
int s = 0; s < s_size; ++s)
120 const int row = ti + (s*ns);
121 const double phi_i_s_t = s_basis.item(s, i) * t_basis.item(t,
124 for (
int col = 0; col < i; ++col)
126 MZphi[col] += M.item(row, col) * phi_i_s_t;
134 for (
int s=0; s<s_size; ++s)
136 for (
int t=0; t<t_size; ++t)
137 error[t + (s*t_size)] = s_basis.item(s, i) * t_basis.item(t, i);
141 for (
int s=0; s<s_size; ++s)
143 for (
int t=0; t<t_size; ++t)
145 for (
int j=0; j<i; ++j)
146 error[t + (s*t_size)] -= MZphi[j] * s_basis.item(s, j) * t_basis.item(t, j);
153 const int nsi = i < ns_mod_nr ? (num_samples / num_basis_vectors) + 1 :
154 num_samples / num_basis_vectors;
156 for (
int j=0; j<nsi; ++j)
160 double maxNorm = -1.0;
162 for (
int t=0; t<t_size - numExcluded; ++t)
164 std::set<int>::const_iterator found = samples.find(t);
165 if (found != samples.end())
169 for (
int s=0; s<s_size; ++s)
171 norm2 += error[t + (s*t_size)] * error[t + (s*t_size)];
175 double globalNorm2 = 0.0;
176 MPI_Allreduce(&norm2, &globalNorm2, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
177 if (globalNorm2 > maxNorm)
179 maxNorm = globalNorm2;
184 samples.insert(tmax);
190 CAROM_VERIFY(num_samples == ns);
193 for (
auto t : samples)
206 void SampleSpatialIndices(
const Matrix & s_basis,
207 const Matrix & t_basis,
208 const int num_f_basis_vectors_used,
209 const int num_t_samples,
212 int* s_sampled_rows_per_proc,
213 Matrix& f_basis_sampled,
216 const int num_samples_req)
223 MPI_Datatype MaxRowType, oldtypes[2];
225 MPI_Aint offsets[2], extent, lower_bound;
228 oldtypes[0] = MPI_DOUBLE;
236 #if (MPI_VERSION == 1)
237 MPI_Type_extent(MPI_DOUBLE, &extent);
239 MPI_Type_get_extent(MPI_DOUBLE, &lower_bound, &extent);
243 oldtypes[1] = MPI_INT;
251 #if (MPI_VERSION == 1)
252 MPI_Type_struct(2, blockcounts, offsets, oldtypes, &MaxRowType);
254 MPI_Type_create_struct(2, blockcounts, offsets, oldtypes, &MaxRowType);
257 MPI_Type_commit(&MaxRowType);
261 MPI_Op_create((MPI_User_function*)RowInfoMax,
true, &RowInfoOp);
266 CAROM_VERIFY(0 < num_f_basis_vectors_used
267 && num_f_basis_vectors_used <= s_basis.numColumns()
268 && num_f_basis_vectors_used <= t_basis.numColumns());
269 CAROM_VERIFY(num_samples_req >
271 const int num_basis_vectors =
272 std::min(num_f_basis_vectors_used, s_basis.numColumns());
274 const int num_samples = num_samples_req;
275 CAROM_VERIFY(num_basis_vectors <= num_samples
276 && num_samples <= s_basis.numRows());
277 CAROM_VERIFY(num_samples == f_basis_sampled.numRows()
278 && num_basis_vectors == f_basis_sampled.numColumns());
279 CAROM_VERIFY(!f_basis_sampled.distributed());
280 const int s_size = s_basis.numRows();
281 const int t_size = t_basis.numRows();
283 const int ns_mod_nr = num_samples % num_basis_vectors;
288 Matrix M(num_basis_vectors, num_basis_vectors,
292 std::vector<std::set<int> > proc_sampled_f_row(num_procs);
293 std::vector<std::map<int, int> > proc_f_row_to_tmp_fs_row(num_procs);
294 int num_f_basis_cols =
295 f_basis_sampled.numColumns();
296 Matrix tmp_fs(f_basis_sampled.numRows(),
298 f_basis_sampled.distributed());
301 RowInfo f_bv_max_local, f_bv_max_global;
303 std::vector<double> error(s_size * t_size);
304 std::vector<double> MZphi(num_basis_vectors);
305 std::vector<double> sampled_row(num_basis_vectors);
308 for (
int s=0; s<s_size; ++s)
310 for (
int t=0; t<t_size; ++t)
311 error[t + (s*t_size)] = s_basis.item(s, 0) * t_basis.item(t, 0);
314 for (
int i=0; i<num_basis_vectors; ++i)
344 M.setSize(ns * num_t_samples, i);
345 for (
int k = 0; k < i; ++k)
346 for (
int j = 0; j < ns; ++j)
348 for (
int ti = 0; ti < num_t_samples; ++ti)
350 const int t = t_samples[ti];
351 const int row = ti + (j*num_t_samples);
353 M.item(row, k) = tmp_fs.item(j, k) * t_basis.item(t, k);
358 M.transposePseudoinverse();
362 for (
int j = 0; j < i; ++j) MZphi[j] = 0.0;
390 for (
int j = 0; j < ns; ++j)
392 for (
int ti = 0; ti < num_t_samples; ++ti)
394 const int t = t_samples[ti];
395 const int row = ti + (j*num_t_samples);
397 const double phi_i_s_t = s_basis.item(j, i) * t_basis.item(t,
400 for (
int k = 0; k < i; ++k)
401 MZphi[k] += M.item(row, k) * phi_i_s_t;
406 for (
int s=0; s<s_size; ++s)
408 for (
int t=0; t<t_size; ++t)
409 error[t + (s*t_size)] = s_basis.item(s, i) * t_basis.item(t, i);
413 for (
int s=0; s<s_size; ++s)
415 for (
int t=0; t<t_size; ++t)
417 for (
int j=0; j<i; ++j)
418 error[t + (s*t_size)] -= MZphi[j] * s_basis.item(s, j) * t_basis.item(t, j);
425 const int nsi = i < ns_mod_nr ? (num_samples / num_basis_vectors) + 1 :
426 num_samples / num_basis_vectors;
428 for (
int j=0; j<nsi; ++j)
433 double maxNorm = -1.0;
435 for (
int s=0; s<s_size; ++s)
437 std::set<int>::const_iterator found = proc_sampled_f_row[myid].find(s);
438 if (found != proc_sampled_f_row[myid].end())
442 for (
int t=0; t<t_size; ++t)
444 norm2 += error[t + (s*t_size)] * error[t + (s*t_size)];
457 f_bv_max_local.row_val = maxNorm;
458 f_bv_max_local.row = smax;
459 f_bv_max_local.proc = myid;
461 MPI_Allreduce(&f_bv_max_local, &f_bv_max_global, 1,
462 MaxRowType, RowInfoOp, MPI_COMM_WORLD);
464 proc_sampled_f_row[f_bv_max_global.proc].insert(f_bv_max_global.row);
465 proc_f_row_to_tmp_fs_row[f_bv_max_global.proc][f_bv_max_global.row] = ns + j;
468 if (f_bv_max_global.proc == myid) {
469 for (
int k = 0; k < num_basis_vectors; ++k) {
470 sampled_row[k] = s_basis.item(f_bv_max_global.row, k);
473 MPI_Bcast(sampled_row.data(), num_basis_vectors, MPI_DOUBLE,
474 f_bv_max_global.proc, MPI_COMM_WORLD);
476 for (
int k = 0; k < num_basis_vectors; ++k) {
477 tmp_fs.item(ns+j, k) = sampled_row[k];
484 CAROM_VERIFY(num_samples == ns);
489 for (
int i = 0; i < num_procs; ++i) {
490 std::set<int>& this_proc_sampled_f_row = proc_sampled_f_row[i];
491 std::map<int, int>& this_proc_f_row_to_tmp_fs_row =
492 proc_f_row_to_tmp_fs_row[i];
493 s_sampled_rows_per_proc[i] = this_proc_sampled_f_row.size();
494 for (std::set<int>::iterator j = this_proc_sampled_f_row.begin();
495 j != this_proc_sampled_f_row.end(); ++j) {
497 s_sampled_row[idx] = this_f_row;
498 int tmp_fs_row = this_proc_f_row_to_tmp_fs_row[this_f_row];
499 for (
int col = 0; col < num_f_basis_cols; ++col) {
500 f_basis_sampled.item(idx, col) = tmp_fs.item(tmp_fs_row, col);
506 CAROM_VERIFY(num_samples == idx);
509 MPI_Type_free(&MaxRowType);
510 MPI_Op_free(&RowInfoOp);
515 const int num_f_basis_vectors_used,
516 std::vector<int>& t_samples,
518 int* f_sampled_rows_per_proc,
522 const int num_t_samples_req,
523 const int num_s_samples_req,
524 const bool excludeFinalTime)
531 CAROM_VERIFY(s_basis.
numColumns() == num_f_basis_vectors_used
532 && t_basis.
numColumns() == num_f_basis_vectors_used);
535 CAROM_VERIFY(t_samples.size() == num_t_samples_req);
537 SampleTemporalIndices(s_basis, t_basis, num_f_basis_vectors_used,
539 myid, num_procs, num_t_samples_req, excludeFinalTime);
543 CAROM_VERIFY(s_basis_sampled.
numRows() == num_s_samples_req
544 && s_basis_sampled.
numColumns() == num_f_basis_vectors_used);
548 SampleSpatialIndices(s_basis, t_basis, num_f_basis_vectors_used,
551 t_samples.data(), f_sampled_row, f_sampled_rows_per_proc,
552 s_basis_sampled, myid, num_procs, num_s_samples_req);
555 void GetSampledSpaceTimeBasis(std::vector<int>
const& t_samples,
556 const Matrix& t_basis,
557 Matrix
const& s_basis_sampled,
558 Matrix& f_basis_sampled_inv)
560 const int num_s_samples = s_basis_sampled.numRows();
561 const int num_t_samples = t_samples.size();
565 CAROM_VERIFY(f_basis_sampled_inv.numRows() == num_t_samples * num_s_samples);
567 for (
int si=0; si<num_s_samples; ++si)
569 for (
int ti=0; ti<num_t_samples; ++ti)
571 const int row = ti + (si*num_t_samples);
572 const int t = t_samples[ti];
573 for (
int j=0; j<f_basis_sampled_inv.numColumns(); ++j)
574 f_basis_sampled_inv.item(row, j) = s_basis_sampled.item(si,
575 j) * t_basis.item(t, j);
580 f_basis_sampled_inv.transposePseudoinverse();
int numColumns() const
Returns the number of columns in the Matrix. This method will return the same value from each process...
int numRows() const
Returns the number of rows of the Matrix on this processor.
void SpaceTimeSampling(const Matrix &s_basis, const Matrix &t_basis, const int num_f_basis_vectors_used, std::vector< int > &t_samples, int *f_sampled_row, int *f_sampled_rows_per_proc, Matrix &s_basis_sampled, const int myid, const int num_procs, const int num_t_samples_req, const int num_s_samples_req, const bool excludeFinalTime)