libMesh
transient_rb_construction.C
Go to the documentation of this file.
1 // rbOOmit: An implementation of the Certified Reduced Basis method.
2 // Copyright (C) 2009, 2010 David J. Knezevic
3 
4 // This file is part of rbOOmit.
5 
6 // rbOOmit is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 
11 // rbOOmit is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
15 
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 
20 // rbOOmit includes
21 #include "libmesh/transient_rb_construction.h"
22 #include "libmesh/transient_rb_evaluation.h"
23 #include "libmesh/transient_rb_theta_expansion.h"
24 #include "libmesh/transient_rb_assembly_expansion.h"
25 
26 // LibMesh includes
27 #include "libmesh/numeric_vector.h"
28 #include "libmesh/sparse_matrix.h"
29 #include "libmesh/dof_map.h"
30 #include "libmesh/libmesh_logging.h"
31 #include "libmesh/linear_solver.h"
32 #include "libmesh/equation_systems.h"
33 #include "libmesh/exodusII_io.h"
34 #include "libmesh/getpot.h"
35 #include "libmesh/dense_matrix.h"
36 #include "libmesh/dense_vector.h"
37 #include "libmesh/xdr_cxx.h"
38 #include "libmesh/timestamp.h"
39 
40 // TIMPI includes
41 #include "timpi/communicator.h"
42 
43 // For checking for the existence of files
44 #include <sys/stat.h>
45 
46 #include <fstream>
47 #include <sstream>
48 
49 // Need SLEPc to get the POD eigenvalues
50 #if defined(LIBMESH_HAVE_SLEPC)
51 // LAPACK include (via SLEPc)
52 #include "libmesh/ignore_warnings.h"
53 #include <petscsys.h>
54 #include <slepcblaslapack.h>
55 #include "libmesh/restore_warnings.h"
56 #endif // LIBMESH_HAVE_SLEPC
57 
58 namespace libMesh
59 {
60 
62  const std::string & name_in,
63  const unsigned int number_in)
64  : Parent(es, name_in, number_in),
65  L2_matrix(SparseMatrix<Number>::build(es.comm())),
66  non_dirichlet_L2_matrix(SparseMatrix<Number>::build(es.comm())),
67  nonzero_initialization(false),
68  compute_truth_projection_error(false),
69  init_filename(""),
70  POD_tol(-1.),
71  max_truth_solves(-1),
72  L2_assembly(nullptr)
73 {
74  // Indicate that we need to compute the RB
75  // inner product matrix in this case
77 
78  // We should not necessarily exit the greedy due to repeated parameters in
79  // the transient case
81 }
82 
84 
86 {
87  Parent::clear();
88 
89  // clear the mass matrices
90  M_q_vector.clear();
91 
94 
95  // clear the temporal_data
96  temporal_data.clear();
97 }
98 
100  bool skip_vector_assembly)
101 {
102  // Check that the theta and assembly objects are consistently sized
103 #ifndef NDEBUG
104  TransientRBThetaExpansion & trans_theta_expansion =
105  cast_ref<TransientRBThetaExpansion &>(get_rb_theta_expansion());
106 
107  TransientRBAssemblyExpansion & trans_assembly_expansion =
108  cast_ref<TransientRBAssemblyExpansion &>(get_rb_assembly_expansion());
109 #endif
110  // This assert only gets called if DEBUG is on
111  libmesh_assert_equal_to (trans_theta_expansion.get_n_M_terms(), trans_assembly_expansion.get_n_M_terms());
112 
113  Parent::initialize_rb_construction(skip_matrix_assembly, skip_vector_assembly);
114 }
115 
116 void TransientRBConstruction::process_parameters_file (const std::string & parameters_filename)
117 {
118  Parent::process_parameters_file(parameters_filename);
119 
120  // Read in data from parameters_filename
121  GetPot infile(parameters_filename);
122 
123  // Read in the generic temporal discretization data
124  process_temporal_parameters_file(parameters_filename);
125 
126  // Read in the data specific to Construction
127  nonzero_initialization = infile("nonzero_initialization",nonzero_initialization);
128  init_filename = infile("init_filename",init_filename);
129 
130  const Real POD_tol_in = infile("POD_tol", POD_tol);
131  const int max_truth_solves_in = infile("max_truth_solves", max_truth_solves);
132  const unsigned int delta_N_in = infile("delta_N", delta_N);
133 
134  set_POD_tol(POD_tol_in);
135  set_max_truth_solves(max_truth_solves_in);
136  set_delta_N(delta_N_in);
137 
138  // Pass the temporal discretization data to the RBEvaluation
139  TransientRBEvaluation & trans_rb_eval = cast_ref<TransientRBEvaluation &>(get_rb_evaluation());
140  trans_rb_eval.pull_temporal_discretization_data( *this );
141 }
142 
144 {
146 
147  libMesh::out << std::endl << "TransientRBConstruction parameters:" << std::endl;
148 
150  {
151  // Print out info that describes the current setup
152  auto & trans_theta_expansion =
153  cast_ref<const TransientRBThetaExpansion &>(get_rb_theta_expansion());
154  libMesh::out << "Q_m: " << trans_theta_expansion.get_n_M_terms() << std::endl;
155  }
156  else
157  {
158  libMesh::out << "RBThetaExpansion member is not set yet" << std::endl;
159  }
160  libMesh::out << "Number of time-steps: " << get_n_time_steps() << std::endl;
161  libMesh::out << "dt: " << get_delta_t() << std::endl;
162  libMesh::out << "euler_theta (time discretization parameter): " << get_euler_theta() << std::endl;
163  if (get_POD_tol() > 0.)
164  libMesh::out << "POD_tol: " << get_POD_tol() << std::endl;
165  if (max_truth_solves > 0)
166  libMesh::out << "Maximum number of truth solves: " << max_truth_solves << std::endl;
167  libMesh::out << "delta_N (number of basis functions to add each POD-Greedy step): " << get_delta_N() << std::endl;
169  {
170  libMesh::out << "Reading initial condition from " << init_filename << std::endl;
171  }
172  else
173  {
174  libMesh::out << "Using zero initial condition" << std::endl;
175  }
176  libMesh::out << std::endl;
177 }
178 
180 {
182 
183  TransientRBThetaExpansion & trans_theta_expansion =
184  cast_ref<TransientRBThetaExpansion &>(get_rb_theta_expansion());
185  const unsigned int Q_m = trans_theta_expansion.get_n_M_terms();
186  const unsigned int n_outputs = trans_theta_expansion.get_n_outputs();
187 
188  // Resize and allocate vectors for storing mesh-dependent data
189  const unsigned int n_time_levels = get_n_time_steps()+1;
190  temporal_data.resize(n_time_levels);
191 
192  // Resize vectors for storing mesh-dependent data but only
193  // initialize if initialize_mesh_dependent_data == true
194  M_q_vector.resize(Q_m);
195 
196  // Only initialize the mass matrices if we
197  // are not in single-matrix mode
198  {
199  DofMap & dof_map = this->get_dof_map();
200 
201  dof_map.attach_matrix(*L2_matrix);
202  L2_matrix->init();
203  L2_matrix->zero();
204 
205  for (unsigned int q=0; q<Q_m; q++)
206  {
207  // Initialize the memory for the matrices
209  dof_map.attach_matrix(*M_q_vector[q]);
210  M_q_vector[q]->init();
211  M_q_vector[q]->zero();
212  }
213 
214  // We also need to initialize a second set of non-Dirichlet operators
216  {
218  non_dirichlet_L2_matrix->init();
219  non_dirichlet_L2_matrix->zero();
220 
221  non_dirichlet_M_q_vector.resize(Q_m);
222  for (unsigned int q=0; q<Q_m; q++)
223  {
224  // Initialize the memory for the matrices
227  non_dirichlet_M_q_vector[q]->init();
228  non_dirichlet_M_q_vector[q]->zero();
229  }
230  }
231  }
232 
233  for (unsigned int i=0; i<n_time_levels; i++)
234  {
236  temporal_data[i]->init (this->n_dofs(), this->n_local_dofs(), false, PARALLEL);
237  }
238 
239  // and the truth output vectors
240  truth_outputs_all_k.resize(n_outputs);
241  for (unsigned int n=0; n<n_outputs; n++)
242  {
243  truth_outputs_all_k[n].resize(n_time_levels);
244  }
245 
246  // This vector is for storing rhs entries for
247  // computing the projection of the initial condition
248  // into the RB space
250 }
251 
253  bool skip_vector_assembly)
254 {
255  // Call parent's assembly functions
256  Parent::assemble_affine_expansion(skip_matrix_assembly, skip_vector_assembly);
257 
258  // Now update RB_ic_proj_rhs_all_N if necessary.
259  // This allows us to compute the L2 projection
260  // of the initial condition into the RB space
261  // so that we can continue to enrich a given RB
262  // space.
263  if (get_rb_evaluation().get_n_basis_functions() > 0)
264  {
265  // Load the initial condition into the solution vector
267 
268  std::unique_ptr<NumericVector<Number>> temp1 = NumericVector<Number>::build(this->comm());
269  temp1->init (this->n_dofs(), this->n_local_dofs(), false, PARALLEL);
270 
271  // First compute the right-hand side vector for the L2 projection
272  L2_matrix->vector_mult(*temp1, *solution);
273 
274  for (unsigned int i=0; i<get_rb_evaluation().get_n_basis_functions(); i++)
275  {
276  RB_ic_proj_rhs_all_N(i) = temp1->dot(get_rb_evaluation().get_basis_function(i));
277  }
278  }
279 }
280 
281 Real TransientRBConstruction::train_reduced_basis(const bool resize_rb_eval_data)
282 {
283  libmesh_error_msg_if(get_RB_training_type() == "POD",
284  "POD RB training is not supported with TransientRBConstruction");
285 
287  Real value = Parent::train_reduced_basis(resize_rb_eval_data);
289 
290  return value;
291 }
292 
294 {
295  TransientRBThetaExpansion & trans_theta_expansion =
296  cast_ref<TransientRBThetaExpansion &>(get_rb_theta_expansion());
297 
298  libmesh_error_msg_if(q >= trans_theta_expansion.get_n_M_terms(),
299  "Error: We must have q < Q_m in get_M_q.");
300 
301  return M_q_vector[q].get();
302 }
303 
305 {
306  libmesh_error_msg_if(!store_non_dirichlet_operators,
307  "Error: Must have store_non_dirichlet_operators==true to access non_dirichlet_M_q.");
308 
309  TransientRBThetaExpansion & trans_theta_expansion =
310  cast_ref<TransientRBThetaExpansion &>(get_rb_theta_expansion());
311 
312  libmesh_error_msg_if(q >= trans_theta_expansion.get_n_M_terms(),
313  "Error: We must have q < Q_m in get_M_q.");
314 
315  return non_dirichlet_M_q_vector[q].get();
316 }
317 
318 void TransientRBConstruction::get_all_matrices(std::map<std::string, SparseMatrix<Number> *> & all_matrices)
319 {
320  Parent::get_all_matrices(all_matrices);
321 
322  all_matrices["L2_matrix"] = L2_matrix.get();
323 
325  all_matrices["L2_matrix_non_dirichlet"] = non_dirichlet_L2_matrix.get();
326 
327  TransientRBThetaExpansion & trans_theta_expansion =
328  cast_ref<TransientRBThetaExpansion &>(get_rb_theta_expansion());
329  const unsigned int Q_m = trans_theta_expansion.get_n_M_terms();
330 
331  for (unsigned int q_m=0; q_m<Q_m; q_m++)
332  {
333  std::stringstream matrix_name;
334  matrix_name << "M" << q_m;
335  all_matrices[matrix_name.str()] = get_M_q(q_m);
336 
338  {
339  matrix_name << "_non_dirichlet";
340  all_matrices[matrix_name.str()] = get_non_dirichlet_M_q(q_m);
341  }
342  }
343 }
344 
345 void TransientRBConstruction::assemble_L2_matrix(SparseMatrix<Number> * input_matrix, bool apply_dirichlet_bc)
346 {
347  input_matrix->zero();
349  L2_assembly,
350  input_matrix,
351  nullptr,
352  false, /* symmetrize */
353  apply_dirichlet_bc);
354 }
355 
357 {
358  input_matrix->zero();
359  add_scaled_mass_matrix(1., input_matrix);
360 }
361 
363 {
364  const RBParameters & mu = get_parameters();
365 
366  TransientRBThetaExpansion & trans_theta_expansion =
367  cast_ref<TransientRBThetaExpansion &>(get_rb_theta_expansion());
368 
369  const unsigned int Q_m = trans_theta_expansion.get_n_M_terms();
370 
371  for (unsigned int q=0; q<Q_m; q++)
372  input_matrix->add(scalar * trans_theta_expansion.eval_M_theta(q,mu), *get_M_q(q));
373 }
374 
376  NumericVector<Number> & dest,
377  NumericVector<Number> & arg)
378 {
379  LOG_SCOPE("mass_matrix_scaled_matvec()", "TransientRBConstruction");
380 
381  dest.zero();
382 
383  const RBParameters & mu = get_parameters();
384 
385  TransientRBThetaExpansion & trans_theta_expansion =
386  cast_ref<TransientRBThetaExpansion &>(get_rb_theta_expansion());
387 
388  const unsigned int Q_m = trans_theta_expansion.get_n_M_terms();
389 
390  std::unique_ptr<NumericVector<Number>> temp_vec = NumericVector<Number>::build(this->comm());
391  temp_vec->init (this->n_dofs(), this->n_local_dofs(), false, PARALLEL);
392 
393  for (unsigned int q=0; q<Q_m; q++)
394  {
395  get_M_q(q)->vector_mult(*temp_vec, arg);
396  dest.add(scalar * trans_theta_expansion.eval_M_theta(q,mu), *temp_vec);
397  }
398 }
399 
401 {
402  LOG_SCOPE("truth_assembly()", "TransientRBConstruction");
403 
404  this->matrix->close();
405 
406  this->matrix->zero();
407  this->rhs->zero();
408 
409  const RBParameters & mu = get_parameters();
410 
411  TransientRBThetaExpansion & trans_theta_expansion =
412  cast_ref<TransientRBThetaExpansion &>(get_rb_theta_expansion());
413 
414  const unsigned int Q_a = trans_theta_expansion.get_n_A_terms();
415  const unsigned int Q_f = trans_theta_expansion.get_n_F_terms();
416 
417  const Real dt = get_delta_t();
418  const Real euler_theta = get_euler_theta();
419 
420  {
421  // We should have already assembled the matrices
422  // and vectors in the affine expansion, so
423  // just use them
424 
427 
428  std::unique_ptr<NumericVector<Number>> temp_vec = NumericVector<Number>::build(this->comm());
429  temp_vec->init (this->n_dofs(), this->n_local_dofs(), false, PARALLEL);
430 
431  for (unsigned int q_a=0; q_a<Q_a; q_a++)
432  {
433  matrix->add(euler_theta*trans_theta_expansion.eval_A_theta(q_a,mu), *get_Aq(q_a));
434 
435  get_Aq(q_a)->vector_mult(*temp_vec, *current_local_solution);
436  temp_vec->scale( -(1.-euler_theta)*trans_theta_expansion.eval_A_theta(q_a,mu) );
437  rhs->add(*temp_vec);
438  }
439 
440  for (unsigned int q_f=0; q_f<Q_f; q_f++)
441  {
442  *temp_vec = *get_Fq(q_f);
443  temp_vec->scale( get_control(get_time_step())*trans_theta_expansion.eval_F_theta(q_f,mu) );
444  rhs->add(*temp_vec);
445  }
446 
447  }
448 
449  this->matrix->close();
450  this->rhs->close();
451 }
452 
454 {
455  L2_assembly = &L2_assembly_in;
456 }
457 
459 {
460  libmesh_error_msg_if(!L2_assembly, "Error: L2_assembly hasn't been initialized yet");
461 
462  return *L2_assembly;
463 }
464 
465 void TransientRBConstruction::assemble_Mq_matrix(unsigned int q, SparseMatrix<Number> * input_matrix, bool apply_dirichlet_bc)
466 {
467  TransientRBThetaExpansion & trans_theta_expansion =
468  cast_ref<TransientRBThetaExpansion &>(get_rb_theta_expansion());
469 
470  TransientRBAssemblyExpansion & trans_assembly_expansion =
471  cast_ref<TransientRBAssemblyExpansion &>(get_rb_assembly_expansion());
472 
473  libmesh_error_msg_if(q >= trans_theta_expansion.get_n_M_terms(),
474  "Error: We must have q < Q_m in assemble_Mq_matrix.");
475 
476  input_matrix->zero();
478  &trans_assembly_expansion.get_M_assembly(q),
479  input_matrix,
480  nullptr,
481  false, /* symmetrize */
482  apply_dirichlet_bc);
483 }
484 
486 {
488 
489  TransientRBThetaExpansion & trans_theta_expansion =
490  cast_ref<TransientRBThetaExpansion &>(get_rb_theta_expansion());
491 
492  for (unsigned int q=0; q<trans_theta_expansion.get_n_M_terms(); q++)
494 
496  {
497  for (unsigned int q=0; q<trans_theta_expansion.get_n_M_terms(); q++)
499  }
500 }
501 
503 {
504  libMesh::out << "Assembling L2 matrix" << std::endl;
506 
508  {
509  libMesh::out << "Assembling non-Dirichlet L2 matrix" << std::endl;
510  assemble_L2_matrix(non_dirichlet_L2_matrix.get(), /* apply_dirichlet_bc = */ false);
511  }
512 
514 }
515 
517 {
518  LOG_SCOPE("truth_solve()", "TransientRBConstruction");
519 
520  const RBParameters & mu = get_parameters();
521  const unsigned int n_time_steps = get_n_time_steps();
522 
523  // // NumericVector for computing true L2 error
524  // std::unique_ptr<NumericVector<Number>> temp = NumericVector<Number>::build();
525  // temp->init (this->n_dofs(), this->n_local_dofs(), false, PARALLEL);
526 
527  // Apply initial condition again.
529  set_time_step(0);
530 
531  // Now compute the truth outputs
532  for (unsigned int n=0; n<get_rb_theta_expansion().get_n_outputs(); n++)
533  {
534  truth_outputs_all_k[n][0] = 0.;
535  for (unsigned int q_l=0; q_l<get_rb_theta_expansion().get_n_output_terms(n); q_l++)
536  {
538  get_output_vector(n,q_l)->dot(*solution);
539  }
540  }
541 
542  // Load initial projection error into temporal_data dense matrix
545 
546  for (unsigned int time_level=1; time_level<=n_time_steps; time_level++)
547  {
548  set_time_step(time_level);
549 
551 
552  // We assume that the truth assembly has been attached to the system
553  truth_assembly();
554 
555  // truth_assembly assembles into matrix and rhs, so use those for the solve
557 
558  // The matrix doesn't change at each timestep, so we
559  // can set reuse_preconditioner == true
560  linear_solver->reuse_preconditioner(true);
561 
562  if (assert_convergence)
563  {
565  }
566 
567  // Now compute the truth outputs
568  for (unsigned int n=0; n<get_rb_theta_expansion().get_n_outputs(); n++)
569  {
570  truth_outputs_all_k[n][time_level] = 0.;
571  for (unsigned int q_l=0; q_l<get_rb_theta_expansion().get_n_output_terms(n); q_l++)
572  {
573  truth_outputs_all_k[n][time_level] +=
575  }
576  }
577 
578  // load projection error into column _k of temporal_data matrix
581 
582  if ((write_interval > 0) && (time_level%write_interval == 0))
583  {
584  libMesh::out << std::endl << "Truth solve, plotting time step " << time_level << std::endl;
585 
586  std::ostringstream file_name;
587 
588  file_name << "truth.e.";
589  file_name << std::setw(3)
590  << std::setprecision(0)
591  << std::setfill('0')
592  << std::right
593  << time_level;
594 
595 #ifdef LIBMESH_HAVE_EXODUS_API
596  ExodusII_IO(get_mesh()).write_equation_systems (file_name.str(),
597  this->get_equation_systems());
598 #endif
599  }
600  }
601 
602  // Set reuse_preconditioner back to false for subsequent solves.
603  linear_solver->reuse_preconditioner(false);
604 
605  // Get the L2 norm of the truth solution at time-level _K
606  // Useful for normalizing our true error data
608  Real final_truth_L2_norm = libmesh_real(std::sqrt(inner_product_storage_vector->dot(*solution)));
609 
610 
611  return final_truth_L2_norm;
612 }
613 
614 bool
616  Real initial_greedy_error,
617  int count)
618 {
619  if ((get_max_truth_solves()>0) && (count >= get_max_truth_solves()))
620  {
621  libMesh::out << "Maximum number of truth solves reached: max = "
622  << count << std::endl;
623  return true;
624  }
625 
626  return Parent::greedy_termination_test(abs_greedy_error, initial_greedy_error, count);
627 }
628 
630 {
631  LOG_SCOPE("set_error_temporal_data()", "TransientRBConstruction");
632 
633  // first compute the projection of solution onto the current
634  // RB space
635 
636  const unsigned int time_step = get_time_step();
637 
638  if (get_rb_evaluation().get_n_basis_functions() == 0)
639  {
640  // If the basis is empty, then the error is the solution itself
641  temporal_data[time_step]->zero();
642  temporal_data[time_step]->add(1., *solution);
643  }
644  else
645  {
646  unsigned int RB_size = get_rb_evaluation().get_n_basis_functions();
647 
648  std::unique_ptr<NumericVector<Number>> temp = NumericVector<Number>::build(this->comm());
649  temp->init (this->n_dofs(), this->n_local_dofs(), false, PARALLEL);
650 
651  // First compute the right-hand side vector for the projection
653 
654  // zero_dirichlet_dofs_on_vector(*temp);
655 
656  // Do not assume that RB_stiffness matrix is diagonal,
657  // diagonality degrades as N increases
658 
659  // Get an appropriately sized copy of RB_inner_product_matrix
660  DenseMatrix<Number> RB_inner_product_matrix_N(RB_size,RB_size);
661  for (unsigned int i=0; i<RB_size; i++)
662  for (unsigned int j=0; j<RB_size; j++)
663  {
664  RB_inner_product_matrix_N(i,j) = get_rb_evaluation().RB_inner_product_matrix(i,j);
665  }
666 
667  // Compute the projection RHS
668  DenseVector<Number> RB_proj_rhs(RB_size);
669  for (unsigned int i=0; i<RB_size; i++)
670  {
671  RB_proj_rhs(i) = temp->dot(get_rb_evaluation().get_basis_function(i));
672  }
673 
674  DenseVector<Number> RB_proj(RB_size);
675 
676  // Now solve the linear system
677  RB_inner_product_matrix_N.lu_solve(RB_proj_rhs, RB_proj);
678 
679  // Load the RB projection into temp
680  temp->zero();
681  for (unsigned int i=0; i<RB_size; i++)
682  {
683  temp->add(RB_proj(i), get_rb_evaluation().get_basis_function(i));
684  }
685 
686  temp->add(-1., *solution);
687 
688  // Now temp holds the projection error, store in temporal_data
689  *(temporal_data[time_step]) = *temp;
690  }
691 
692  // return the square of the X norm of the truth solution
694 
696 }
697 
699 {
700  LOG_SCOPE("get_error_temporal_data()", "TransientRBConstruction");
701 
702  const unsigned int time_step = get_time_step();
703 
704  return *temporal_data[time_step];
705 }
706 
708 {
710  {
711  // Use System::read_serialized_data to read the initial condition
712  // into this->solution
713  Xdr IC_data(init_filename, READ);
714  read_serialized_data(IC_data, false);
715  }
716  else
717  {
718  // Otherwise zero out the solution as a default
719  this->solution->zero();
720  }
721  this->solution->close();
722  this->update();
723 }
724 
726 {
727  LOG_SCOPE("add_IC_to_RB_space()", "TransientRBConstruction");
728 
729  libmesh_error_msg_if(get_rb_evaluation().get_n_basis_functions() > 0,
730  "Error: Should not call TransientRBConstruction::add_IC_to_RB_space() "
731  "on a system that already contains basis functions.");
732 
733  libmesh_error_msg_if(!nonzero_initialization,
734  "Error: Should not call TransientRBConstruction::add_IC_to_RB_space() "
735  "when nonzero_initialization==false.");
736 
738 
739  // load the new basis function into the basis_functions vector.
741  NumericVector<Number> & current_bf = get_rb_evaluation().get_basis_function(get_rb_evaluation().get_n_basis_functions()-1);
742  current_bf.init (this->n_dofs(), this->n_local_dofs(), false, PARALLEL);
743  current_bf = *solution;
744 
745  // We can just set the norm to 1.
747 
748  Real current_bf_norm = libmesh_real(std::sqrt( current_bf.dot(*inner_product_storage_vector) ));
749  current_bf.scale(1./current_bf_norm);
750 
751  unsigned int saved_delta_N = get_delta_N();
752  set_delta_N(1);
753  update_system();
754  set_delta_N(saved_delta_N);
755 }
756 
758 {
759  // Need SLEPc to get the POD eigenvalues
760  LOG_SCOPE("enrich_RB_space()", "TransientRBConstruction");
761 
762  // With the "method of snapshots", the size of
763  // the eigenproblem is determined by the number
764  // of time-steps (rather than the number of spatial dofs).
765  unsigned int n_snapshots = temporal_data.size();
766  DenseMatrix<Number> correlation_matrix(n_snapshots,n_snapshots);
767  for (unsigned int i=0; i<n_snapshots; i++)
768  {
771 
772  for (unsigned int j=0; j<=i; j++)
773  {
774  // Scale the inner products by the number of time-steps to normalize the
775  // POD energy norm appropriately
776  Number inner_prod = (temporal_data[j]->dot(*inner_product_storage_vector)) /
777  (Real)(get_n_time_steps()+1);
778 
779  correlation_matrix(i,j) = inner_prod;
780  if(i != j)
781  {
782  correlation_matrix(j,i) = libmesh_conj(inner_prod);
783  }
784  }
785  }
786 
787  // The POD can be formulated in terms of either the SVD or an eigenvalue problem.
788  // Here we use the SVD of the correlation matrix to obtain the POD eigenvalues and
789  // eigenvectors.
790  DenseVector<Real> sigma( n_snapshots );
791  DenseMatrix<Number> U( n_snapshots, n_snapshots );
792  DenseMatrix<Number> VT( n_snapshots, n_snapshots );
793  correlation_matrix.svd(sigma, U, VT );
794 
795  libMesh::out << std::endl << "POD singular values:" << std::endl;
796  for (unsigned int i=0; i<=1; i++)
797  {
798  libMesh::out << "singular value " << i << " = " << sigma(i) << std::endl;
799  }
800  libMesh::out << "..." << std::endl;
801  libMesh::out << "last singular value = " << sigma(n_snapshots-1) << std::endl;
802  libMesh::out << std::endl;
803 
804  // Now load the new basis functions
805  unsigned int j = 0;
806  while (true)
807  {
808  // load the new basis function into the basis_functions vector.
810  NumericVector<Number> & current_bf =
811  get_rb_evaluation().get_basis_function(get_rb_evaluation().get_n_basis_functions()-1);
812  current_bf.init (this->n_dofs(), this->n_local_dofs(), false, PARALLEL);
813  current_bf.zero();
814 
815  // Perform the matrix multiplication of temporal data with
816  // the next POD eigenvector
817  for (unsigned int i=0; i<n_snapshots; i++)
818  {
819  current_bf.add( U.el(i,j), *temporal_data[i] );
820  }
821 
822  // We just set the norm to 1.
824 
825  Real current_bf_norm = std::abs( std::sqrt( current_bf.dot(*inner_product_storage_vector) ) );
826  current_bf.scale(1./current_bf_norm);
827 
828  // Increment j here since we use the incremented counter
829  // in the if clauses below
830  j++;
831 
832  // If positive POD_tol, we use it to determine the number of basis functions
833  // to add, and then break the loop when POD_tol is satisfied, or after Nmax
834  // basis functions have been added. Else we break the loop after delta_N
835  // (or Nmax) new basis functions.
836  if (POD_tol > 0.)
837  {
838  set_delta_N(1);
839 
840  // We need to define the updated RB system matrices before the RB solve
841  update_system();
842  Real error_bound = get_rb_evaluation().rb_solve(get_rb_evaluation().get_n_basis_functions());
843 
844  if ((error_bound <= POD_tol) || (get_rb_evaluation().get_n_basis_functions()==get_Nmax()))
845  {
846  set_delta_N(0);
847  break;
848  }
849  }
850  else
851  {
852  if (j == get_delta_N())
853  {
854  break;
855  }
856  else
857  if (get_rb_evaluation().get_n_basis_functions()==get_Nmax())
858  {
859  set_delta_N(j);
860  break;
861  }
862  }
863  }
864 }
865 
866 
868 {
869  // If delta_N is set to zero, there is nothing to update
870  if (get_delta_N() == 0)
871  return;
872 
874 
875  libMesh::out << "Updating RB initial conditions" << std::endl;
877 }
878 
880 {
881  return *L2_matrix;
882 }
883 
885 {
886  LOG_SCOPE("load_rb_solution()", "TransientRBConstruction");
887 
888  solution->zero();
889 
890  const unsigned int time_step = get_time_step();
891 
892  TransientRBEvaluation & trans_rb_eval = cast_ref<TransientRBEvaluation &>(get_rb_evaluation());
893  DenseVector<Number> RB_solution_vector_k = trans_rb_eval.RB_temporal_solution_data[time_step];
894 
895  libmesh_error_msg_if(RB_solution_vector_k.size() > get_rb_evaluation().get_n_basis_functions(),
896  "ERROR: rb_eval object contains "
898  << " basis functions. RB_solution vector contains "
899  << RB_solution_vector_k.size()
900  << " entries. RB_solution in TransientRBConstruction::load_rb_solution is too long!");
901 
902  for (unsigned int i=0; i<RB_solution_vector_k.size(); i++)
903  solution->add(RB_solution_vector_k(i), get_rb_evaluation().get_basis_function(i));
904 
905  update();
906 }
907 
909 {
910  LOG_SCOPE("update_RB_system_matrices()", "TransientRBConstruction");
911 
913 
914  TransientRBEvaluation & trans_rb_eval = cast_ref<TransientRBEvaluation &>(get_rb_evaluation());
915 
916  TransientRBThetaExpansion & trans_theta_expansion =
917  cast_ref<TransientRBThetaExpansion &>(get_rb_theta_expansion());
918  const unsigned int Q_m = trans_theta_expansion.get_n_M_terms();
919 
920  unsigned int RB_size = get_rb_evaluation().get_n_basis_functions();
921 
922  std::unique_ptr<NumericVector<Number>> temp = NumericVector<Number>::build(this->comm());
923  temp->init (this->n_dofs(), this->n_local_dofs(), false, PARALLEL);
924 
925  for (unsigned int i=(RB_size-delta_N); i<RB_size; i++)
926  {
927  for (unsigned int j=0; j<RB_size; j++)
928  {
929  // Compute reduced L2 matrix
930  temp->zero();
931  L2_matrix->vector_mult(*temp, get_rb_evaluation().get_basis_function(j));
932 
934  trans_rb_eval.RB_L2_matrix(i,j) = value;
935  if (i!=j)
936  {
937  // The L2 matrix is assumed
938  // to be symmetric
939  trans_rb_eval.RB_L2_matrix(j,i) = value;
940  }
941 
942  for (unsigned int q_m=0; q_m<Q_m; q_m++)
943  {
944  // Compute reduced M_q matrix
945  temp->zero();
946  get_M_q(q_m)->vector_mult(*temp, get_rb_evaluation().get_basis_function(j));
947 
948  value = (get_rb_evaluation().get_basis_function(i)).dot(*temp);
949  trans_rb_eval.RB_M_q_vector[q_m](i,j) = value;
950 
951  if (i!=j)
952  {
953  // Each mass matrix term is assumed
954  // to be symmetric
955  trans_rb_eval.RB_M_q_vector[q_m](j,i) = value;
956  }
957  }
958 
959  }
960  }
961 }
962 
963 
964 
965 
966 void TransientRBConstruction::update_residual_terms(bool compute_inner_products)
967 {
968  LOG_SCOPE("update_residual_terms()", "TransientRBConstruction");
969 
970  Parent::update_residual_terms(compute_inner_products);
971 
972  TransientRBEvaluation & trans_rb_eval = cast_ref<TransientRBEvaluation &>(get_rb_evaluation());
973 
974  TransientRBThetaExpansion & trans_theta_expansion =
975  cast_ref<TransientRBThetaExpansion &>(get_rb_theta_expansion());
976 
977  const unsigned int Q_m = trans_theta_expansion.get_n_M_terms();
978  const unsigned int Q_a = trans_theta_expansion.get_n_A_terms();
979  const unsigned int Q_f = trans_theta_expansion.get_n_F_terms();
980 
981  unsigned int RB_size = get_rb_evaluation().get_n_basis_functions();
982 
983  for (unsigned int q_m=0; q_m<Q_m; q_m++)
984  {
985  for (unsigned int i=(RB_size-delta_N); i<RB_size; i++)
986  {
987  // Initialize the vectors when we need them
988  if (!trans_rb_eval.M_q_representor[q_m][i])
989  {
990  trans_rb_eval.M_q_representor[q_m][i] = NumericVector<Number>::build(this->comm());
991  trans_rb_eval.M_q_representor[q_m][i]->init (this->n_dofs(), this->n_local_dofs(), false, PARALLEL);
992  }
993 
994  libmesh_assert(trans_rb_eval.M_q_representor[q_m][i]->size() == this->n_dofs() &&
995  trans_rb_eval.M_q_representor[q_m][i]->local_size() == this->n_local_dofs() );
996 
997  rhs->zero();
998  M_q_vector[q_m]->vector_mult(*rhs, get_rb_evaluation().get_basis_function(i));
999 
1000  if (!is_quiet())
1001  libMesh::out << "Starting solve i="
1002  << i << " in TransientRBConstruction::update_residual_terms() at "
1003  << Utility::get_timestamp() << std::endl;
1004 
1006 
1007  if (assert_convergence)
1009 
1010  if (!is_quiet())
1011  {
1012  libMesh::out << "Finished solve i="
1013  << i << " in TransientRBConstruction::update_residual_terms() at "
1014  << Utility::get_timestamp() << std::endl;
1015 
1017  << " iterations, final residual "
1018  << this->final_linear_residual() << std::endl;
1019  }
1020 
1021  *trans_rb_eval.M_q_representor[q_m][i] = *solution;
1022  }
1023  }
1024 
1025  // Now compute and store the inner products if requested
1026  if (compute_inner_products)
1027  {
1028  for (unsigned int q_f=0; q_f<Q_f; q_f++)
1029  {
1031 
1032  for (unsigned int i=(RB_size-delta_N); i<RB_size; i++)
1033  {
1034  for (unsigned int q_m=0; q_m<Q_m; q_m++)
1035  {
1036  trans_rb_eval.Fq_Mq_representor_innerprods[q_f][q_m][i] =
1037  trans_rb_eval.M_q_representor[q_m][i]->dot(*inner_product_storage_vector);
1038  } // end for q_m
1039  } // end for i
1040  } // end for q_f
1041 
1042  unsigned int q=0;
1043  for (unsigned int q_m1=0; q_m1<Q_m; q_m1++)
1044  {
1045  for (unsigned int q_m2=q_m1; q_m2<Q_m; q_m2++)
1046  {
1047  for (unsigned int i=(RB_size-delta_N); i<RB_size; i++)
1048  {
1049  for (unsigned int j=0; j<RB_size; j++)
1050  {
1052 
1053  trans_rb_eval.Mq_Mq_representor_innerprods[q][i][j] =
1054  trans_rb_eval.M_q_representor[q_m1][i]->dot(*inner_product_storage_vector);
1055 
1056  if (i != j)
1057  {
1059  *trans_rb_eval.M_q_representor[q_m2][i]);
1060 
1061  trans_rb_eval.Mq_Mq_representor_innerprods[q][j][i] =
1062  trans_rb_eval.M_q_representor[q_m1][j]->dot(*inner_product_storage_vector);
1063  }
1064  } // end for j
1065  } // end for i
1066  q++;
1067  } // end for q_m2
1068  } // end for q_m1
1069 
1070 
1071  for (unsigned int i=(RB_size-delta_N); i<RB_size; i++)
1072  {
1073  for (unsigned int j=0; j<RB_size; j++)
1074  {
1075  for (unsigned int q_a=0; q_a<Q_a; q_a++)
1076  {
1077  for (unsigned int q_m=0; q_m<Q_m; q_m++)
1078  {
1080  *trans_rb_eval.M_q_representor[q_m][j]);
1081 
1082  trans_rb_eval.Aq_Mq_representor_innerprods[q_a][q_m][i][j] =
1083  trans_rb_eval.Aq_representor[q_a][i]->dot(*inner_product_storage_vector);
1084 
1085  if (i != j)
1086  {
1088  *trans_rb_eval.M_q_representor[q_m][i]);
1089 
1090  trans_rb_eval.Aq_Mq_representor_innerprods[q_a][q_m][j][i] =
1091  trans_rb_eval.Aq_representor[q_a][j]->dot(*inner_product_storage_vector);
1092  }
1093  } // end for q_m
1094  } // end for q_a
1095  } // end for j
1096  } // end for i
1097  } // end if (compute_inner_products)
1098 }
1099 
1100 
1102 {
1103  LOG_SCOPE("update_RB_initial_condition_all_N()", "TransientRBConstruction");
1104 
1105  TransientRBEvaluation & trans_rb_eval = cast_ref<TransientRBEvaluation &>(get_rb_evaluation());
1106 
1107  // Load the initial condition into the solution vector
1108  initialize_truth();
1109 
1110  std::unique_ptr<NumericVector<Number>> temp1 = NumericVector<Number>::build(this->comm());
1111  temp1->init (this->n_dofs(), this->n_local_dofs(), false, PARALLEL);
1112 
1113  std::unique_ptr<NumericVector<Number>> temp2 = NumericVector<Number>::build(this->comm());
1114  temp2->init (this->n_dofs(), this->n_local_dofs(), false, PARALLEL);
1115 
1116 
1117  unsigned int RB_size = get_rb_evaluation().get_n_basis_functions();
1118 
1119  // First compute the right-hand side vector for the L2 projection
1120  L2_matrix->vector_mult(*temp1, *solution);
1121 
1122  for (unsigned int i=(RB_size-delta_N); i<RB_size; i++)
1123  {
1124  RB_ic_proj_rhs_all_N(i) = temp1->dot(get_rb_evaluation().get_basis_function(i));
1125  }
1126 
1127 
1128  // Now compute the projection for each N
1129  DenseMatrix<Number> RB_L2_matrix_N;
1130  DenseVector<Number> RB_rhs_N;
1131  for (unsigned int N=(RB_size-delta_N); N<RB_size; N++)
1132  {
1133  // We have to index here by N+1 since the loop index is zero-based.
1134  trans_rb_eval.RB_L2_matrix.get_principal_submatrix(N+1, RB_L2_matrix_N);
1135 
1137 
1138  DenseVector<Number> RB_ic_N(N+1);
1139 
1140  // Now solve the linear system
1141  RB_L2_matrix_N.lu_solve(RB_rhs_N, RB_ic_N);
1142 
1143  // Load RB_ic_N into RB_initial_condition_all_N
1144  trans_rb_eval.RB_initial_condition_all_N[N] = RB_ic_N;
1145 
1146  // Compute the L2 error for the RB initial condition
1147  // This part is dependent on the truth space.
1148 
1149  // load the RB solution into temp1
1150  temp1->zero();
1151  for (unsigned int i=0; i<N+1; i++)
1152  {
1153  temp1->add(RB_ic_N(i), get_rb_evaluation().get_basis_function(i));
1154  }
1155 
1156  // subtract truth initial condition from RB_ic_N
1157  temp1->add(-1., *solution);
1158 
1159  // Compute L2 norm error, i.e. sqrt(M(solution,solution))
1160  temp2->zero();
1161  L2_matrix->vector_mult(*temp2, *temp1);
1162 
1163  trans_rb_eval.initial_L2_error_all_N[N] = libmesh_real(std::sqrt(temp2->dot(*temp1)));
1164  }
1165 }
1166 
1167 //Real TransientRBConstruction::uncached_compute_residual_dual_norm(const unsigned int N)
1168 //{
1169 // LOG_SCOPE("uncached_compute_residual_dual_norm()", "TransientRBConstruction");
1170 //
1171 // // This is the "slow" way of computing the residual, but it is useful
1172 // // for validating the "fast" way.
1173 // // Note that this only works in serial since otherwise each processor will
1174 // // have a different parameter value during the Greedy training.
1175 //
1176 // // Assemble the right-hand side to find the Reisz representor
1177 // // of the residual in the X norm
1178 // std::unique_ptr<NumericVector<Number>> RB_sol = NumericVector<Number>::build();
1179 // RB_sol->init (this->n_dofs(), this->n_local_dofs(), false, PARALLEL);
1180 // RB_sol->zero();
1181 //
1182 // std::unique_ptr<NumericVector<Number>> ghosted_temp = NumericVector<Number>::build();
1183 // ghosted_temp->init (this->n_dofs(), this->n_local_dofs(),
1184 // this->get_dof_map().get_send_list(), false,
1185 // GHOSTED);
1186 //
1187 // std::unique_ptr<NumericVector<Number>> parallel_temp = NumericVector<Number>::build();
1188 // parallel_temp->init (this->n_dofs(), this->n_local_dofs(), false, PARALLEL);
1189 //
1190 // // Store current_local_solution, since we don't want to corrupt it
1191 // *ghosted_temp = *current_local_solution;
1192 //
1193 // for (unsigned int i=0; i<N; i++)
1194 // {
1195 // RB_sol->add(RB_solution(i), rb_eval->get_basis_function(i));
1196 // parallel_temp->add(old_RB_solution(i), rb_eval->get_basis_function(i));
1197 // }
1198 //
1199 // // Load parallel_temp into current_local_solution in order to do assembly
1200 // const std::vector<unsigned int> & send_list = this->get_dof_map().get_send_list();
1201 // parallel_temp->localize (*current_local_solution, send_list);
1202 //
1203 // // Load the system_matrix
1204 // this->truth_assembly();
1205 //
1206 // // Restore current_local_solution
1207 // *current_local_solution = *ghosted_temp;
1208 //
1209 // matrix->vector_mult(*parallel_temp, *RB_sol);
1210 // rhs->add(-1., *parallel_temp);
1211 // rhs->close();
1212 //
1213 // zero_dirichlet_dofs_on_rhs();
1214 //
1215 // // Then solve the system to get the Reisz representor
1216 // matrix->zero();
1217 // {
1218 // matrix->add(1., *inner_product_matrix);
1219 // if (constrained_problem)
1220 // matrix->add(1., *constraint_matrix);
1221 // }
1222 //
1223 //
1224 // solution->zero();
1225 // solve();
1226 // // Make sure we didn't max out the number of iterations
1227 // if ((this->n_linear_iterations() >=
1228 // this->get_equation_systems().parameters.get<unsigned int>("linear solver maximum iterations")) &&
1229 // (this->final_linear_residual() >
1230 // this->get_equation_systems().parameters.get<Real>("linear solver tolerance")))
1231 // {
1232 // libmesh_error_msg("Warning: Linear solver may not have converged! Final linear residual = "
1233 // << this->final_linear_residual() << ", number of iterations = "
1234 // << this->n_linear_iterations());
1235 // }
1236 //
1237 // get_non_dirichlet_inner_product_matrix_if_avail()->vector_mult(*inner_product_storage_vector, *solution);
1238 //
1239 // Real slow_residual_norm_sq = solution->dot(*inner_product_storage_vector);
1240 //
1241 // return libmesh_real(std::sqrt( slow_residual_norm_sq ));
1242 //}
1243 
1244 void TransientRBConstruction::write_riesz_representors_to_files(const std::string & riesz_representors_dir,
1245  const bool write_binary_residual_representors)
1246 {
1247  LOG_SCOPE("write_riesz_representors_to_files()", "TransientRBConstruction");
1248 
1249  // Write out the M_q_representors. These are useful to have when restarting,
1250  // so you don't have to recompute them all over again. There should be
1251  // this->rb_eval->get_n_basis_functions() of these.
1252  libMesh::out << "Writing out the M_q_representors..." << std::endl;
1253 
1254  std::ostringstream file_name;
1255  const std::string riesz_representor_suffix = (write_binary_residual_representors ? ".xdr" : ".dat");
1256 
1257  TransientRBEvaluation & trans_rb_eval = cast_ref<TransientRBEvaluation &>(get_rb_evaluation());
1258 
1259  const unsigned int istop = trans_rb_eval.get_n_basis_functions();
1260  const unsigned int istart = istop-get_delta_N();
1261 
1262  for (std::size_t q=0; q<trans_rb_eval.M_q_representor.size(); ++q)
1263  for (unsigned int i=istart; i<istop; ++i)
1264  {
1265  libMesh::out << "Writing out M_q_representor[" << q << "][" << i << "]..." << std::endl;
1266  libmesh_assert(trans_rb_eval.M_q_representor[q][i]);
1267 
1268  file_name.str(""); // reset filename
1269  file_name << riesz_representors_dir << "/M_q_representor" << i << riesz_representor_suffix;
1270 
1271  {
1272  // No need to copy!
1273  //*solution = *(M_q_representor[q][i]);
1274  trans_rb_eval.M_q_representor[q][i]->swap(*solution);
1275 
1276  Xdr mr_data(file_name.str(),
1277  write_binary_residual_representors ? ENCODE : WRITE);
1278 
1279  write_serialized_data(mr_data, false);
1280 
1281  // Synchronize before moving on
1282  this->comm().barrier();
1283 
1284  // Swap back.
1285  trans_rb_eval.M_q_representor[q][i]->swap(*solution);
1286 
1287  // TODO: bzip the resulting file? See $LIBMESH_DIR/src/mesh/unstructured_mesh.C
1288  // for the system call, be sure to do it only on one processor, etc.
1289  }
1290  }
1291 }
1292 
1293 void TransientRBConstruction::read_riesz_representors_from_files(const std::string & riesz_representors_dir,
1294  const bool read_binary_residual_representors)
1295 {
1296  LOG_SCOPE("read_riesz_representors_from_files()", "TransientRBConstruction");
1297 
1298  const std::string riesz_representor_suffix =
1299  (read_binary_residual_representors ? ".xdr" : ".dat");
1300 
1301  std::ostringstream file_name;
1302  struct stat stat_info;
1303 
1304  TransientRBEvaluation & trans_rb_eval = cast_ref<TransientRBEvaluation &>(get_rb_evaluation());
1305 
1306  libMesh::out << "Reading in the M_q_representors..." << std::endl;
1307 
1308  // Read in the Aq representors. The class makes room for [Q_m][Nmax] of these. We are going to
1309  // read in [Q_m][this->rb_eval->get_n_basis_functions()]. FIXME:
1310  // should we be worried about leaks in the locations where we're about to fill entries?
1311  for (std::size_t i=0; i<trans_rb_eval.M_q_representor.size(); ++i)
1312  for (std::size_t j=0; j<trans_rb_eval.M_q_representor[i].size(); ++j)
1313  libmesh_error_msg_if(trans_rb_eval.M_q_representor[i][j] != nullptr,
1314  "Error, must delete existing M_q_representor before reading in from file.");
1315 
1316  // Now ready to read them in from file!
1317  for (std::size_t i=0; i<trans_rb_eval.M_q_representor.size(); ++i)
1318  for (std::size_t j=0; j<trans_rb_eval.get_n_basis_functions(); ++j)
1319  {
1320  file_name.str(""); // reset filename
1321  file_name << riesz_representors_dir
1322  << "/M_q_representor" << i << "_" << j << riesz_representor_suffix;
1323 
1324  // On processor zero check to be sure the file exists
1325  if (this->processor_id() == 0)
1326  {
1327  int stat_result = stat(file_name.str().c_str(), &stat_info);
1328 
1329  libmesh_error_msg_if(stat_result != 0, "File does not exist: " << file_name.str());
1330  }
1331 
1332  Xdr aqr_data(file_name.str(),
1333  read_binary_residual_representors ? DECODE : READ);
1334 
1335  read_serialized_data(aqr_data, false);
1336 
1337  trans_rb_eval.M_q_representor[i][j] = NumericVector<Number>::build(this->comm());
1338  trans_rb_eval.M_q_representor[i][j]->init (n_dofs(), n_local_dofs(),
1339  false, PARALLEL);
1340 
1341  // No need to copy, just swap
1342  //*M_q_representor[i][j] = *solution;
1343  trans_rb_eval.M_q_representor[i][j]->swap(*solution);
1344  }
1345 }
1346 
1347 } // namespace libMesh
T libmesh_real(T a)
std::vector< std::vector< std::vector< Number > > > Mq_Mq_representor_innerprods
std::unique_ptr< SparseMatrix< Number > > L2_matrix
The L2 matrix.
virtual void allocate_data_structures() override
Helper function that actually allocates all the data structures required by this class.
std::vector< std::vector< std::unique_ptr< NumericVector< Number > > > > Aq_representor
Vector storing the residual representors associated with the left-hand side.
virtual void initialize_rb_construction(bool skip_matrix_assembly=false, bool skip_vector_assembly=false)
Allocate all the data structures necessary for the construction stage of the RB method.
virtual void load_rb_solution() override
Load the RB solution from the current time-level into the libMesh solution vector.
void write_serialized_data(Xdr &io, const bool write_additional_data=true) const
Writes additional data, namely vectors, for this System.
Definition: system_io.C:1668
This is the EquationSystems class.
int max_truth_solves
Maximum number of truth solves in the POD-Greedy.
virtual Number eval_output_theta(unsigned int output_index, unsigned int q_l, const RBParameters &mu) const
Evaluate theta_q_l at the current parameter.
virtual Number eval_A_theta(unsigned int q, const RBParameters &mu) const
Evaluate theta_q_a at the current parameter.
Real get_POD_tol() const
Get/set POD_tol.
void set_max_truth_solves(int max_truth_solves_in)
virtual void zero() override final
Set every element in the vector to 0.
Definition: dense_vector.h:420
std::vector< std::unique_ptr< NumericVector< Number > > > Fq_representor
Vector storing the residual representors associated with the right-hand side.
T libmesh_conj(T a)
void assemble_mass_matrix(SparseMatrix< Number > *input_matrix)
Assemble the mass matrix at the current parameter and store it in input_matrix.
unsigned int get_n_F_terms() const
Get Q_f, the number of terms in the affine expansion for the right-hand side.
bool assert_convergence
A boolean flag to indicate whether to check for proper convergence after each solve.
virtual void assemble_all_affine_operators() override
Assemble and store all the affine operators.
virtual Real train_reduced_basis(const bool resize_rb_eval_data=true)
Train the reduced basis.
virtual SparseMatrix< Number > & get_matrix_for_output_dual_solves() override
Override to return the L2 product matrix for output dual norm solves for transient state problems...
virtual void get_all_matrices(std::map< std::string, SparseMatrix< Number > *> &all_matrices)
Get a map that stores pointers to all of the matrices.
void process_temporal_parameters_file(const std::string &parameters_filename)
Read in and initialize parameters from parameters_filename.
SparseMatrix< Number > * get_M_q(unsigned int q)
Get a pointer to M_q.
virtual Real train_reduced_basis(const bool resize_rb_eval_data=true) override
Train the reduced basis.
This extends RBAssemblyExpansion to provide an assembly expansion for the case of time-dependent PDEs...
void vector_mult(NumericVector< T > &dest, const NumericVector< T > &arg) const
Multiplies the matrix by the NumericVector arg and stores the result in NumericVector dest...
virtual void truth_assembly() override
Assemble the truth system in the transient linear case.
std::vector< DenseMatrix< Number > > RB_M_q_vector
Dense matrices for the RB mass matrices.
std::string get_timestamp()
Definition: timestamp.C:37
The ExodusII_IO class implements reading meshes in the ExodusII file format from Sandia National Labs...
Definition: exodusII_io.h:52
std::vector< std::unique_ptr< SparseMatrix< Number > > > non_dirichlet_M_q_vector
We sometimes also need a second set of M_q matrices that do not have the Dirichlet boundary condition...
DenseMatrix< Number > RB_inner_product_matrix
The inner product matrix.
SparseMatrix< Number > * get_Aq(unsigned int q)
Get a pointer to Aq.
bool compute_RB_inner_product
Boolean flag to indicate whether we compute the RB_inner_product_matrix.
void resize(const unsigned int n)
Resize the vector.
Definition: dense_vector.h:396
std::vector< std::unique_ptr< NumericVector< Number > > > basis_functions
The libMesh vectors storing the finite element coefficients of the RB basis functions.
virtual void initialize_truth()
This function imposes a truth initial condition, defaults to zero initial condition if the flag nonze...
virtual void get_all_matrices(std::map< std::string, SparseMatrix< Number > *> &all_matrices) override
Get a map that stores pointers to all of the matrices.
const EquationSystems & get_equation_systems() const
Definition: system.h:721
void attach_matrix(SparseMatrix< Number > &matrix)
Additional matrices may be attached to this DofMap.
Definition: dof_map.C:274
void barrier() const
virtual Real truth_solve(int write_interval) override
Perform a truth solve at the current parameter.
NumericVector< Number > * rhs
The system matrix.
unsigned int get_n_A_terms() const
Get Q_a, the number of terms in the affine expansion for the bilinear form.
const Parallel::Communicator & comm() const
bool is_quiet() const
Is the system in quiet mode?
Real POD_tol
If positive, this tolerance determines the number of POD modes we add to the space on a call to enric...
This class is part of the rbOOmit framework.
std::vector< std::vector< Number > > truth_outputs_all_k
The truth outputs for all time-levels from the most recent truth_solve.
virtual bool greedy_termination_test(Real abs_greedy_error, Real initial_greedy_error, int count)
Function that indicates when to terminate the Greedy basis training.
This class stores the set of RBTheta functor objects that define the "parameter-dependent expansion" ...
void update_RB_initial_condition_all_N()
Compute the L2 projection of the initial condition onto the RB space for 1 <= N <= RB_size and store ...
virtual LinearSolver< Number > * get_linear_solver() const override
std::unique_ptr< SparseMatrix< Number > > inner_product_matrix
The inner product matrix.
const std::string & get_RB_training_type() const
The libMesh namespace provides an interface to certain functionality in the library.
NumericVector< Number > * get_Fq(unsigned int q)
Get a pointer to Fq.
virtual T dot(const NumericVector< T > &v) const =0
dof_id_type n_local_dofs() const
Definition: system.C:158
virtual Number eval_M_theta(unsigned int q, const RBParameters &mu) const
Evaluate theta at the current parameter.
std::string init_filename
The filename of the file containing the initial condition projected onto the truth mesh...
Real get_delta_t() const
Get/set delta_t, the time-step size.
unsigned int get_n_outputs() const
Get n_outputs, the number output functionals.
const MeshBase & get_mesh() const
Definition: system.h:2358
virtual void init(const numeric_index_type n, const numeric_index_type n_local, const bool fast=false, const ParallelType ptype=AUTOMATIC)=0
Change the dimension of the vector to n.
void get_principal_subvector(unsigned int sub_n, DenseVector< T > &dest) const
Puts the principal subvector of size sub_n (i.e.
Definition: dense_vector.h:713
static std::unique_ptr< SparseMatrix< T > > build(const Parallel::Communicator &comm, const SolverPackage solver_package=libMesh::default_solver_package(), const MatrixBuildType matrix_build_type=MatrixBuildType::AUTOMATIC)
Builds a SparseMatrix<T> using the linear solver package specified by solver_package.
virtual void print_info() const
Print out info that describes the current setup of this RBConstruction.
NumericVector< Number > * old_local_solution
All the values I need to compute my contribution to the simulation at hand.
Real get_euler_theta() const
Get/set euler_theta, parameter that determines the temporal discretization.
dof_id_type n_dofs() const
Definition: system.C:121
virtual void zero()=0
Set all entries to zero.
std::unique_ptr< NumericVector< Number > > inner_product_storage_vector
We keep an extra temporary vector that is useful for performing inner products (avoids unnecessary me...
virtual void add(const numeric_index_type i, const numeric_index_type j, const T value)=0
Add value to the element (i,j).
virtual void update_RB_system_matrices() override
Compute the reduced basis matrices for the current basis.
virtual void read_riesz_representors_from_files(const std::string &riesz_representors_dir, const bool write_binary_residual_representors) override
Write out all the Riesz representor data to files.
Generic sparse matrix.
Definition: vector_fe_ex5.C:46
This class handles the numbering of degrees of freedom on a mesh.
Definition: dof_map.h:179
virtual void scale(const T factor)=0
Scale each element of the vector by the given factor.
std::vector< std::vector< std::unique_ptr< NumericVector< Number > > > > M_q_representor
Vector storing the mass matrix representors.
virtual void solve_for_matrix_and_rhs(LinearSolver< Number > &input_solver, SparseMatrix< Number > &input_matrix, NumericVector< Number > &input_rhs)
Assembles & solves the linear system A*x=b for the specified matrix input_matrix and right-hand side ...
void assemble_L2_matrix(SparseMatrix< Number > *input_matrix, bool apply_dirichlet_bc=true)
Assemble the L2 matrix.
void pull_temporal_discretization_data(RBTemporalDiscretization &other)
Pull the temporal discretization data from other.
RBThetaExpansion & get_rb_theta_expansion()
Get a reference to the RBThetaExpansion object that that belongs to rb_eval.
virtual void write_riesz_representors_to_files(const std::string &riesz_representors_dir, const bool write_binary_residual_representors) override
Write out all the Riesz representor data to files.
std::unique_ptr< SparseMatrix< Number > > non_dirichlet_L2_matrix
The L2 matrix without Dirichlet conditions enforced.
virtual void zero()=0
Set all entries to 0.
std::vector< Real > initial_L2_error_all_N
Vector storing initial L2 error for all 1 <= N <= RB_size.
virtual T el(const unsigned int i, const unsigned int j) const override final
Definition: dense_matrix.h:126
unsigned int n_linear_iterations() const
void svd(DenseVector< Real > &sigma)
Compute the singular value decomposition of the matrix.
void set_L2_assembly(ElemAssembly &L2_assembly_in)
Set the L2 object.
unsigned int get_Nmax() const
Get/set Nmax, the maximum number of RB functions we are willing to compute.
RBAssemblyExpansion & get_rb_assembly_expansion()
virtual void enrich_RB_space() override
Add a new basis functions to the RB space.
virtual void write_equation_systems(const std::string &fname, const EquationSystems &es, const std::set< std::string > *system_names=nullptr) override
Writes out the solution for no specific time or timestep.
Definition: exodusII_io.C:2033
int get_max_truth_solves() const
Get/set max_truth_solves, the maximum number of RB truth solves we are willing to compute in the tran...
virtual unsigned int get_n_M_terms() const
Get Q_m, the number of terms in the affine expansion for the mass operator.
virtual void update_RB_system_matrices()
Compute the reduced basis matrices for the current basis.
NumericVector< Number > & get_basis_function(unsigned int i)
Get a reference to the i^th basis function.
virtual void update_residual_terms(bool compute_inner_products=true)
Compute the terms that are combined ‘online’ to determine the dual norm of the residual.
Number set_error_temporal_data()
Set column k (i.e.
virtual void clear() override
Clear all the data structures associated with the system.
std::unique_ptr< NumericVector< Number > > solution
Data structure to hold solution values.
Definition: system.h:1593
virtual void update_system()
Update the system after enriching the RB space; this calls a series of functions to update the system...
libmesh_assert(ctx)
virtual Number eval_F_theta(unsigned int q, const RBParameters &mu) const
Evaluate theta_q_f at the current parameter.
std::vector< std::vector< std::vector< Number > > > Fq_Mq_representor_innerprods
Vectors storing the residual representor inner products to be used in computing the residuals online...
bool nonzero_initialization
Boolean flag to indicate whether we are using a non-zero initialization.
unsigned int get_delta_N() const
Get delta_N, the number of basis functions we add to the RB space per iteration of the greedy algorit...
const RBParameters & get_parameters() const
Get the current parameters.
void get_principal_submatrix(unsigned int sub_m, unsigned int sub_n, DenseMatrix< T > &dest) const
Put the sub_m x sub_n principal submatrix into dest.
ElemAssembly * L2_assembly
Function pointer for assembling the L2 matrix.
unsigned int get_time_step() const
Get/set the current time-step.
void add_scaled_matrix_and_vector(Number scalar, ElemAssembly *elem_assembly, SparseMatrix< Number > *input_matrix, NumericVector< Number > *input_vector, bool symmetrize=false, bool apply_dof_constraints=true)
This function loops over the mesh and applies the specified interior and/or boundary assembly routine...
This class is part of the rbOOmit framework.
Definition: rb_parameters.h:52
bool is_rb_eval_initialized() const
unsigned int delta_N
The number of basis functions that we add at each greedy step.
virtual void update_residual_terms(bool compute_inner_products) override
Compute the terms that are combined ‘online’ to determine the dual norm of the residual.
virtual bool greedy_termination_test(Real abs_greedy_error, Real initial_greedy_error, int count) override
Function that indicates when to terminate the Greedy basis training.
virtual void close()=0
Calls the NumericVector&#39;s internal assembly routines, ensuring that the values are consistent across ...
This class implements a C++ interface to the XDR (eXternal Data Representation) format.
Definition: xdr_cxx.h:67
std::vector< DenseVector< Number > > RB_initial_condition_all_N
The RB initial conditions (i.e.
virtual Real rb_solve(unsigned int N)
Perform online solve with the N RB basis functions, for the set of parameters in current_params, where 0 <= N <= RB_size.
TransientRBConstruction(EquationSystems &es, const std::string &name, const unsigned int number)
Constructor.
void set_POD_tol(const Real POD_tol_in)
CompareTypes< T, T2 >::supertype dot(const DenseVector< T2 > &vec) const
Definition: dense_vector.h:492
virtual void update()
Update the local values to reflect the solution on neighboring processors.
Definition: system.C:510
virtual void close()=0
Calls the SparseMatrix&#39;s internal assembly routines, ensuring that the values are consistent across p...
void lu_solve(const DenseVector< T > &b, DenseVector< T > &x)
Solve the system Ax=b given the input vector b.
bool store_non_dirichlet_operators
Boolean flag to indicate whether we store a second copy of each affine operator and vector which does...
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
virtual void assemble_affine_expansion(bool skip_matrix_assembly, bool skip_vector_assembly) override
Override assemble_affine_expansion to also initialize RB_ic_proj_rhs_all_N, if necessary.
unsigned int get_n_output_terms(unsigned int output_index) const
Get the number of affine terms associated with the specified output.
void check_convergence(LinearSolver< Number > &input_solver)
Check if the linear solver reports convergence.
std::unique_ptr< LinearSolver< Number > > inner_product_solver
We store an extra linear solver object which we can optionally use for solving all systems in which t...
std::vector< std::unique_ptr< NumericVector< Number > > > temporal_data
Dense matrix to store the data that we use for the temporal POD.
virtual void process_parameters_file(const std::string &parameters_filename) override
Read in the parameters from file and set up the system accordingly.
virtual void clear() override
Clear all the data structures associated with the system.
OStreamProxy out
SparseMatrix< Number > * matrix
The system matrix.
virtual unsigned int get_n_basis_functions() const
Get the current number of basis functions.
std::vector< DenseVector< Number > > RB_temporal_solution_data
Array storing the solution data at each time level from the most recent solve.
ElemAssembly provides a per-element (interior and boundary) assembly functionality.
Definition: elem_assembly.h:38
SparseMatrix< Number > * get_non_dirichlet_inner_product_matrix_if_avail()
Get the non-Dirichlet inner-product matrix if it&#39;s available, otherwise get the inner-product matrix ...
static const bool value
Definition: xdr_io.C:54
void assemble_Mq_matrix(unsigned int q, SparseMatrix< Number > *input_matrix, bool apply_dirichlet_bc=true)
Assemble the q^th affine term of the mass matrix and store it in input_matrix.
static std::unique_ptr< NumericVector< T > > build(const Parallel::Communicator &comm, SolverPackage solver_package=libMesh::default_solver_package(), ParallelType parallel_type=AUTOMATIC)
Builds a NumericVector on the processors in communicator comm using the linear solver package specifi...
void add_scaled_mass_matrix(Number scalar, SparseMatrix< Number > *input_matrix)
Add the scaled mass matrix (assembled for the current parameter) to input_matrix. ...
std::unique_ptr< NumericVector< Number > > current_local_solution
All the values I need to compute my contribution to the simulation at hand.
Definition: system.h:1605
unsigned int get_n_time_steps() const
Get/set the total number of time-steps.
virtual void process_parameters_file(const std::string &parameters_filename)
Read in from the file specified by parameters_filename and set the this system&#39;s member variables acc...
const NumericVector< Number > & get_error_temporal_data()
Get the column of temporal_data corresponding to the current time level.
NumericVector< Number > * get_output_vector(unsigned int n, unsigned int q_l)
Get a pointer to the n^th output.
RBEvaluation & get_rb_evaluation()
Get a reference to the RBEvaluation object.
virtual void assemble_misc_matrices()
Assemble and store all the inner-product matrix, the constraint matrix (for constrained problems) and...
std::vector< std::vector< std::vector< std::vector< Number > > > > Aq_Mq_representor_innerprods
bool compute_truth_projection_error
Boolean flag that indicates whether we will compute the projection error for the truth solution into ...
void mass_matrix_scaled_matvec(Number scalar, NumericVector< Number > &dest, NumericVector< Number > &arg)
Perform a matrix-vector multiplication with the current mass matrix and store the result in dest...
void set_delta_N(const unsigned int new_delta_N)
Set delta_N, the number of basis functions we add to the RB space from each POD.
void add_IC_to_RB_space()
Initialize RB space by adding the truth initial condition as the first RB basis function.
virtual void add(const numeric_index_type i, const T value)=0
Adds value to the vector entry specified by i.
processor_id_type processor_id() const
SparseMatrix< Number > * get_non_dirichlet_M_q(unsigned int q)
Get a pointer to non_dirichlet_M_q.
std::vector< std::unique_ptr< SparseMatrix< Number > > > M_q_vector
Vector storing the Q_m matrices from the mass operator.
bool exit_on_repeated_greedy_parameters
Boolean flag to indicate whether we exit the greedy if we select the same parameters twice in a row...
std::unique_ptr< LinearSolver< Number > > linear_solver
This class handles all the details of interfacing with various linear algebra packages like PETSc or ...
const DofMap & get_dof_map() const
Definition: system.h:2374
void read_serialized_data(Xdr &io, const bool read_additional_data=true)
Reads additional data, namely vectors, for this System.
Definition: system_io.C:680
virtual void allocate_data_structures()
Helper function that actually allocates all the data structures required by this class.
Real get_control(const unsigned int k) const
Get/set the RHS control.
DenseMatrix< Number > RB_L2_matrix
Dense RB L2 matrix.
virtual void assemble_misc_matrices() override
Override to assemble the L2 matrix as well.
virtual void update_system() override
Update the system after enriching the RB space.
virtual void print_info() const override
Print out info that describes the current setup of this RBConstruction.
unsigned int Nmax
Maximum number of reduced basis functions we are willing to use.
virtual void assemble_affine_expansion(bool skip_matrix_assembly, bool skip_vector_assembly)
Assemble the matrices and vectors for this system.
DenseVector< Number > RB_ic_proj_rhs_all_N
The vector that stores the right-hand side for the initial condition projections. ...
virtual void assemble_all_affine_operators()
Assemble and store all Q_a affine operators as well as the inner-product matrix.
virtual void initialize_rb_construction(bool skip_matrix_assembly=false, bool skip_vector_assembly=false) override
Allocate all the data structures necessary for the construction stage of the RB method.