libMesh
Loading...
Searching...
No Matches
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
58namespace 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{
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
116void 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 {
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
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
318void 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
345void TransientRBConstruction::assemble_L2_matrix(SparseMatrix<Number> * input_matrix, bool apply_dirichlet_bc)
346{
347 input_matrix->zero();
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
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
465void 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 {
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
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
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
614bool
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);
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
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
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 "
897 << get_rb_evaluation().get_n_basis_functions()
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
966void 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
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
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
1244void 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
1293void 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
Defines a dense matrix for use in Finite Element-type computations.
void svd(DenseVector< Real > &sigma)
Compute the singular value decomposition of the matrix.
void lu_solve(const DenseVector< T > &b, DenseVector< T > &x)
Solve the system Ax=b given the input vector b.
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.
virtual T el(const unsigned int i, const unsigned int j) const override final
virtual void zero() override final
Sets all elements of the matrix to 0 and resets any decomposition flag which may have been previously...
Defines a dense vector for use in Finite Element-type computations.
void resize(const unsigned int n)
Resize the vector.
virtual void zero() override final
Set every element in the vector to 0.
void get_principal_subvector(unsigned int sub_n, DenseVector< T > &dest) const
Puts the principal subvector of size sub_n (i.e.
CompareTypes< T, T2 >::supertype dot(const DenseVector< T2 > &vec) const
virtual unsigned int size() const override final
This class handles the numbering of degrees of freedom on a mesh.
Definition dof_map.h:181
void attach_matrix(SparseMatrix< Number > &matrix)
Additional matrices may be attached to this DofMap.
Definition dof_map.C:240
ElemAssembly provides a per-element (interior and boundary) assembly functionality.
This is the EquationSystems class.
The ExodusII_IO class implements reading meshes in the ExodusII file format from Sandia National Labs...
Definition exodusII_io.h:53
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.
NumericVector< Number > * rhs
The system matrix.
SparseMatrix< Number > * matrix
The system matrix.
std::unique_ptr< LinearSolver< Number > > linear_solver
This class handles all the details of interfacing with various linear algebra packages like PETSc or ...
virtual LinearSolver< Number > * get_linear_solver() const override
Provides a uniform interface to vector storage schemes for different linear algebra libraries.
virtual void close()=0
Calls the NumericVector's internal assembly routines, ensuring that the values are consistent across ...
virtual T dot(const NumericVector< T > &v) const =0
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...
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.
virtual void scale(const T factor)=0
Scale each element of the vector by the given factor.
virtual void zero()=0
Set all entries to zero.
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
const Parallel::Communicator & comm() const
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...
bool is_quiet() const
Is the system in quiet mode?
virtual void allocate_data_structures()
Helper function that actually allocates all the data structures required by this class.
RBThetaExpansion & get_rb_theta_expansion()
Get a reference to the RBThetaExpansion object that that belongs to rb_eval.
std::unique_ptr< SparseMatrix< Number > > inner_product_matrix
The inner product matrix.
virtual void update_RB_system_matrices()
Compute the reduced basis matrices for the current basis.
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...
virtual void assemble_all_affine_operators()
Assemble and store all Q_a affine operators as well as the inner-product matrix.
NumericVector< Number > * get_output_vector(unsigned int n, unsigned int q_l)
Get a pointer to the n^th output.
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.
virtual void print_info() const
Print out info that describes the current setup of this RBConstruction.
virtual void update_system()
Update the system after enriching the RB space; this calls a series of functions to update the system...
virtual void assemble_misc_matrices()
Assemble and store all the inner-product matrix, the constraint matrix (for constrained problems) and...
virtual void assemble_affine_expansion(bool skip_matrix_assembly, bool skip_vector_assembly)
Assemble the matrices and vectors for this system.
void check_convergence(LinearSolver< Number > &input_solver)
Check if the linear solver reports convergence.
bool compute_RB_inner_product
Boolean flag to indicate whether we compute the RB_inner_product_matrix.
RBEvaluation & get_rb_evaluation()
Get a reference to the RBEvaluation object.
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.
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.
SparseMatrix< Number > * get_non_dirichlet_inner_product_matrix_if_avail()
Get the non-Dirichlet inner-product matrix if it's available, otherwise get the inner-product matrix ...
NumericVector< Number > * get_Fq(unsigned int q)
Get a pointer to Fq.
virtual Real train_reduced_basis(const bool resize_rb_eval_data=true)
Train the reduced basis.
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...
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 ...
RBAssemblyExpansion & get_rb_assembly_expansion()
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...
unsigned int get_Nmax() const
Get/set Nmax, the maximum number of RB functions we are willing to compute.
const std::string & get_RB_training_type() const
std::vector< std::unique_ptr< NumericVector< Number > > > Fq_representor
Vector storing the residual representors associated with the right-hand side.
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.
unsigned int Nmax
Maximum number of reduced basis functions we are willing to use.
bool store_non_dirichlet_operators
Boolean flag to indicate whether we store a second copy of each affine operator and vector which does...
virtual void get_all_matrices(std::map< std::string, SparseMatrix< Number > * > &all_matrices)
Get a map that stores pointers to all of the matrices.
bool is_rb_eval_initialized() const
virtual void process_parameters_file(const std::string &parameters_filename)
Read in from the file specified by parameters_filename and set the this system's member variables acc...
SparseMatrix< Number > * get_Aq(unsigned int q)
Get a pointer to Aq.
unsigned int delta_N
The number of basis functions that we add at each greedy step.
bool assert_convergence
A boolean flag to indicate whether to check for proper convergence after each solve.
NumericVector< Number > & get_basis_function(unsigned int i)
Get a reference to the i^th basis function.
DenseMatrix< Number > RB_inner_product_matrix
The inner product matrix.
std::vector< std::unique_ptr< NumericVector< Number > > > basis_functions
The libMesh vectors storing the finite element coefficients of the RB basis functions.
virtual Real rb_solve(unsigned int N)
Perform online solve with the N RB basis functions, for the set of parameters in current_params,...
std::vector< std::vector< std::unique_ptr< NumericVector< Number > > > > Aq_representor
Vector storing the residual representors associated with the left-hand side.
virtual unsigned int get_n_basis_functions() const
Get the current number of basis functions.
This class is part of the rbOOmit framework.
const RBParameters & get_parameters() const
Get the current parameters.
Real get_control(const unsigned int k) const
Get/set the RHS control.
void pull_temporal_discretization_data(RBTemporalDiscretization &other)
Pull the temporal discretization data from other.
Real get_delta_t() const
Get/set delta_t, the time-step size.
Real get_euler_theta() const
Get/set euler_theta, parameter that determines the temporal discretization.
void process_temporal_parameters_file(const std::string &parameters_filename)
Read in and initialize parameters from parameters_filename.
unsigned int get_n_time_steps() const
Get/set the total number of time-steps.
unsigned int get_time_step() const
Get/set the current time-step.
virtual Number eval_F_theta(unsigned int q, const RBParameters &mu) const
Evaluate theta_q_f at the current parameter.
unsigned int get_n_F_terms() const
Get Q_f, the number of terms in the affine expansion for the right-hand side.
unsigned int get_n_A_terms() const
Get Q_a, the number of terms in the affine expansion for the bilinear form.
virtual Number eval_A_theta(unsigned int q, const RBParameters &mu) const
Evaluate theta_q_a at the current parameter.
unsigned int get_n_output_terms(unsigned int output_index) const
Get the number of affine terms associated with the specified output.
unsigned int get_n_outputs() const
Get n_outputs, the number output functionals.
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.
Generic sparse matrix.
virtual void close()=0
Calls the SparseMatrix's internal assembly routines, ensuring that the values are consistent across p...
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.
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 zero()=0
Set all entries to 0.
virtual void add(const numeric_index_type i, const numeric_index_type j, const T value)=0
Add value to the element (i,j).
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:1667
void read_serialized_data(Xdr &io, const bool read_additional_data=true)
Reads additional data, namely vectors, for this System.
Definition system_io.C:533
dof_id_type n_dofs() const
Definition system.C:118
dof_id_type n_local_dofs() const
Definition system.C:155
std::unique_ptr< NumericVector< Number > > solution
Data structure to hold solution values.
Definition system.h:1655
virtual void update()
Update the local values to reflect the solution on neighboring processors.
Definition system.C:498
const DofMap & get_dof_map() const
Definition system.h:2417
const MeshBase & get_mesh() const
Definition system.h:2401
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:1518
This extends RBAssemblyExpansion to provide an assembly expansion for the case of time-dependent PDEs...
ElemAssembly & get_M_assembly(unsigned int q)
Return a reference to the specified M_assembly object.
unsigned int get_n_M_terms() const
Get Q_m, the number of terms in the affine expansion for the bilinear form.
virtual void truth_assembly() override
Assemble the truth system in the transient linear case.
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.
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 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::vector< std::vector< Number > > truth_outputs_all_k
The truth outputs for all time-levels from the most recent truth_solve.
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...
Real get_POD_tol() const
Get/set POD_tol.
const NumericVector< Number > & get_error_temporal_data()
Get the column of temporal_data corresponding to the current time level.
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 Real truth_solve(int write_interval) override
Perform a truth solve at the current parameter.
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.
Number set_error_temporal_data()
Set column k (i.e.
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.
TransientRBConstruction(EquationSystems &es, const std::string &name, const unsigned int number)
Constructor.
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.
std::unique_ptr< SparseMatrix< Number > > L2_matrix
The L2 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.
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.
Real POD_tol
If positive, this tolerance determines the number of POD modes we add to the space on a call to enric...
SparseMatrix< Number > * get_non_dirichlet_M_q(unsigned int q)
Get a pointer to non_dirichlet_M_q.
void assemble_mass_matrix(SparseMatrix< Number > *input_matrix)
Assemble the mass matrix at the current parameter and store it in input_matrix.
void assemble_L2_matrix(SparseMatrix< Number > *input_matrix, bool apply_dirichlet_bc=true)
Assemble the L2 matrix.
virtual void initialize_truth()
This function imposes a truth initial condition, defaults to zero initial condition if the flag nonze...
std::vector< std::unique_ptr< SparseMatrix< Number > > > M_q_vector
Vector storing the Q_m matrices from the mass operator.
virtual void clear() override
Clear all the data structures associated with the system.
virtual Real train_reduced_basis(const bool resize_rb_eval_data=true) override
Train the reduced basis.
virtual void print_info() const override
Print out info that describes the current setup of this RBConstruction.
bool compute_truth_projection_error
Boolean flag that indicates whether we will compute the projection error for the truth solution into ...
virtual void enrich_RB_space() override
Add a new basis functions to the RB space.
void add_IC_to_RB_space()
Initialize RB space by adding the truth initial condition as the first RB basis function.
void set_max_truth_solves(int max_truth_solves_in)
virtual void update_system() override
Update the system after enriching the RB space.
virtual void assemble_all_affine_operators() override
Assemble and store all the affine operators.
virtual void assemble_misc_matrices() override
Override to assemble the L2 matrix as well.
std::unique_ptr< SparseMatrix< Number > > non_dirichlet_L2_matrix
The L2 matrix without Dirichlet conditions enforced.
bool nonzero_initialization
Boolean flag to indicate whether we are using a non-zero initialization.
std::string init_filename
The filename of the file containing the initial condition projected onto the truth mesh.
virtual void update_RB_system_matrices() override
Compute the reduced basis matrices for the current basis.
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.
ElemAssembly * L2_assembly
Function pointer for assembling the L2 matrix.
virtual void load_rb_solution() override
Load the RB solution from the current time-level into the libMesh solution vector.
SparseMatrix< Number > * get_M_q(unsigned int q)
Get a pointer to M_q.
DenseVector< Number > RB_ic_proj_rhs_all_N
The vector that stores the right-hand side for the initial condition projections.
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.
std::vector< std::unique_ptr< NumericVector< Number > > > temporal_data
Dense matrix to store the data that we use for the temporal POD.
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.
int max_truth_solves
Maximum number of truth solves in the POD-Greedy.
virtual void process_parameters_file(const std::string &parameters_filename) override
Read in the parameters from file and set up the system accordingly.
void add_scaled_mass_matrix(Number scalar, SparseMatrix< Number > *input_matrix)
Add the scaled mass matrix (assembled for the current parameter) to input_matrix.
void set_L2_assembly(ElemAssembly &L2_assembly_in)
Set the L2 object.
virtual void allocate_data_structures() override
Helper function that actually allocates all the data structures required by this class.
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.
This class is part of the rbOOmit framework.
std::vector< std::vector< std::vector< std::vector< Number > > > > Aq_Mq_representor_innerprods
std::vector< std::vector< std::vector< Number > > > Mq_Mq_representor_innerprods
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.
DenseMatrix< Number > RB_L2_matrix
Dense RB L2 matrix.
std::vector< std::vector< std::unique_ptr< NumericVector< Number > > > > M_q_representor
Vector storing the mass matrix representors.
std::vector< Real > initial_L2_error_all_N
Vector storing initial L2 error for all 1 <= N <= RB_size.
std::vector< DenseMatrix< Number > > RB_M_q_vector
Dense matrices for the RB mass matrices.
std::vector< DenseVector< Number > > RB_temporal_solution_data
Array storing the solution data at each time level from the most recent solve.
std::vector< DenseVector< Number > > RB_initial_condition_all_N
The RB initial conditions (i.e.
This class stores the set of RBTheta functor objects that define the "parameter-dependent expansion" ...
virtual unsigned int get_n_M_terms() const
Get Q_m, the number of terms in the affine expansion for the mass operator.
virtual Number eval_M_theta(unsigned int q, const RBParameters &mu) const
Evaluate theta at the current parameter.
virtual void clear() override
Clear all the data structures associated with the system.
NumericVector< Number > * old_local_solution
All the values I need to compute my contribution to the simulation at hand.
This class implements a C++ interface to the XDR (eXternal Data Representation) format.
Definition xdr_cxx.h:68
std::string get_timestamp()
Definition timestamp.C:37
The libMesh namespace provides an interface to certain functionality in the library.
T libmesh_real(T a)
libmesh_assert(ctx)
OStreamProxy out
T libmesh_conj(T a)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
static const bool value
Definition xdr_io.C:55