JaRMoS  1.1
Java Reduced Model Simulations
 All Classes Namespaces Files Functions Variables Enumerator Groups Pages
TransientRBSystem.java
Go to the documentation of this file.
1 package rb;
2 
5 import jarmos.Log;
10 
11 import java.io.BufferedReader;
12 import java.io.IOException;
13 
14 import org.apache.commons.math.linear.Array2DRowRealMatrix;
15 import org.apache.commons.math.linear.ArrayRealVector;
16 import org.apache.commons.math.linear.LUDecompositionImpl;
17 import org.apache.commons.math.linear.RealMatrix;
18 import org.apache.commons.math.linear.RealVector;
19 
21 
32 public class TransientRBSystem extends RBSystem {
33 
34  // Logging tag
35  private static final String DEBUG_TAG = "TransientRBSystem";
36 
40  private boolean apply_temporal_filter_flag;
41 
42  private double[][][][] Aq_Mq_representor_norms;
43 
44  private double[][] cached_Aq_Aq_matrix;
45 
46  private double[][] cached_Aq_Mq_matrix;
47 
48  private double[] cached_Fq_Aq_vector;
49  private double[] cached_Fq_Mq_vector;
50  private double cached_Fq_term;
51 
52  private double[][] cached_Mq_Mq_matrix;
56  private double dt;
60  protected double[] error_bound_all_k;
65  private double euler_theta;
69  private double filter_width;
73  private double[][][] Fq_Mq_representor_norms;
74 
78  private int fQm;
79 
83  public int fTotalTimesteps;
84 
85  private double[][][] Mq_Mq_representor_norms;
86 
91  public int n_plotting_steps;
92 
96  protected RealVector old_RB_solution;
97 
98  // @SuppressWarnings({ "unused" })
99  // /**
100  // * A secondary SCM object since we might need a lower bound for the mass
101  // * matrix and the stiffness matrix.
102  // */
103  // private RBSCMSystem mSecondRbScmSystem;
104 
108  protected RealMatrix RB_L2_matrix;
112  protected RealMatrix[] RB_M_q_matrix;
116  protected int timestep;
120  protected RealVector[] timestepRBSolutions;
121 
125  public void apply_temporal_filter() {
126  double[][] RB_convolved_outputs_all_k = new double[getNumOutputs()][getTotalTimesteps() + 1];
127  double[][] RB_convolved_error_bounds_all_k = new double[getNumOutputs()][getTotalTimesteps() + 1];
128 
129  boolean tdL = affineFunctionsInstance.isTimeDependentL();
130  double output_dual_norm = 0;
131  for (int n = 0; n < getNumOutputs(); n++) {
132  if (!tdL)
133  output_dual_norm = compute_output_dual_norm(n, 0);// Zero
134  // is
135  // current
136  // time
137 
138  for (int time_level = 0; time_level <= getTotalTimesteps(); time_level++) {
139  if (tdL)
140  output_dual_norm = compute_output_dual_norm(n, time_level * getdt());
141 
142  double conv_weight_integral_sq = 0.;
143  RB_convolved_outputs_all_k[n][time_level] = 0.;
144 
145  for (int k_prime = 0; k_prime <= getTotalTimesteps(); k_prime++) {
146  double time_diff = getdt() * (time_level - k_prime);
147  RB_convolved_outputs_all_k[n][time_level] += getdt() * conv_weight(time_diff)
148  * RB_outputs_all_k[n][k_prime];
149 
150  conv_weight_integral_sq += getdt() * Math.pow(conv_weight(time_diff), 2.);
151  }
152 
153  RB_convolved_error_bounds_all_k[n][time_level] = error_bound_all_k[getTotalTimesteps()]
154  * output_dual_norm * Math.sqrt(conv_weight_integral_sq);
155  }
156  }
157 
158  RB_outputs_all_k = RB_convolved_outputs_all_k;
159  RB_output_error_bounds_all_k = RB_convolved_error_bounds_all_k;
160  }
161 
165  protected void cache_online_residual_terms(int N) {
166 
167  cached_Fq_term = 0.;
168  int q = 0;
169  for (int q_f1 = 0; q_f1 < getQf(); q_f1++) {
170 
171  double cached_theta_q_f1 = thetaQf(q_f1);
172  for (int q_f2 = q_f1; q_f2 < getQf(); q_f2++) {
173  double delta = (q_f1 == q_f2) ? 1. : 2.;
174  cached_Fq_term += delta * cached_theta_q_f1 * thetaQf(q_f2) * Fq_representor_norms[q];
175 
176  q++;
177  }
178  }
179 
180  for (int q_f = 0; q_f < getQf(); q_f++) {
181  double cached_theta_q_f = thetaQf(q_f);
182  for (int q_a = 0; q_a < getQa(); q_a++) {
183  double cached_theta_q_a = thetaQa(q_a);
184  for (int i = 0; i < N; i++) {
185  // Clear the entries on the first pass
186  if ((q_f == 0) && (q_a == 0))
187  cached_Fq_Aq_vector[i] = 0.;
188 
189  cached_Fq_Aq_vector[i] += 2. * cached_theta_q_f * cached_theta_q_a
190  * Fq_Aq_representor_norms[q_f][q_a][i];
191  }
192  }
193  }
194 
195  q = 0;
196  for (int q_a1 = 0; q_a1 < getQa(); q_a1++) {
197  double cached_theta_q_a1 = thetaQa(q_a1);
198  for (int q_a2 = q_a1; q_a2 < getQa(); q_a2++) {
199  double cached_theta_q_a2 = thetaQa(q_a2);
200  double delta = (q_a1 == q_a2) ? 1. : 2.;
201 
202  for (int i = 0; i < N; i++) {
203  for (int j = 0; j < N; j++) {
204  // Clear the entries on the first pass
205  if (q == 0)
206  cached_Aq_Aq_matrix[i][j] = 0.;
207 
208  cached_Aq_Aq_matrix[i][j] += delta * cached_theta_q_a1 * cached_theta_q_a2
209  * Aq_Aq_representor_norms[q][i][j];
210  }
211  }
212  q++;
213  }
214  }
215 
216  for (int q_f = 0; q_f < getQf(); q_f++) {
217  double cached_theta_q_f = thetaQf(q_f);
218 
219  for (int q_m = 0; q_m < getQm(); q_m++) {
220  double cached_theta_q_m = thetaQm(q_m);
221 
222  for (int i = 0; i < N; i++) {
223  // Clear the entries on the first pass
224  if ((q_f == 0) && (q_m == 0))
225  cached_Fq_Mq_vector[i] = 0.;
226 
227  cached_Fq_Mq_vector[i] += 2. * cached_theta_q_f * cached_theta_q_m
228  * Fq_Mq_representor_norms[q_f][q_m][i];
229  }
230  }
231  }
232 
233  for (int q_a = 0; q_a < getQa(); q_a++) {
234  double cached_theta_q_a = thetaQa(q_a);
235 
236  for (int q_m = 0; q_m < getQm(); q_m++) {
237  double cached_theta_q_m = thetaQm(q_m);
238 
239  for (int i = 0; i < N; i++) {
240  for (int j = 0; j < N; j++) {
241  // Clear the entries on the first pass
242  if ((q_a == 0) && (q_m == 0))
243  cached_Aq_Mq_matrix[i][j] = 0.;
244 
245  cached_Aq_Mq_matrix[i][j] += 2. * cached_theta_q_a * cached_theta_q_m
246  * Aq_Mq_representor_norms[q_a][q_m][i][j];
247  }
248  }
249  }
250  }
251 
252  q = 0;
253  for (int q_m1 = 0; q_m1 < getQm(); q_m1++) {
254  double cached_theta_q_m1 = thetaQm(q_m1);
255  for (int q_m2 = q_m1; q_m2 < getQm(); q_m2++) {
256  double cached_theta_q_m2 = thetaQm(q_m2);
257  double delta = (q_m1 == q_m2) ? 1. : 2.;
258 
259  for (int i = 0; i < N; i++) {
260  for (int j = 0; j < N; j++) {
261  if (q == 0)
262  cached_Mq_Mq_matrix[i][j] = 0.;
263 
264  cached_Mq_Mq_matrix[i][j] += delta * cached_theta_q_m1 * cached_theta_q_m2
265  * Mq_Mq_representor_norms[q][i][j];
266  }
267  }
268  q++;
269  }
270  }
271 
272  }
273 
281  @Override
282  protected double compute_residual_dual_norm(int N) {
283  // This assembly assumes we have already called
284  // cache_online_residual_terms
285  // and that the RB_solve parameter is constant in time
286 
287  RealVector RB_u_euler_theta = RB_solution.mapMultiply(getEulerTheta()).add(
288  old_RB_solution.mapMultiply(1. - getEulerTheta()));
289  RealVector mass_coeffs = RB_solution.subtract(old_RB_solution).mapMultiply(-1. / getdt());
290 
291  double residual_norm_sq = cached_Fq_term;
292 
293  for (int i = 0; i < N; i++) {
294  residual_norm_sq += RB_u_euler_theta.getEntry(i) * cached_Fq_Aq_vector[i];
295  residual_norm_sq += mass_coeffs.getEntry(i) * cached_Fq_Mq_vector[i];
296  }
297 
298  for (int i = 0; i < N; i++)
299  for (int j = 0; j < N; j++) {
300  residual_norm_sq += RB_u_euler_theta.getEntry(i) * RB_u_euler_theta.getEntry(j)
301  * cached_Aq_Aq_matrix[i][j];
302  residual_norm_sq += mass_coeffs.getEntry(i) * mass_coeffs.getEntry(j) * cached_Mq_Mq_matrix[i][j];
303  residual_norm_sq += RB_u_euler_theta.getEntry(i) * mass_coeffs.getEntry(j) * cached_Aq_Mq_matrix[i][j];
304  }
305 
306  if (residual_norm_sq < 0) {
307  Log.d(DEBUG_TAG, "Warning: Square of residual norm is negative "
308  + "in TransientRBSystem::compute_residual_dual_norm()");
309 
310  // Sometimes this is negative due to rounding error,
311  // but error is on the order of 1.e-10, so shouldn't
312  // affect result
313  residual_norm_sq = Math.abs(residual_norm_sq);
314  }
315 
316  return Math.sqrt(residual_norm_sq);
317  }
318 
319  protected double conv_weight(double x) {
320  // Specify a Gaussian with standard deviation sigma
321 
322  double sigma = filter_width * getdt();
323 
324  return 1. / Math.sqrt(2. * Math.PI * sigma * sigma) * Math.exp(-x * x / (2. * sigma * sigma));
325  }
326 
330  public double getdt() {
331  return dt;
332  }
333 
338  public double getEulerTheta() {
339  return euler_theta;
340  }
341 
351  @Override
353  // RB solution size
354  int N = timestepRBSolutions[1].getDimension();
355  // Number of time-steps to show
356  int nt = getVisualNumTimesteps();
357  // Dimension of the full solution
358  int numDoFs = fullBasisVectors[0][0].length;
359 
360  SimulationResult res = new SimulationResult(nt);
362  for (timestep = 1; timestep <= nt; timestep++) {
363  res.addTransform(dt);
364  }
365  int curDoFfield = 0;
366  for (FieldDescriptor sftype : logicalFieldTypes) {
367  if (curDoFfield + sftype.Type.requiredDoFFields > getNumDoFFields()) {
368  throw new RuntimeException("Too many output fields used by current "
369  + "SolutionFieldTypes set in RBSystem. Check your model.xml.");
370  }
371  switch (sftype.Type) {
372  case RealValue: {
373  DefaultSolutionField f = new DefaultSolutionField(sftype, numDoFs * nt);
374  double tmpval;
375  for (timestep = 1; timestep <= nt; timestep++) {
376  // Choose equally spaced indices
377  int solidx = (int) Math.round(Math.floor(fTotalTimesteps * ((float) timestep / nt)));
378  for (int dim = 0; dim < numDoFs; dim++) {
379  tmpval = 0;
380  for (int j = 0; j < N; j++) {
381  tmpval += fullBasisVectors[curDoFfield][j][dim] * timestepRBSolutions[solidx].getEntry(j);
382  }
383  f.setValue((timestep - 1) * numDoFs + dim, (float) tmpval);
384  }
385  }
386  res.addField(f);
387  break;
388  }
389  default:
390  throw new RuntimeException("Invalid/unimplemented solution field type '" + sftype.Type
391  + "' for transient RB system");
392  }
393  /*
394  * Increase field counter by the amount the current solution field
395  * used
396  */
397  curDoFfield += sftype.Type.requiredDoFFields;
398  }
399  return res;
400  }
401 
405  public int getQm() {
406  return fQm;
407  }
408 
412  public int getTotalTimesteps() {
413  return fTotalTimesteps;
414  }
415 
416  public int getVisualNumTimesteps() {
417  /*
418  * int nt = Math.round(50000/get_calN()); nt = nt>_K?_K:nt; return nt;
419  */
420  int nt = (int) Math.round(75000 / getGeometry().getNumVertices() / (1 + 0.4 * (getNumDoFFields() - 1)));
421  nt = nt > 25 ? 25 : nt; // cap nt at 25
422  return nt > fTotalTimesteps ? fTotalTimesteps : nt;
423  }
424 
428  @Override
429  protected void initialize_data_vectors() {
430  super.initialize_data_vectors();
431 
432  RB_outputs_all_k = new double[getNumOutputs()][getTotalTimesteps() + 1];
434 
435  // Resize the error bound vector
436  error_bound_all_k = new double[getTotalTimesteps() + 1];
437 
438  // Resize the array that stores the solution data at all time levels
439  timestepRBSolutions = new RealVector[getTotalTimesteps() + 1];
440  }
441 
445  @Override
446  public void loadOfflineData_rbappmit(AModelManager m) throws IOException {
447 
448  super.loadOfflineData_rbappmit(m);
449 
450  // Initialize the residual caching data storage
451  cached_Fq_Aq_vector = new double[getNBF()];
452  cached_Aq_Aq_matrix = new double[getNBF()][getNBF()];
453  cached_Fq_Mq_vector = new double[getNBF()];
454  cached_Aq_Mq_matrix = new double[getNBF()][getNBF()];
455  cached_Mq_Mq_matrix = new double[getNBF()][getNBF()];
456 
457  {
458  BufferedReader reader = m.getBufReader("RB_L2_matrix.dat");
459 
460  String[] tokens = reader.readLine().split(" ");
461 
462  // Set the size of the inner product matrix
463  RB_L2_matrix = new Array2DRowRealMatrix(getNBF(), getNBF());
464 
465  // Fill the matrix
466  int count = 0;
467  for (int i = 0; i < getNBF(); i++)
468  for (int j = 0; j < getNBF(); j++) {
469  RB_L2_matrix.setEntry(i, j, Double.parseDouble(tokens[count]));
470  count++;
471  }
472  reader.close();
473  reader = null;
474 
475  Log.d(DEBUG_TAG, "Finished reading RB_L2_matrix.dat");
476  }
477 
478  // Read in the M_q matrices
479  {
480  RB_M_q_matrix = new RealMatrix[getQm()];
481  for (int q_m = 0; q_m < getQm(); q_m++) {
482 
483  BufferedReader reader = m.getBufReader("RB_M_" + String.format("%03d", q_m) + ".dat");
484 
485  String line = reader.readLine();
486  reader.close();
487  reader = null;
488  String[] tokens = line.split(" ");
489 
490  // Set the size of the inner product matrix
491  RB_M_q_matrix[q_m] = new Array2DRowRealMatrix(getNBF(), getNBF());
492 
493  // Fill the vector
494  int count = 0;
495  for (int i = 0; i < getNBF(); i++)
496  for (int j = 0; j < getNBF(); j++) {
497  RB_M_q_matrix[q_m].setEntry(i, j, Double.parseDouble(tokens[count]));
498  count++;
499  }
500  }
501  Log.d(DEBUG_TAG, "Finished reading RB_M_q data");
502  }
503 
504  // Read in Fq_Mq representor norm data
505  {
506  BufferedReader reader = m.getBufReader("Fq_Mq_norms.dat");
507 
508  String line = reader.readLine();
509  reader.close();
510  reader = null;
511  String[] tokens = line.split(" ");
512 
513  // Declare the array
514  Fq_Mq_representor_norms = new double[getQf()][getQm()][getNBF()];
515 
516  // Fill it
517  int count = 0;
518  for (int q_f = 0; q_f < getQf(); q_f++)
519  for (int q_m = 0; q_m < getQm(); q_m++)
520  for (int i = 0; i < getNBF(); i++) {
521  Fq_Mq_representor_norms[q_f][q_m][i] = Double.parseDouble(tokens[count]);
522  count++;
523  }
524 
525  Log.d(DEBUG_TAG, "Finished reading Fq_Mq_norms.dat");
526  }
527 
528  // Read in M_M representor norm data
529  {
530  BufferedReader reader = m.getBufReader("Mq_Mq_norms.dat");
531 
532  String line = reader.readLine();
533  reader.close();
534  reader = null;
535  String[] tokens = line.split(" ");
536 
537  // Declare the array
538  int Q_m_hat = getQm() * (getQm() + 1) / 2;
539  Mq_Mq_representor_norms = new double[Q_m_hat][getNBF()][getNBF()];
540 
541  // Fill it
542  int count = 0;
543  for (int q = 0; q < Q_m_hat; q++)
544  for (int i = 0; i < getNBF(); i++)
545  for (int j = 0; j < getNBF(); j++) {
546  Mq_Mq_representor_norms[q][i][j] = Double.parseDouble(tokens[count]);
547  count++;
548  }
549  Log.d(DEBUG_TAG, "Finished reading Mq_Mq_norms.dat");
550  }
551 
552  // Read in Aq_M representor norm data
553  {
554  try {
555  BufferedReader reader = m.getBufReader("Aq_Mq_norms.dat");
556 
557  String line = reader.readLine();
558  reader.close();
559  reader = null;
560  String[] tokens = line.split(" ");
561 
562  // Declare the array
563  Aq_Mq_representor_norms = new double[getQa()][getQm()][getNBF()][getNBF()];
564 
565  // Fill it
566  int count = 0;
567  for (int q_a = 0; q_a < getQa(); q_a++)
568  for (int q_m = 0; q_m < getQm(); q_m++)
569  for (int i = 0; i < getNBF(); i++)
570  for (int j = 0; j < getNBF(); j++) {
571  Aq_Mq_representor_norms[q_a][q_m][i][j] = Double.parseDouble(tokens[count]);
572  count++;
573  }
574 
575  } catch (IOException iae) {
576  // Declare the array
577  Aq_Mq_representor_norms = new double[getQa()][getQm()][getNBF()][getNBF()];
578 
579  MathObjectReader mr = m.getMathObjReader();
580  int count = 0;
581  for (int i = 0; i < getQa(); i++)
582  for (int j = 0; j < getQm(); j++) {
583  String file = "Aq_Mq_" + String.format("%03d", i) + "_" + String.format("%03d", j)
584  + "_norms.bin";
585  Aq_Mq_representor_norms[i][j] = mr.readRawDoubleMatrix(m.getInStream(file), getNBF(), getNBF());
586 
587  // for (int k = 0; k < get_n_basis_functions(); k++)
588  // for (int l = 0; l < get_n_basis_functions(); l++)
589  // Aq_Mq_representor_norms[i][j][k][l] = dis
590  // .ReadDouble();
591  count++;
592  // dis.close();
593  }
594  }
595 
596  Log.d(DEBUG_TAG, "Finished reading Aq_Mq_norms.dat");
597  }
598  }
599 
603  @Override
604  public void loadOfflineDataJRB(AModelManager m) throws IOException {
605  super.loadOfflineDataJRB(m);
606 
607  // Initialize the residual caching data storage
608  cached_Fq_Aq_vector = new double[getNBF()];
609  cached_Aq_Aq_matrix = new double[getNBF()][getNBF()];
610  cached_Fq_Mq_vector = new double[getNBF()];
611  cached_Aq_Mq_matrix = new double[getNBF()][getNBF()];
612  cached_Mq_Mq_matrix = new double[getNBF()][getNBF()];
613 
614  MathObjectReader mr = m.getMathObjReader();
615  /*
616  * Read L2 matrix
617  */
618  RB_L2_matrix = mr.readMatrix(m.getInStream("RB_L2_matrix.bin"));
619 
620  /*
621  * Read in the M_q matrices
622  */
623  String filename;
624  RB_M_q_matrix = new RealMatrix[fQm];
625  for (int q_m = 0; q_m < fQm; q_m++) {
626  filename = "RB_M_" + String.format("%03d", q_m) + ".bin";
627  RB_M_q_matrix[q_m] = mr.readMatrix(m.getInStream(filename));
628  }
629  Log.d(DEBUG_TAG, "Finished reading RB_M_q data");
630 
631  /*
632  * Read in Fq_Mq representor norm data
633  */
634  // Declare the array
635  Fq_Mq_representor_norms = new double[getQf()][fQm][];
636  for (int q_f = 0; q_f < getQf(); q_f++) {
637  for (int q_m = 0; q_m < fQm; q_m++) {
638  filename = "Fq_Mq_" + String.format("%03d", q_f) + "_" + String.format("%03d", q_m) + ".bin";
639  Fq_Mq_representor_norms[q_f][q_m] = mr.readRawDoubleVector(m.getInStream(filename));
640  }
641  }
642  Log.d(DEBUG_TAG, "Finished reading Fq_Mq_norms.dat");
643 
644  /*
645  * Read in Mq_Mq representor norm data
646  */
647  int Q_m_hat = fQm * (fQm + 1) / 2;
648  Mq_Mq_representor_norms = new double[Q_m_hat][][];
649  for (int q1 = 0; q1 < fQm; q1++) {
650  for (int q2 = 0; q2 < fQm - q1; q2++) {
651  filename = "Mq_Mq_" + String.format("%03d", q1) + "_" + String.format("%03d", q2) + ".bin";
652  Mq_Mq_representor_norms[q2 + q1 * fQm] = mr.readRawDoubleMatrix(m.getInStream(filename));
653  }
654  }
655  Log.d(DEBUG_TAG, "Finished reading Mq_Mq_norms.dat");
656 
657  /*
658  * Read in Aq_M representor norm data
659  */
660  Aq_Mq_representor_norms = new double[getQa()][fQm][][];
661  for (int i = 0; i < getQa(); i++) {
662  for (int j = 0; j < fQm; j++) {
663  filename = "Aq_Mq_" + String.format("%03d", i) + "_" + String.format("%03d", j) + "_norms.bin";
664  Aq_Mq_representor_norms[i][j] = mr.readRawDoubleMatrix(m.getInStream(filename));
665  }
666  }
667  Log.d(DEBUG_TAG, "Finished reading Aq_Mq_norms.dat");
668  }
669 
674  @Override
675  public double RB_solve(int N) {
676  current_N = N;
677 
678  if (N > getNBF()) {
679  throw new RuntimeException("ERROR: N cannot be larger than the number " + "of basis functions in RB_solve");
680  }
681  if (N == 0) {
682  throw new RuntimeException("ERROR: N must be greater than 0 in RB_solve");
683  }
684 
685  RealMatrix RB_mass_matrix_N = null;
686  RealMatrix RB_LHS_matrix = null;
687  RealMatrix RB_RHS_matrix = null;
688 
689  boolean tdM = ((ITransient) affineFunctionsInstance).isTimeDependentM();
690  // Have time-dependent RB LHS/RHS matrices also if only theta^m are
691  // time-dependent
692  boolean tdA = affineFunctionsInstance.isTimeDependentA() || tdM;
693 
694  boolean LHSMatrixIsID = false;
695  /*
696  * Initialize constant RB matrices for time-independent theta
697  * coefficient functions. This saves time during the simulations.
698  */
699  if (!tdM) {
700  // First assemble the mass matrix
701  RB_mass_matrix_N = new Array2DRowRealMatrix(N, N);
702  for (int q_m = 0; q_m < getQm(); q_m++) {
703  RB_mass_matrix_N = RB_mass_matrix_N.add(RB_M_q_matrix[q_m].getSubMatrix(0, N - 1, 0, N - 1)
704  .scalarMultiply(thetaQm(q_m)));
705  }
706  }
707  if (!tdA) {
708  // No need to copy, "add" returns a new matrix anyways
709  RB_LHS_matrix = RB_mass_matrix_N;
710  RB_RHS_matrix = RB_mass_matrix_N;
711  // RB_LHS_matrix = new Array2DRowRealMatrix(N, N);
712  // RB_RHS_matrix = new Array2DRowRealMatrix(N, N);
713  //
714  // RB_LHS_matrix = RB_LHS_matrix.add(RB_mass_matrix_N
715  // .scalarMultiply(1. / getdt()));
716  // RB_RHS_matrix = RB_RHS_matrix.add(RB_mass_matrix_N
717  // .scalarMultiply(1. / getdt()));
718 
719  for (int q_a = 0; q_a < getQa(); q_a++) {
720  RB_LHS_matrix = RB_LHS_matrix.add(RB_A_q_vector[q_a].getSubMatrix(0, N - 1, 0, N - 1).scalarMultiply(
721  getEulerTheta() * getdt() * thetaQa(q_a)));
722  RB_RHS_matrix = RB_RHS_matrix.add(RB_A_q_vector[q_a].getSubMatrix(0, N - 1, 0, N - 1).scalarMultiply(
723  -(1. - getEulerTheta()) * getdt() * thetaQa(q_a)));
724  }
725  LHSMatrixIsID = isIdentityMatrix(RB_LHS_matrix);
726  }
727 
728  setTimeStep(0); // Sets the member variable timestep to zero
729 
730  // Get initial conditions
732  RealVector RB_solution_N = RB_solution.copy();
733  RealVector old_RB_solution_N = RB_solution_N.copy();
734 
735  // Initialize rhs
736  RealVector RB_rhs_N = new ArrayRealVector(N);
737 
738  // Load the initial condition into RB_temporal_solution_data
739  timestepRBSolutions[timestep] = RB_solution_N;
740 
741  double error_bound_sum = 0.;
742 
743  // Set error bound at _k=0
744  error_bound_all_k[timestep] = Math.sqrt(error_bound_sum);
745 
746  // Compute the outputs and associated error bounds at _k=0
747  for (int k = 0; k < getNumOutputs(); k++) {
748  RB_outputs_all_k[k][timestep] = 0.;
750  for (int q_l = 0; q_l < getQl(k); q_l++) {
751  RB_outputs_all_k[k][timestep] += thetaQl(k, q_l, 0)
752  * (RB_output_vectors[k][q_l].getSubVector(0, N).dotProduct(RB_solution_N));
753  }
755  }
756 
757  double alpha_LB = get_SCM_lower_bound();
758 
759  // Precompute time-invariant parts of the dual norm of the residual.
761 
762  /*
763  * Main time step loop
764  */
765  for (int time_level = 1; time_level <= fTotalTimesteps; time_level++) {
766  // The current time
767  double t = getdt() * (time_level - 1);
768 
769  /*
770  * Initialize constant RB matrices for time-independent theta
771  * coefficient functions. This saves time during the simulations.
772  */
773  if (tdM) {
774  // First assemble the mass matrix
775  RB_mass_matrix_N = new Array2DRowRealMatrix(N, N);
776  for (int q_m = 0; q_m < getQm(); q_m++) {
777  RB_mass_matrix_N = RB_mass_matrix_N.add(RB_M_q_matrix[q_m].getSubMatrix(0, N - 1, 0, N - 1)
778  .scalarMultiply(thetaQm(q_m, t)));
779  }
780  }
781  if (tdA) {
782  // No need to copy, "add" returns a new matrix anyways
783  RB_LHS_matrix = RB_mass_matrix_N;
784  RB_RHS_matrix = RB_mass_matrix_N;
785  for (int q_a = 0; q_a < getQa(); q_a++) {
786  RB_LHS_matrix = RB_LHS_matrix.add(RB_A_q_vector[q_a].getSubMatrix(0, N - 1, 0, N - 1)
787  .scalarMultiply(getEulerTheta() * getdt() * thetaQa(q_a, t)));
788  RB_RHS_matrix = RB_RHS_matrix.add(RB_A_q_vector[q_a].getSubMatrix(0, N - 1, 0, N - 1)
789  .scalarMultiply(-(1. - getEulerTheta()) * getdt() * thetaQa(q_a, t)));
790  }
791  LHSMatrixIsID = isIdentityMatrix(RB_LHS_matrix);
792  }
793 
794  setTimeStep(time_level); // This updates the member variable
795  // timestep
796  old_RB_solution_N = RB_solution_N;
797 
798  // Compute RB_rhs, as RB_LHS_matrix x old_RB_solution
799  RB_rhs_N = RB_RHS_matrix.operate(old_RB_solution_N);
800 
801  // Add forcing terms
802  RealVector force = new ArrayRealVector(N);
803  for (int q_f = 0; q_f < getQf(); q_f++) {
804  force = force.add(RB_F_q_vector[q_f].getSubVector(0, N).mapMultiplyToSelf(thetaQf(q_f, t)));
805  }
806  RB_rhs_N = RB_rhs_N.add(force.mapMultiplyToSelf(getdt()));
807 
808  if (!LHSMatrixIsID) {
809  // Solve the linear system
810  RB_solution_N = new LUDecompositionImpl(RB_LHS_matrix).getSolver().solve(RB_rhs_N);
811  } else {
812  RB_solution_N = RB_rhs_N;
813  }
814 
815  double[] sol = RB_solution_N.getData();
816  String sol_str = "[";
817  for (int i = 0; i < sol.length; i++) {
818  sol_str += String.format("%1.15e ", sol[i]);
819  }
820  // Log.d("TransientRBSystem", "RB_solution at t=" + String.format("%5f", time_level * getdt()) + ": "
821  // + sol_str + "]");
822 
823  // Save RB_solution for current time level
824  timestepRBSolutions[timestep] = RB_solution_N;
825 
826  // Evaluate the dual norm of the residual for RB_solution_vector
827  RB_solution = RB_solution_N;
828  old_RB_solution = old_RB_solution_N;
829  double epsilon_N = compute_residual_dual_norm(N);
830 
831  error_bound_sum += residual_scaling_numer(alpha_LB) * Math.pow(epsilon_N, 2.);
832 
833  // store error bound at time-level _k
834  error_bound_all_k[timestep] = Math.sqrt(error_bound_sum / residual_scaling_denom(alpha_LB));
835 
836  // Now compute the outputs and associated errors
837  for (int i = 0; i < getNumOutputs(); i++) {
838  RB_outputs_all_k[i][timestep] = 0.;
840  for (int q_l = 0; q_l < getQl(i); q_l++) {
841  RB_outputs_all_k[i][timestep] += thetaQl(i, q_l, t)
842  * (RB_output_vectors[i][q_l].getSubVector(0, N).dotProduct(RB_solution_N));
843  }
846  }
847  }
848 
849  // double[] sol = RB_outputs_all_k[0];
850  // String sol_str = "[";
851  // for (int i = 0; i < sol.length; i++) {
852  // sol_str += String.format("%1.5e %1.5e\n", sol[i],
853  // RB_output_error_bounds_all_k[0][i]);
854  // }
855  // Log.d("TransientRBSystem", "RB_outputs_all_k: " + sol_str + "]");
856 
857  // Now compute the L2 norm of the RB solution at time-level _K
858  // to normalize the error bound
859  // We reuse RB_rhs here
860  RealMatrix RB_L2_matrix_N = RB_L2_matrix.getSubMatrix(0, N - 1, 0, N - 1);
861  double final_RB_L2_norm = Math.sqrt(RB_L2_matrix_N.operate(RB_solution_N).dotProduct(RB_solution_N));
862 
863  if (apply_temporal_filter_flag) {
865  }
866 
867  return (return_rel_error_bound ? error_bound_all_k[fTotalTimesteps] / final_RB_L2_norm
869  }
870 
871  private boolean isIdentityMatrix(RealMatrix m) {
872  if (!m.isSquare())
873  return false;
874  for (int i = 0; i < m.getRowDimension(); i++) {
875  for (int j = 0; j < m.getColumnDimension(); j++) {
876  if ((i == j && m.getEntry(i, j) != 1) || (i != j && m.getEntry(i, j) != 0))
877  return false;
878  }
879  }
880  return true;
881  }
882 
883  @Override
885  super.readConfigurationJRB(m);
886  fQm = ((ITransient) affineFunctionsInstance).getQm();
887  dt = Double.parseDouble(m.getModelXMLTagValue("rb_model.timeinfo.dt"));
888  euler_theta = Double.parseDouble(m.getModelXMLTagValue("rb_model.timeinfo.euler_theta"));
889  fTotalTimesteps = Integer.parseInt(m.getModelXMLTagValue("rb_model.timeinfo.K"));
890 
891  n_plotting_steps = Integer
892  .parseInt(m.getModelXMLTagValue("model.visual.plotSteps", "" + (fTotalTimesteps + 1)));
893  }
894 
899  @Override
900  protected void readConfigurationRBAppMIT(GetPot infile) {
901  super.readConfigurationRBAppMIT(infile);
902 
903  dt = infile.call("dt", 0.);
904  fTotalTimesteps = infile.call("K", 0);
905  euler_theta = infile.call("euler_theta", 1.);
906 
907  int apply_temporal_filter_flag_in = infile.call("apply_temporal_filter_flag", 0);
908  apply_temporal_filter_flag = (apply_temporal_filter_flag_in != 0);
909 
910  double filter_width_in = infile.call("filter_width", 2.);
911  filter_width = filter_width_in;
912 
913  int n_plotting_steps_in = infile.call("n_plotting_steps", getTotalTimesteps() + 1);
914  n_plotting_steps = n_plotting_steps_in;
915 
916  Log.d(DEBUG_TAG, "TransientRBSystem parameters from " + Const.parameters_filename + ":");
917  Log.d(DEBUG_TAG, "dt: " + getdt());
918  Log.d(DEBUG_TAG, "Number of time steps: " + getTotalTimesteps());
919  Log.d(DEBUG_TAG, "euler_theta (for generalized Euler): " + getEulerTheta());
920  Log.d(DEBUG_TAG, "Apply a temporal filter? " + apply_temporal_filter_flag);
921  if (apply_temporal_filter_flag) {
922  Log.d(DEBUG_TAG, "Temporal filter std. dev. " + filter_width);
923  Log.d(DEBUG_TAG, "Number of timesteps to be plotted" + n_plotting_steps);
924  }
925 
926  fQm = ((ITransient) affineFunctionsInstance).getQm();
927  Log.d(DEBUG_TAG, "Q_m = " + fQm);
928  }
929 
934  @Override
935  protected double residual_scaling_denom(double alpha_LB) {
936  return alpha_LB;
937  }
938 
943  protected double residual_scaling_numer(double alpha_LB) {
944  return getdt();
945  }
946 
947  // PROTECTED FUNCTIONS
948 
949  public void setTimeStep(int k_in) {
950  this.timestep = k_in;
951  }
952 
959  public double thetaQm(int i) {
960  return thetaQm(i, 0);
961  }
962 
963  // public void set_dt(double dt_in) {
964  // this.dt = dt_in;
965  // }
966  //
967  // public void set_euler_theta(double euler_theta_in) {
968  // this.euler_theta = euler_theta_in;
969  // }
970  //
971  // public void set_K(int K_in) {
972  // this._K = K_in;
973  // }
974 
982  public double thetaQm(int i, double t) {
983  return ((ITransient) affineFunctionsInstance).thetaQm(i, getParams().getCurrent(), t);
984  }
985 
986  // /**
987  // * Set the secondary SCM system
988  // */
989  // public void setSecondarySCM(RBSCMSystem second_scm_system) {
990  // mSecondRbScmSystem = second_scm_system;
991  // }
992 
997  protected double uncached_compute_residual_dual_norm(int N) {
998 
999  RealVector RB_u_euler_theta = RB_solution.mapMultiply(getEulerTheta()).add(
1000  old_RB_solution.mapMultiply(1. - getEulerTheta()));
1001  RealVector mass_coeffs = RB_solution.subtract(old_RB_solution).mapMultiply(-1. / getdt());
1002 
1003  double residual_norm_sq = 0.;
1004 
1005  int q = 0;
1006  for (int q_f1 = 0; q_f1 < getQf(); q_f1++) {
1007  double cached_theta_q_f1 = thetaQf(q_f1);
1008  for (int q_f2 = q_f1; q_f2 < getQf(); q_f2++) {
1009  double delta = (q_f1 == q_f2) ? 1. : 2.;
1010  residual_norm_sq += delta * cached_theta_q_f1 * thetaQf(q_f2) * Fq_representor_norms[q];
1011 
1012  q++;
1013  }
1014  }
1015 
1016  for (int q_f = 0; q_f < getQf(); q_f++) {
1017  double cached_theta_q_f = thetaQf(q_f);
1018  for (int q_a = 0; q_a < getQa(); q_a++) {
1019  double cached_theta_q_a = thetaQa(q_a);
1020  for (int i = 0; i < N; i++) {
1021  residual_norm_sq += 2. * RB_u_euler_theta.getEntry(i) * cached_theta_q_f * cached_theta_q_a
1022  * Fq_Aq_representor_norms[q_f][q_a][i];
1023  }
1024  }
1025  }
1026 
1027  q = 0;
1028  for (int q_a1 = 0; q_a1 < getQa(); q_a1++) {
1029  double cached_theta_q_a1 = thetaQa(q_a1);
1030  for (int q_a2 = q_a1; q_a2 < getQa(); q_a2++) {
1031  double cached_theta_q_a2 = thetaQa(q_a2);
1032  double delta = (q_a1 == q_a2) ? 1. : 2.;
1033 
1034  for (int i = 0; i < N; i++) {
1035  for (int j = 0; j < N; j++) {
1036  residual_norm_sq += delta * RB_u_euler_theta.getEntry(i) * RB_u_euler_theta.getEntry(j)
1037  * cached_theta_q_a1 * cached_theta_q_a2 * Aq_Aq_representor_norms[q][i][j];
1038  }
1039  }
1040  q++;
1041  }
1042  }
1043 
1044  // Now add the terms due to the time-derivative
1045  q = 0;
1046  for (int q_m1 = 0; q_m1 < getQm(); q_m1++) {
1047  double cached_theta_q_m1 = thetaQm(q_m1);
1048  for (int q_m2 = q_m1; q_m2 < getQm(); q_m2++) {
1049  double cached_theta_q_m2 = thetaQm(q_m2);
1050  double delta = (q_m1 == q_m2) ? 1. : 2.;
1051 
1052  for (int i = 0; i < N; i++) {
1053  for (int j = 0; j < N; j++) {
1054  residual_norm_sq += delta * mass_coeffs.getEntry(i) * mass_coeffs.getEntry(j)
1055  * cached_theta_q_m1 * cached_theta_q_m2 * Mq_Mq_representor_norms[q][i][j];
1056  }
1057  }
1058  q++;
1059  }
1060  }
1061 
1062  for (int q_f = 0; q_f < getQf(); q_f++) {
1063  double cached_theta_q_f = thetaQf(q_f);
1064 
1065  for (int q_m = 0; q_m < getQm(); q_m++) {
1066  double cached_theta_q_m = thetaQm(q_m);
1067 
1068  for (int i = 0; i < N; i++) {
1069  residual_norm_sq += 2. * mass_coeffs.getEntry(i) * cached_theta_q_f * cached_theta_q_m
1070  * Fq_Mq_representor_norms[q_f][q_m][i];
1071  }
1072  }
1073  }
1074 
1075  for (int q_a = 0; q_a < getQa(); q_a++) {
1076  double cached_theta_q_a = thetaQa(q_a);
1077  for (int q_m = 0; q_m < getQm(); q_m++) {
1078  double cached_theta_q_m = thetaQm(q_m);
1079 
1080  for (int i = 0; i < N; i++) {
1081  for (int j = 0; j < N; j++) {
1082  residual_norm_sq += 2. * RB_u_euler_theta.getEntry(i) * mass_coeffs.getEntry(j)
1083  * cached_theta_q_a * cached_theta_q_m * Aq_Mq_representor_norms[q_a][q_m][i][j];
1084  }
1085  }
1086  }
1087  }
1088 
1089  if (residual_norm_sq < 0) {
1090  Log.d(DEBUG_TAG, "Warning: Square of residual norm is negative "
1091  + "in TransientRBSystem::compute_residual_dual_norm()");
1092 
1093  // Sometimes this is negative due to rounding error,
1094  // but error is on the order of 1.e-10, so shouldn't
1095  // affect result
1096  residual_norm_sq = Math.abs(residual_norm_sq);
1097  }
1098 
1099  return Math.sqrt(residual_norm_sq);
1100  }
1101 }
GeometryData getGeometry()
The model&#39;s geometry data.
Definition: ModelBase.java:69
int getNumOutputs()
Definition: RBSystem.java:612
double thetaQm(int i, double t)
Evaluate theta_q_m (for the q^th mass matrix term) at the current parameter.
double compute_output_dual_norm(int i, double t)
Compute the dual norm of the i^th output function at the current parameter value. ...
Definition: RBSystem.java:402
void cache_online_residual_terms(int N)
Helper function that caches the time-independent residual quantities.
float[][][] fullBasisVectors
Definition: RBSystem.java:114
int getNumDoFFields()
Returns the number of degree-of-freedom fields generated/computed by the model.
Definition: ModelBase.java:78
Utility helper class from rbAppMIT included for compatibility of rbAppMIT model loading.
Definition: GetPot.java:31
double residual_scaling_denom(double alpha_LB)
Specifies the residual scaling on the denominator to be used in the a posteriori error bound...
This class provides the Online stage for the reduced basis method for elliptic steady state problems...
Definition: RBSystem.java:54
The default solution field containing an array of real values.
int current_N
Definition: RBSystem.java:80
RealMatrix RB_L2_matrix
A secondary SCM object since we might need a lower bound for the mass matrix and the stiffness matrix...
double[][][] Fq_Aq_representor_norms
Definition: RBSystem.java:85
Represents the results of a simulation.
This class provides the Online reduced basis functionality for linear parabolic problems.
Interface for AffineFunctions in unsteady rb systems.
Definition: ITransient.java:12
Reading matrices and vectors with a bunch of convenient overloads for different sources and output fo...
RealVector getInitialCoefficients(int N)
Returns the initial conditions solution coefficients for RB size N.
Definition: RBSystem.java:588
int timestep
The current time-level, 0 &lt;= _k &lt;= _K.
Parameters getParams()
Returns the system&#39;s parameters object.
Definition: RBSystem.java:621
void readConfigurationRBAppMIT(GetPot infile)
double[][][] Aq_Aq_representor_norms
Definition: RBSystem.java:77
double thetaQl(int k, int i)
Definition: RBSystem.java:1720
double compute_residual_dual_norm(int N)
Compute the dual norm of the residual for the solution saved in RB_solution_vector.
IAffineFunctions affineFunctionsInstance
The member object that defines the parameter-dependent functions for the affine expansion of the left...
Definition: RBSystem.java:75
boolean return_rel_error_bound
Boolean flag to indicate whether RB_solve returns an absolute or relative error bound.
Definition: RBSystem.java:209
double[] Fq_representor_norms
Arrays storing the residual representor inner products to be used in computing the residuals in the O...
Definition: RBSystem.java:91
void readConfigurationJRB(AModelManager m)
double conv_weight(double x)
double thetaQa(int q)
Evaluate theta_q_a (for the q^th bilinear form) at the current parameter.
Definition: RBSystem.java:1681
RealVector old_RB_solution
RBSystem has a member RB_solution, we also need old_RB_solution here.
double thetaQf(int i)
Definition: RBSystem.java:1700
This class serves as base class for accessing various types of models at different locations...
RealMatrix[] RB_M_q_matrix
Dense matrices for the RB computations.
void apply_temporal_filter()
Apply the temporal filter to the outputs.
RealVector[] timestepRBSolutions
The solution coefficients at each time level from the most recent RB_solve.
int getQf()
TODO: if all affine_functions implement the IAffineFunctions interface, just call the getQf method of...
Definition: RBSystem.java:638
double uncached_compute_residual_dual_norm(int N)
Set the secondary SCM system.
RealVector RB_solution
The RB solution vector.
Definition: RBSystem.java:201
FieldDescriptor[] logicalFieldTypes
The logical output fields of the model, each collecting one ore more model DoF&#39;s into a related unit...
Definition: ModelBase.java:26
double getEulerTheta()
Get/set euler_theta, parameter that determines the temporal discretization.
double getdt()
Gets dt, the time-step size.
Provides a Log class imitating the Android Log class when not used on android systems.
Definition: Log.java:11
void initialize_data_vectors()
Resize the output vectors according to n_outputs.
double[][] RB_output_error_bounds_all_k
The output error bounds at all time levels.
Definition: RBSystem.java:183
RealMatrix[] RB_A_q_vector
Dense matrices for the RB computations.
Definition: RBSystem.java:163
double residual_scaling_numer(double alpha_LB)
Specifies the residual scaling on the numerator to be used in the a posteriori error bound...
double RB_solve(int N)
Perform online solve with the N RB basis functions, for the set of parameters in current_params, where 1 &lt;= N &lt;= RB_size.
double[][] RB_outputs_all_k
The outputs at all time levels.
Definition: RBSystem.java:197
int getQa()
Definition: RBSystem.java:628
RealVector[][] RB_output_vectors
The vectors storing the RB output vectors.
Definition: RBSystem.java:187
double[] error_bound_all_k
The error bound for the field variable at each time level.
int getTotalTimesteps()
Get K, the total number of time-steps.
RealVector[] RB_F_q_vector
Dense vector for the RHS.
Definition: RBSystem.java:168
double thetaQm(int i)
Evaluate theta_q_m (for the q^th mass matrix term) at the current parameter.
int getNBF()
Definition: RBSystem.java:605
void loadOfflineDataJRB(AModelManager m)
Override read_offline_data_from_files in order to read in the mass matrix and initial condition data ...
Default mesh transformation.
void loadOfflineData_rbappmit(AModelManager m)
Override read_offline_data_from_files in order to read in the mass matrix and initial condition data ...
Contains information about the logical solution fields.
SimulationResult getSimulationResults()
Returns the animated results of the transient RB system.
int getQl(int output_index)
TODO: if all affine_functions implement the IAffineFunctions interface, just call the getQl method of...
Definition: RBSystem.java:650
int fTotalTimesteps
Total number of time-steps.
double get_SCM_lower_bound()
Definition: RBSystem.java:551
int n_plotting_steps
The number of time steps we actually plot in the output plotter.