libMesh
Loading...
Searching...
No Matches
transient_rb_evaluation.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_evaluation.h"
22#include "libmesh/transient_rb_theta_expansion.h"
23
24// libMesh includes
25#include "libmesh/getpot.h"
26#include "libmesh/int_range.h"
27#include "libmesh/libmesh_logging.h"
28#include "libmesh/numeric_vector.h"
29#include "libmesh/xdr_cxx.h"
30
31// C++ includes
32#include <fstream>
33#include <sstream>
34#include <iomanip>
35
36namespace libMesh
37{
38
40 RBEvaluation(comm_in),
41 _rb_solve_data_cached(false)
42{
43 // Indicate that we need to compute the RB
44 // inner product matrix in this case
46}
47
49
56
58{
60
61 // Delete the M_q representors
62 M_q_representor.clear();
63}
64
66 bool resize_error_bound_data)
67{
68 LOG_SCOPE("resize_data_structures()", "TransientRBEvaluation");
69
70 Parent::resize_data_structures(Nmax, resize_error_bound_data);
71
72 RB_L2_matrix.resize(Nmax,Nmax);
73 RB_LHS_matrix.resize(Nmax,Nmax);
74 RB_RHS_matrix.resize(Nmax,Nmax);
75 RB_RHS_save.resize(Nmax);
76
77 TransientRBThetaExpansion & trans_theta_expansion =
78 cast_ref<TransientRBThetaExpansion &>(get_rb_theta_expansion());
79 const unsigned int Q_m = trans_theta_expansion.get_n_M_terms();
80 const unsigned int Q_a = trans_theta_expansion.get_n_A_terms();
81 const unsigned int Q_f = trans_theta_expansion.get_n_F_terms();
82
83 // Allocate dense matrices for RB solves
84 RB_M_q_vector.resize(Q_m);
85 for (unsigned int q=0; q<Q_m; q++)
86 {
87 // Initialize the memory for the RB matrices
88 RB_M_q_vector[q].resize(Nmax,Nmax);
89 }
90
91 // Initialize the initial condition storage
92 RB_initial_condition_all_N.resize(Nmax);
93 for (auto i : make_range(RB_initial_condition_all_N.size()))
94 {
95 // The i^th row holds a vector of length i+1
96 RB_initial_condition_all_N[i].resize(i+1);
97 }
98
99 initial_L2_error_all_N.resize(Nmax, 0.);
100
101
102 if (resize_error_bound_data)
103 {
104 // Initialize vectors for the norms of the representors
106 for (unsigned int i=0; i<Q_f; i++)
107 {
108 Fq_Mq_representor_innerprods[i].resize(Q_m);
109 for (unsigned int j=0; j<Q_m; j++)
110 {
111 Fq_Mq_representor_innerprods[i][j].resize(Nmax, 0.);
112 }
113 }
114
115 unsigned int Q_m_hat = Q_m*(Q_m+1)/2;
116 Mq_Mq_representor_innerprods.resize(Q_m_hat);
117 for (unsigned int i=0; i<Q_m_hat; i++)
118 {
119 Mq_Mq_representor_innerprods[i].resize(Nmax);
120 for (unsigned int j=0; j<Nmax; j++)
121 {
122 Mq_Mq_representor_innerprods[i][j].resize(Nmax, 0.);
123 }
124 }
125
127 for (unsigned int i=0; i<Q_a; i++)
128 {
129 Aq_Mq_representor_innerprods[i].resize(Q_m);
130 for (unsigned int j=0; j<Q_m; j++)
131 {
132 Aq_Mq_representor_innerprods[i][j].resize(Nmax);
133 for (unsigned int k=0; k<Nmax; k++)
134 {
135 Aq_Mq_representor_innerprods[i][j][k].resize(Nmax, 0.);
136 }
137 }
138 }
139
140 // Resize M_q_representor
141 // This is cleared in the call to clear_riesz_representors
142 // in Parent::resize_RB_data, so just resize here
143 M_q_representor.resize(Q_m);
144 for (unsigned int q_m=0; q_m<Q_m; q_m++)
145 {
146 M_q_representor[q_m].resize(Nmax);
147 }
148 }
149}
150
152{
153 LOG_SCOPE("rb_solve()", "TransientRBEvaluation");
154
155 libmesh_error_msg_if(N > get_n_basis_functions(),
156 "ERROR: N cannot be larger than the number of basis functions in rb_solve");
157
158 const RBParameters & mu = get_parameters();
159
160 TransientRBThetaExpansion & trans_theta_expansion =
161 cast_ref<TransientRBThetaExpansion &>(get_rb_theta_expansion());
162 const unsigned int Q_m = trans_theta_expansion.get_n_M_terms();
163 const unsigned int Q_a = trans_theta_expansion.get_n_A_terms();
164 const unsigned int Q_f = trans_theta_expansion.get_n_F_terms();
165
166 const unsigned int n_time_steps = get_n_time_steps();
167 const Real dt = get_delta_t();
168 const Real euler_theta = get_euler_theta();
169
170 // Resize the RB and error bound vectors
171 error_bound_all_k.resize(n_time_steps+1);
172 RB_outputs_all_k.resize(trans_theta_expansion.get_n_outputs());
173 RB_output_error_bounds_all_k.resize(trans_theta_expansion.get_n_outputs());
174 for (unsigned int n=0; n<trans_theta_expansion.get_n_outputs(); n++)
175 {
176 RB_outputs_all_k[n].resize(n_time_steps+1, 0.);
177 RB_output_error_bounds_all_k[n].resize(n_time_steps+1, 0.);
178 }
179
180 // First assemble the mass matrix
181 DenseMatrix<Number> RB_mass_matrix_N(N,N);
182 RB_mass_matrix_N.zero();
183 DenseMatrix<Number> RB_M_q_m;
184 for (unsigned int q_m=0; q_m<Q_m; q_m++)
185 {
186 RB_M_q_vector[q_m].get_principal_submatrix(N, RB_M_q_m);
187 RB_mass_matrix_N.add(trans_theta_expansion.eval_M_theta(q_m, mu), RB_M_q_m);
188 }
189
192
195
196 RB_LHS_matrix.add(1./dt, RB_mass_matrix_N);
197 RB_RHS_matrix.add(1./dt, RB_mass_matrix_N);
198
199 DenseMatrix<Number> RB_Aq_a;
200 for (unsigned int q_a=0; q_a<Q_a; q_a++)
201 {
202 RB_Aq_vector[q_a].get_principal_submatrix(N, RB_Aq_a);
203
204 RB_LHS_matrix.add( euler_theta*trans_theta_expansion.eval_A_theta(q_a,mu), RB_Aq_a);
205 RB_RHS_matrix.add( -(1.-euler_theta)*trans_theta_expansion.eval_A_theta(q_a,mu), RB_Aq_a);
206 }
207
208 // Add forcing terms
209 DenseVector<Number> RB_Fq_f;
212 for (unsigned int q_f=0; q_f<Q_f; q_f++)
213 {
214 RB_Fq_vector[q_f].get_principal_subvector(N, RB_Fq_f);
215 RB_RHS_save.add(trans_theta_expansion.eval_F_theta(q_f,mu), RB_Fq_f);
216 }
217
218 // Set system time level to 0
219 set_time_step(0);
220
221 // Resize/clear the solution vector
223
224 // Load the initial condition into RB_solution
225 if (N > 0)
226 {
228 }
229
230 // Resize/clear the old solution vector
232
233 // Initialize the RB rhs
234 DenseVector<Number> RB_rhs(N);
235 RB_rhs.zero();
236
237 // Initialize the vectors storing solution data
238 RB_temporal_solution_data.resize(n_time_steps+1);
239 for (unsigned int time_level=0; time_level<=n_time_steps; time_level++)
240 {
241 RB_temporal_solution_data[time_level].resize(N);
242 }
243 // and load the initial data
245
246 // Set outputs at initial time
247 {
248 DenseVector<Number> RB_output_vector_N;
249 for (unsigned int n=0; n<trans_theta_expansion.get_n_outputs(); n++)
250 {
251 RB_outputs_all_k[n][0] = 0.;
252 for (unsigned int q_l=0; q_l<trans_theta_expansion.get_n_output_terms(n); q_l++)
253 {
254 RB_output_vectors[n][q_l].get_principal_subvector(N, RB_output_vector_N);
255 RB_outputs_all_k[n][0] += trans_theta_expansion.eval_output_theta(n,q_l,mu)*RB_output_vector_N.dot(RB_solution);
256 }
257 }
258 }
259
260 // Initialize error bounds, if necessary
261 Real error_bound_sum = 0.;
262 Real alpha_LB = 0.;
264 {
265 if (N > 0)
266 {
267 error_bound_sum += pow( initial_L2_error_all_N[N-1], 2.);
268 }
269
270 // Set error bound at the initial time
271 error_bound_all_k[get_time_step()] = std::sqrt(error_bound_sum);
272
273 // Compute the outputs and associated error bounds at the initial time
274 DenseVector<Number> RB_output_vector_N;
275 for (unsigned int n=0; n<trans_theta_expansion.get_n_outputs(); n++)
276 {
277 RB_outputs_all_k[n][0] = 0.;
278 for (unsigned int q_l=0; q_l<trans_theta_expansion.get_n_output_terms(n); q_l++)
279 {
280 RB_output_vectors[n][q_l].get_principal_subvector(N, RB_output_vector_N);
281 RB_outputs_all_k[n][0] += trans_theta_expansion.eval_output_theta(n,q_l,mu)*RB_output_vector_N.dot(RB_solution);
282 }
283
285 }
286
287 alpha_LB = get_stability_lower_bound();
288
289 // Precompute time-invariant parts of the dual norm of the residual.
291 }
292
293 for (unsigned int time_level=1; time_level<=n_time_steps; time_level++)
294 {
295 set_time_step(time_level);
297
298 // Compute RB_rhs, as RB_LHS_matrix x old_RB_solution
300
301 // Add forcing terms
302 RB_rhs.add(get_control(time_level), RB_RHS_save);
303
304 if (N > 0)
305 {
307 }
308
309 // Save RB_solution for current time level
311
312 // Evaluate outputs
313 DenseVector<Number> RB_output_vector_N;
314 for (unsigned int n=0; n<trans_theta_expansion.get_n_outputs(); n++)
315 {
316 RB_outputs_all_k[n][time_level] = 0.;
317 for (unsigned int q_l=0; q_l<trans_theta_expansion.get_n_output_terms(n); q_l++)
318 {
319 RB_output_vectors[n][q_l].get_principal_subvector(N, RB_output_vector_N);
320 RB_outputs_all_k[n][time_level] += trans_theta_expansion.eval_output_theta(n,q_l,mu)*
321 RB_output_vector_N.dot(RB_solution);
322 }
323 }
324
325 // Calculate RB error bounds
327 {
328 // Evaluate the dual norm of the residual for RB_solution_vector
329 // Real epsilon_N = uncached_compute_residual_dual_norm(N);
330 Real epsilon_N = compute_residual_dual_norm(N);
331
332 error_bound_sum += residual_scaling_numer(alpha_LB) * pow(epsilon_N, 2.);
333
334 // store error bound at time-level _k
335 error_bound_all_k[time_level] = std::sqrt(error_bound_sum/residual_scaling_denom(alpha_LB));
336
337 // Now evaluated output error bounds
338 for (unsigned int n=0; n<trans_theta_expansion.get_n_outputs(); n++)
339 {
340 RB_output_error_bounds_all_k[n][time_level] = error_bound_all_k[time_level] *
341 eval_output_dual_norm(n, nullptr);
342 }
343 }
344 }
345
346 _rb_solve_data_cached = true ;
347
348 if (evaluate_RB_error_bound) // Calculate the error bounds
349 {
350 return error_bound_all_k[n_time_steps];
351 }
352 else // Don't calculate the error bounds
353 {
354 // Just return -1. if we did not compute the error bound
355 return -1.;
356 }
357}
358
360{
362
363 const unsigned int n_time_steps = get_n_time_steps();
364 // Set system time level to 0
365 set_time_step(0);
366
367 // Resize/clear the solution vector
368 const unsigned int N = RB_RHS_save.size();
370
371 // Load the initial condition into RB_solution
372 if (N > 0)
374
375 // Resize/clear the old solution vector
377
378 // Initialize the RB rhs
379 DenseVector<Number> RB_rhs(N);
380 RB_rhs.zero();
381
382 for (unsigned int time_level=1; time_level<=n_time_steps; time_level++)
383 {
384 set_time_step(time_level);
386
387 // Compute RB_rhs, as *RB_lhs_matrix x old_RB_solution
389
390 // Add forcing terms
391 RB_rhs.add(get_control(time_level), RB_RHS_save);
392
393 if (N > 0)
395 }
396
397 {
398 // Just return -1. We did not compute the error bound
399 return -1.;
400 }
401}
402
404{
405 // Just set the normalization factor to 1 in this case.
406 // Users can override this method if specific behavior
407 // is required.
408
409 return 1.;
410}
411
416
418{
419 LOG_SCOPE("cache_online_residual_terms()", "TransientRBEvaluation");
420
421 const RBParameters mu = get_parameters();
422
423 TransientRBThetaExpansion & trans_theta_expansion =
424 cast_ref<TransientRBThetaExpansion &>(get_rb_theta_expansion());
425 const unsigned int Q_m = trans_theta_expansion.get_n_M_terms();
426 const unsigned int Q_a = trans_theta_expansion.get_n_A_terms();
427 const unsigned int Q_f = trans_theta_expansion.get_n_F_terms();
428
429 cached_Fq_term = 0.;
430 unsigned int q=0;
431 for (unsigned int q_f1=0; q_f1<Q_f; q_f1++)
432 {
433 Number cached_theta_q_f1 = trans_theta_expansion.eval_F_theta(q_f1,mu);
434 for (unsigned int q_f2=q_f1; q_f2<Q_f; q_f2++)
435 {
436 Real delta = (q_f1==q_f2) ? 1. : 2.;
437 cached_Fq_term += delta*cached_theta_q_f1*trans_theta_expansion.eval_F_theta(q_f2,mu) *
439
440 q++;
441 }
442 }
443
445 for (unsigned int q_f=0; q_f<Q_f; q_f++)
446 {
447 Number cached_theta_q_f = trans_theta_expansion.eval_F_theta(q_f,mu);
448 for (unsigned int q_a=0; q_a<Q_a; q_a++)
449 {
450 Number cached_theta_q_a = trans_theta_expansion.eval_A_theta(q_a,mu);
451 for (unsigned int i=0; i<N; i++)
452 {
453 cached_Fq_Aq_vector(i) += 2.*cached_theta_q_f*cached_theta_q_a*
454 Fq_Aq_representor_innerprods[q_f][q_a][i];
455 }
456 }
457 }
458
460 q=0;
461 for (unsigned int q_a1=0; q_a1<Q_a; q_a1++)
462 {
463 Number cached_theta_q_a1 = trans_theta_expansion.eval_A_theta(q_a1,mu);
464 for (unsigned int q_a2=q_a1; q_a2<Q_a; q_a2++)
465 {
466 Number cached_theta_q_a2 = trans_theta_expansion.eval_A_theta(q_a2,mu);
467 Real delta = (q_a1==q_a2) ? 1. : 2.;
468
469 for (unsigned int i=0; i<N; i++)
470 {
471 for (unsigned int j=0; j<N; j++)
472 {
473 cached_Aq_Aq_matrix(i,j) += delta*
474 cached_theta_q_a1*cached_theta_q_a2*
476 }
477 }
478 q++;
479 }
480 }
481
483 for (unsigned int q_f=0; q_f<Q_f; q_f++)
484 {
485 Number cached_theta_q_f = trans_theta_expansion.eval_F_theta(q_f,mu);
486 for (unsigned int q_m=0; q_m<Q_m; q_m++)
487 {
488 Number cached_theta_q_m = trans_theta_expansion.eval_M_theta(q_m,mu);
489 for (unsigned int i=0; i<N; i++)
490 {
491 cached_Fq_Mq_vector(i) += 2.*cached_theta_q_f * cached_theta_q_m * Fq_Mq_representor_innerprods[q_f][q_m][i];
492 }
493 }
494 }
495
497 for (unsigned int q_a=0; q_a<Q_a; q_a++)
498 {
499 Number cached_theta_q_a = trans_theta_expansion.eval_A_theta(q_a,mu);
500
501 for (unsigned int q_m=0; q_m<Q_m; q_m++)
502 {
503 Number cached_theta_q_m = trans_theta_expansion.eval_M_theta(q_m,mu);
504
505 for (unsigned int i=0; i<N; i++)
506 {
507 for (unsigned int j=0; j<N; j++)
508 {
509 cached_Aq_Mq_matrix(i,j) += 2.*cached_theta_q_a*cached_theta_q_m*Aq_Mq_representor_innerprods[q_a][q_m][i][j];
510 }
511 }
512 }
513 }
514
516 q=0;
517 for (unsigned int q_m1=0; q_m1<Q_m; q_m1++)
518 {
519 Number cached_theta_q_m1 = trans_theta_expansion.eval_M_theta(q_m1,mu);
520 for (unsigned int q_m2=q_m1; q_m2<Q_m; q_m2++)
521 {
522 Number cached_theta_q_m2 = trans_theta_expansion.eval_M_theta(q_m2,mu);
523 Real delta = (q_m1==q_m2) ? 1. : 2.;
524
525 for (unsigned int i=0; i<N; i++)
526 {
527 for (unsigned int j=0; j<N; j++)
528 {
529 cached_Mq_Mq_matrix(i,j) += delta*
530 cached_theta_q_m1*cached_theta_q_m2*
532 }
533 }
534 q++;
535 }
536 }
537}
538
540{
541 LOG_SCOPE("compute_residual_dual_norm()", "TransientRBEvaluation");
542
543 // This assembly assumes we have already called cache_online_residual_terms
544 // and that the rb_solve parameter is constant in time
545
546 const Real dt = get_delta_t();
547 const Real euler_theta = get_euler_theta();
548 const Real current_control = get_control(get_time_step());
549
550 DenseVector<Number> RB_u_euler_theta(N);
551 DenseVector<Number> mass_coeffs(N);
552 for (unsigned int i=0; i<N; i++)
553 {
554 RB_u_euler_theta(i) = euler_theta*RB_solution(i) +
555 (1.-euler_theta)*old_RB_solution(i);
556 mass_coeffs(i) = -(RB_solution(i) - old_RB_solution(i))/dt;
557 }
558
559 Number residual_norm_sq = current_control*current_control*cached_Fq_term;
560
561 residual_norm_sq += current_control*RB_u_euler_theta.dot(cached_Fq_Aq_vector);
562 residual_norm_sq += current_control*mass_coeffs.dot(cached_Fq_Mq_vector);
563
564 for (unsigned int i=0; i<N; i++)
565 for (unsigned int j=0; j<N; j++)
566 {
567 residual_norm_sq += RB_u_euler_theta(i)*RB_u_euler_theta(j)*cached_Aq_Aq_matrix(i,j);
568 residual_norm_sq += mass_coeffs(i)*mass_coeffs(j)*cached_Mq_Mq_matrix(i,j);
569 residual_norm_sq += RB_u_euler_theta(i)*mass_coeffs(j)*cached_Aq_Mq_matrix(i,j);
570 }
571
572
573 if (libmesh_real(residual_norm_sq) < 0)
574 {
575 libMesh::out << "Warning: Square of residual norm is negative "
576 << "in TransientRBEvaluation::compute_residual_dual_norm()" << std::endl;
577
578 // Sometimes this is negative due to rounding error,
579 // but error is on the order of 1.e-10, so shouldn't
580 // affect result
581 residual_norm_sq = std::abs(residual_norm_sq);
582 }
583
584 return libmesh_real(std::sqrt( residual_norm_sq ));
585}
586
588{
589 LOG_SCOPE("uncached_compute_residual_dual_norm()", "TransientRBEvaluation");
590
591 // Use the stored representor inner product values
592 // to evaluate the residual norm
593
594 const RBParameters & mu = get_parameters();
595
596 TransientRBThetaExpansion & trans_theta_expansion =
597 cast_ref<TransientRBThetaExpansion &>(get_rb_theta_expansion());
598 const unsigned int Q_m = trans_theta_expansion.get_n_M_terms();
599 const unsigned int Q_a = trans_theta_expansion.get_n_A_terms();
600 const unsigned int Q_f = trans_theta_expansion.get_n_F_terms();
601
602 const Real dt = get_delta_t();
603 const Real euler_theta = get_euler_theta();
604
605 std::vector<Number> RB_u_euler_theta(N);
606 std::vector<Number> mass_coeffs(N);
607 for (unsigned int i=0; i<N; i++)
608 {
609 RB_u_euler_theta[i] = euler_theta*RB_solution(i) +
610 (1.-euler_theta)*old_RB_solution(i);
611 mass_coeffs[i] = -(RB_solution(i) - old_RB_solution(i))/dt;
612 }
613
614 Number residual_norm_sq = 0.;
615
616 unsigned int q=0;
617 for (unsigned int q_f1=0; q_f1<Q_f; q_f1++)
618 {
619 Number cached_theta_q_f1 = trans_theta_expansion.eval_F_theta(q_f1,mu);
620 for (unsigned int q_f2=q_f1; q_f2<Q_f; q_f2++)
621 {
622 Real delta = (q_f1==q_f2) ? 1. : 2.;
623 residual_norm_sq += delta*cached_theta_q_f1*trans_theta_expansion.eval_F_theta(q_f2,mu) * Fq_representor_innerprods[q];
624
625 q++;
626 }
627 }
628
629 for (unsigned int q_f=0; q_f<Q_f; q_f++)
630 {
631 Number cached_theta_q_f = trans_theta_expansion.eval_F_theta(q_f,mu);
632 for (unsigned int q_a=0; q_a<Q_a; q_a++)
633 {
634 Number cached_theta_q_a = trans_theta_expansion.eval_A_theta(q_a,mu);
635 for (unsigned int i=0; i<N; i++)
636 {
637 residual_norm_sq += 2.*RB_u_euler_theta[i]*cached_theta_q_f*cached_theta_q_a*
638 Fq_Aq_representor_innerprods[q_f][q_a][i];
639 }
640 }
641 }
642
643 q=0;
644 for (unsigned int q_a1=0; q_a1<Q_a; q_a1++)
645 {
646 Number cached_theta_q_a1 = trans_theta_expansion.eval_A_theta(q_a1,mu);
647 for (unsigned int q_a2=q_a1; q_a2<Q_a; q_a2++)
648 {
649 Number cached_theta_q_a2 = trans_theta_expansion.eval_A_theta(q_a2,mu);
650 Real delta = (q_a1==q_a2) ? 1. : 2.;
651
652 for (unsigned int i=0; i<N; i++)
653 {
654 for (unsigned int j=0; j<N; j++)
655 {
656 residual_norm_sq += delta*RB_u_euler_theta[i]*RB_u_euler_theta[j]*
657 cached_theta_q_a1*cached_theta_q_a2*
659 }
660 }
661 q++;
662 }
663 }
664
665 // Now add the terms due to the time-derivative
666 q=0;
667 for (unsigned int q_m1=0; q_m1<Q_m; q_m1++)
668 {
669 Number cached_theta_q_m1 = trans_theta_expansion.eval_M_theta(q_m1,mu);
670 for (unsigned int q_m2=q_m1; q_m2<Q_m; q_m2++)
671 {
672 Number cached_theta_q_m2 = trans_theta_expansion.eval_M_theta(q_m2,mu);
673 Real delta = (q_m1==q_m2) ? 1. : 2.;
674
675 for (unsigned int i=0; i<N; i++)
676 {
677 for (unsigned int j=0; j<N; j++)
678 {
679 residual_norm_sq += delta*mass_coeffs[i]*mass_coeffs[j]*
680 cached_theta_q_m1*cached_theta_q_m2*
682 }
683 }
684 q++;
685 }
686 }
687
688 for (unsigned int q_f=0; q_f<Q_f; q_f++)
689 {
690 Number cached_theta_q_f = trans_theta_expansion.eval_F_theta(q_f,mu);
691 for (unsigned int q_m=0; q_m<Q_m; q_m++)
692 {
693 Number cached_theta_q_m = trans_theta_expansion.eval_M_theta(q_m,mu);
694 for (unsigned int i=0; i<N; i++)
695 {
696 residual_norm_sq += 2.*mass_coeffs[i]*cached_theta_q_f * cached_theta_q_m * Fq_Mq_representor_innerprods[q_f][q_m][i];
697 }
698 }
699 }
700
701 for (unsigned int q_a=0; q_a<Q_a; q_a++)
702 {
703 Number cached_theta_q_a = trans_theta_expansion.eval_A_theta(q_a,mu);
704
705 for (unsigned int q_m=0; q_m<Q_m; q_m++)
706 {
707 Number cached_theta_q_m = trans_theta_expansion.eval_M_theta(q_m,mu);
708
709 for (unsigned int i=0; i<N; i++)
710 {
711 for (unsigned int j=0; j<N; j++)
712 {
713 residual_norm_sq += 2.*RB_u_euler_theta[i]*mass_coeffs[j]*
714 cached_theta_q_a*cached_theta_q_m*
715 Aq_Mq_representor_innerprods[q_a][q_m][i][j];
716 }
717 }
718 }
719 }
720
721 if (libmesh_real(residual_norm_sq) < 0)
722 {
723 libMesh::out << "Warning: Square of residual norm is negative "
724 << "in TransientRBEvaluation::compute_residual_dual_norm()" << std::endl;
725
726 // Sometimes this is negative due to rounding error,
727 // but error is on the order of 1.e-10, so shouldn't
728 // affect result
729 residual_norm_sq = std::abs(residual_norm_sq);
730 }
731
732 // libMesh::out << "slow residual_sq = " << slow_residual_norm_sq
733 // << ", fast residual_sq = " << residual_norm_sq << std::endl;
734
735 return libmesh_real(std::sqrt( residual_norm_sq ));
736}
737
738void TransientRBEvaluation::legacy_write_offline_data_to_files(const std::string & directory_name,
739 const bool write_binary_data)
740{
741 LOG_SCOPE("legacy_write_offline_data_to_files()", "TransientRBEvaluation");
742
744
745 TransientRBThetaExpansion & trans_theta_expansion =
746 cast_ref<TransientRBThetaExpansion &>(get_rb_theta_expansion());
747 const unsigned int Q_m = trans_theta_expansion.get_n_M_terms();
748 const unsigned int Q_a = trans_theta_expansion.get_n_A_terms();
749 const unsigned int Q_f = trans_theta_expansion.get_n_F_terms();
750
751 const unsigned int n_bfs = get_n_basis_functions();
752
753 // The writing mode: ENCODE for binary, WRITE for ASCII
754 XdrMODE mode = write_binary_data ? ENCODE : WRITE;
755
756 // The suffix to use for all the files that are written out
757 const std::string suffix = write_binary_data ? ".xdr" : ".dat";
758
759 if (this->processor_id() == 0)
760 {
761 std::ostringstream file_name;
762
763 // Write out the temporal discretization data
764 file_name.str("");
765 file_name << directory_name << "/temporal_discretization_data" << suffix;
766 Xdr temporal_discretization_data_out(file_name.str(), mode);
767
768 Real real_value; unsigned int int_value;
769 real_value = get_delta_t(); temporal_discretization_data_out << real_value;
770 real_value = get_euler_theta(); temporal_discretization_data_out << real_value;
771 int_value = get_n_time_steps(); temporal_discretization_data_out << int_value;
772 int_value = get_time_step(); temporal_discretization_data_out << int_value;
773 temporal_discretization_data_out.close();
774
775
776 // Write out the L2 matrix
777 file_name.str("");
778 file_name << directory_name << "/RB_L2_matrix" << suffix;
779 Xdr RB_L2_matrix_out(file_name.str(), mode);
780
781 for (unsigned int i=0; i<n_bfs; i++)
782 {
783 for (unsigned int j=0; j<n_bfs; j++)
784 {
785 RB_L2_matrix_out << RB_L2_matrix(i,j);
786 }
787 }
788 RB_L2_matrix_out.close();
789
790 // Write out the M_q matrices
791 for (unsigned int q_m=0; q_m<Q_m; q_m++)
792 {
793 file_name.str("");
794 file_name << directory_name << "/RB_M_";
795 file_name << std::setw(3)
796 << std::setprecision(0)
797 << std::setfill('0')
798 << std::right
799 << q_m;
800 file_name << suffix;
801 Xdr RB_M_q_m_out(file_name.str(), mode);
802
803 for (unsigned int i=0; i<n_bfs; i++)
804 {
805 for (unsigned int j=0; j<n_bfs; j++)
806 {
807 RB_M_q_m_out << RB_M_q_vector[q_m](i,j);
808 }
809 }
810 RB_M_q_m_out.close();
811 }
812
813 // Write out the initial condition data
814 // and the initial L2 error for all N
815 file_name.str("");
816 file_name << directory_name << "/initial_conditions" << suffix;
817 Xdr initial_conditions_out(file_name.str(), mode);
818 file_name.str("");
819 file_name << directory_name << "/initial_L2_error" << suffix;
820 Xdr initial_L2_error_out(file_name.str(), mode);
821
822 for (unsigned int i=0; i<n_bfs; i++)
823 {
824 initial_L2_error_out << initial_L2_error_all_N[i];
825 for (unsigned int j=0; j<=i; j++)
826 {
827 initial_conditions_out << RB_initial_condition_all_N[i](j);
828 }
829 }
830 initial_conditions_out.close();
831 initial_L2_error_out.close();
832
833 // Next write out the Fq_Mq representor norm data
834 file_name.str("");
835 file_name << directory_name << "/Fq_Mq_terms" << suffix;
836 Xdr RB_Fq_Mq_terms_out(file_name.str(), mode);
837
838 for (unsigned int q_f=0; q_f<Q_f; q_f++)
839 {
840 for (unsigned int q_m=0; q_m<Q_m; q_m++)
841 {
842 for (unsigned int i=0; i<n_bfs; i++)
843 {
844 RB_Fq_Mq_terms_out << Fq_Mq_representor_innerprods[q_f][q_m][i];
845 }
846 }
847 }
848 RB_Fq_Mq_terms_out.close();
849
850 // Next write out the Mq_Mq representor norm data
851 file_name.str("");
852 file_name << directory_name << "/Mq_Mq_terms" << suffix;
853 Xdr RB_Mq_Mq_terms_out(file_name.str(), mode);
854
855 unsigned int Q_m_hat = Q_m*(Q_m+1)/2;
856 for (unsigned int q=0; q<Q_m_hat; q++)
857 {
858 for (unsigned int i=0; i<n_bfs; i++)
859 {
860 for (unsigned int j=0; j<n_bfs; j++)
861 {
862 RB_Mq_Mq_terms_out << Mq_Mq_representor_innerprods[q][i][j];
863 }
864 }
865 }
866 RB_Mq_Mq_terms_out.close();
867
868 // Next write out the Aq_Mq representor norm data
869 file_name.str("");
870 file_name << directory_name << "/Aq_Mq_terms" << suffix;
871 Xdr RB_Aq_Mq_terms_out(file_name.str(), mode);
872
873 for (unsigned int q_a=0; q_a<Q_a; q_a++)
874 {
875 for (unsigned int q_m=0; q_m<Q_m; q_m++)
876 {
877 for (unsigned int i=0; i<n_bfs; i++)
878 {
879 for (unsigned int j=0; j<n_bfs; j++)
880 {
881 RB_Aq_Mq_terms_out << Aq_Mq_representor_innerprods[q_a][q_m][i][j];
882 }
883 }
884 }
885 }
886 RB_Aq_Mq_terms_out.close();
887 }
888}
889
891 bool read_error_bound_data,
892 const bool read_binary_data)
893{
894 LOG_SCOPE("legacy_read_offline_data_from_files()", "TransientRBEvaluation");
895
897
898 TransientRBThetaExpansion & trans_theta_expansion =
899 cast_ref<TransientRBThetaExpansion &>(get_rb_theta_expansion());
900 const unsigned int Q_m = trans_theta_expansion.get_n_M_terms();
901 const unsigned int Q_a = trans_theta_expansion.get_n_A_terms();
902 const unsigned int Q_f = trans_theta_expansion.get_n_F_terms();
903
904 // First, find out how many basis functions we had when Greedy terminated
905 // This was set in RBSystem::read_offline_data_from_files
906 unsigned int n_bfs = this->get_n_basis_functions();
907
908 // The reading mode: DECODE for binary, READ for ASCII
909 XdrMODE mode = read_binary_data ? DECODE : READ;
910
911 // The suffix to use for all the files that are written out
912 const std::string suffix = read_binary_data ? ".xdr" : ".dat";
913
914 // The string stream we'll use to make the file names
915 std::ostringstream file_name;
916
917 // Write out the temporal discretization data
918 file_name.str("");
919 file_name << directory_name << "/temporal_discretization_data" << suffix;
920 assert_file_exists(file_name.str());
921
922 Xdr temporal_discretization_data_in(file_name.str(), mode);
923
924 Real real_value; unsigned int int_value;
925 temporal_discretization_data_in >> real_value; set_delta_t(real_value);
926 temporal_discretization_data_in >> real_value; set_euler_theta(real_value);
927 temporal_discretization_data_in >> int_value; set_n_time_steps(int_value);
928 temporal_discretization_data_in >> int_value; set_time_step(int_value);
929 temporal_discretization_data_in.close();
930
931 file_name.str("");
932 file_name << directory_name << "/RB_L2_matrix" << suffix;
933 assert_file_exists(file_name.str());
934
935 Xdr RB_L2_matrix_in(file_name.str(), mode);
936
937 for (unsigned int i=0; i<n_bfs; i++)
938 {
939 for (unsigned int j=0; j<n_bfs; j++)
940 {
942 RB_L2_matrix_in >> value;
943 RB_L2_matrix(i,j) = value;
944 }
945 }
946 RB_L2_matrix_in.close();
947
948 // Read in the M_q matrices
949 for (unsigned int q_m=0; q_m<Q_m; q_m++)
950 {
951 file_name.str("");
952 file_name << directory_name << "/RB_M_";
953 file_name << std::setw(3)
954 << std::setprecision(0)
955 << std::setfill('0')
956 << std::right
957 << q_m;
958
959 file_name << suffix;
960 assert_file_exists(file_name.str());
961
962 Xdr RB_M_q_m_in(file_name.str(), mode);
963
964 for (unsigned int i=0; i<n_bfs; i++)
965 {
966 for (unsigned int j=0; j<n_bfs; j++)
967 {
969 RB_M_q_m_in >> value;
970 RB_M_q_vector[q_m](i,j) = value;
971 }
972 }
973 RB_M_q_m_in.close();
974 }
975
976
977 // Read in the initial condition data
978 // and the initial L2 error for all N
979 file_name.str("");
980 file_name << directory_name << "/initial_conditions" << suffix;
981 assert_file_exists(file_name.str());
982
983 Xdr initial_conditions_in(file_name.str(), mode);
984
985 file_name.str("");
986 file_name << directory_name << "/initial_L2_error" << suffix;
987 assert_file_exists(file_name.str());
988
989 Xdr initial_L2_error_in(file_name.str(), mode);
990
991 for (unsigned int i=0; i<n_bfs; i++)
992 {
993 initial_L2_error_in >> initial_L2_error_all_N[i];
994 for (unsigned int j=0; j<=i; j++)
995 {
996 initial_conditions_in >> RB_initial_condition_all_N[i](j);
997 }
998 }
999 initial_conditions_in.close();
1000 initial_L2_error_in.close();
1001
1002
1003 if (read_error_bound_data)
1004 {
1005 // Next read in the Fq_Mq representor norm data
1006 file_name.str("");
1007 file_name << directory_name << "/Fq_Mq_terms" << suffix;
1008 assert_file_exists(file_name.str());
1009
1010 Xdr RB_Fq_Mq_terms_in(file_name.str(), mode);
1011
1012 for (unsigned int q_f=0; q_f<Q_f; q_f++)
1013 {
1014 for (unsigned int q_m=0; q_m<Q_m; q_m++)
1015 {
1016 for (unsigned int i=0; i<n_bfs; i++)
1017 {
1018 RB_Fq_Mq_terms_in >> Fq_Mq_representor_innerprods[q_f][q_m][i];
1019 }
1020 }
1021 }
1022 RB_Fq_Mq_terms_in.close();
1023
1024 // Next read in the Mq_Mq representor norm data
1025 file_name.str("");
1026 file_name << directory_name << "/Mq_Mq_terms" << suffix;
1027 assert_file_exists(file_name.str());
1028
1029 Xdr RB_Mq_Mq_terms_in(file_name.str(), mode);
1030
1031 unsigned int Q_m_hat = Q_m*(Q_m+1)/2;
1032 for (unsigned int q=0; q<Q_m_hat; q++)
1033 {
1034 for (unsigned int i=0; i<n_bfs; i++)
1035 {
1036 for (unsigned int j=0; j<n_bfs; j++)
1037 {
1038 RB_Mq_Mq_terms_in >> Mq_Mq_representor_innerprods[q][i][j];
1039 }
1040 }
1041 }
1042 RB_Mq_Mq_terms_in.close();
1043
1044 // Next read in the Aq_Mq representor norm data
1045 file_name.str("");
1046 file_name << directory_name << "/Aq_Mq_terms" << suffix;
1047 assert_file_exists(file_name.str());
1048
1049 Xdr RB_Aq_Mq_terms_in(file_name.str(), mode);
1050
1051 for (unsigned int q_a=0; q_a<Q_a; q_a++)
1052 {
1053 for (unsigned int q_m=0; q_m<Q_m; q_m++)
1054 {
1055 for (unsigned int i=0; i<n_bfs; i++)
1056 {
1057 for (unsigned int j=0; j<n_bfs; j++)
1058 {
1059 RB_Aq_Mq_terms_in >> Aq_Mq_representor_innerprods[q_a][q_m][i][j];
1060 }
1061 }
1062 }
1063 }
1064 RB_Aq_Mq_terms_in.close();
1065 }
1066}
1067
1068}
Defines a dense matrix for use in Finite Element-type computations.
void vector_mult(DenseVector< T > &dest, const DenseVector< T > &arg) const
Performs the matrix-vector multiplication, dest := (*this) * arg.
void resize(const unsigned int new_m, const unsigned int new_n)
Resizes the matrix to the specified size and calls zero().
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.
std::enable_if< ScalarTraits< T2 >::value, void >::type add(const T2 factor, const DenseMatrix< T3 > &mat)
Adds factor times mat to this matrix.
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.
std::enable_if< ScalarTraits< T2 >::value, void >::type add(const T2 factor, const DenseVector< T3 > &vec)
Adds factor times vec to this vector.
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
processor_id_type processor_id() const
This class is part of the rbOOmit framework.
virtual Real residual_scaling_denom(Real alpha_LB)
Specifies the residual scaling on the denominator to be used in the a posteriori error bound.
virtual void legacy_write_offline_data_to_files(const std::string &directory_name="offline_data", const bool write_binary_data=true)
Write out all the data to text files in order to segregate the Offline stage from the Online stage.
std::vector< Number > Fq_representor_innerprods
Vectors storing the residual representor inner products to be used in computing the residuals online.
virtual void resize_data_structures(const unsigned int Nmax, bool resize_error_bound_data=true)
Resize and clear the data vectors corresponding to the value of Nmax.
bool compute_RB_inner_product
Boolean flag to indicate whether we compute the RB_inner_product_matrix.
virtual Real get_stability_lower_bound()
Get a lower bound for the stability constant (e.g.
bool evaluate_RB_error_bound
Boolean to indicate whether we evaluate a posteriori error bounds when rb_solve is called.
std::vector< std::vector< std::vector< Number > > > Aq_Aq_representor_innerprods
virtual unsigned int get_n_basis_functions() const
Get the current number of basis functions.
std::vector< std::vector< std::vector< Number > > > Fq_Aq_representor_innerprods
Vectors storing the residual representor inner products to be used in computing the residuals online.
std::vector< std::vector< DenseVector< Number > > > RB_output_vectors
The vectors storing the RB output vectors.
Real eval_output_dual_norm(unsigned int n, const std::vector< Number > *evaluated_thetas)
Evaluate the dual norm of output n for the current parameters, or using the pre-evaluted theta values...
RBThetaExpansion & get_rb_theta_expansion()
Get a reference to the rb_theta_expansion.
virtual void clear_riesz_representors()
Clear all the Riesz representors that are used to compute the RB residual (and hence error bound).
static void assert_file_exists(const std::string &file_name)
Helper function that checks if file_name exists.
virtual void clear() override
Clear this RBEvaluation object.
std::vector< DenseVector< Number > > RB_Fq_vector
Dense vector for the RHS.
DenseVector< Number > RB_solution
The RB solution vector.
virtual void legacy_read_offline_data_from_files(const std::string &directory_name="offline_data", bool read_error_bound_data=true, const bool read_binary_data=true)
Read in the saved Offline reduced basis data to initialize the system for Online solves.
std::vector< DenseMatrix< Number > > RB_Aq_vector
Dense matrices for the RB computations.
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 set_euler_theta(const Real euler_theta_in)
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.
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.
virtual Real get_error_bound_normalization() override
std::vector< std::vector< Real > > RB_output_error_bounds_all_k
The error bounds for each RB output for all time-levels from the most recent rb_solve.
std::vector< std::vector< std::vector< std::vector< Number > > > > Aq_Mq_representor_innerprods
std::vector< std::vector< Number > > RB_outputs_all_k
The RB outputs for all time-levels from the most recent rb_solve.
virtual void clear() override
Clear this TransientRBEvaluation object.
Number cached_Fq_term
Cached residual terms.
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.
void cache_online_residual_terms(const unsigned int N)
Helper function for caching the terms in the online residual assembly that do not change in time.
DenseMatrix< Number > RB_LHS_matrix
Cached data for subsequent solves.
std::vector< Real > error_bound_all_k
The error bound data for all time-levels from the most recent rb_solve.
DenseMatrix< Number > RB_L2_matrix
Dense RB L2 matrix.
virtual void resize_data_structures(const unsigned int Nmax, bool resize_error_bound_data=true) override
Resize and clear the data vectors corresponding to the value of Nmax.
virtual Real uncached_compute_residual_dual_norm(const unsigned int N)
Compute the dual norm of the residual for the solution saved in RB_solution.
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.
bool _rb_solve_data_cached
Check that the data has been cached in case of using rb_solve_again.
TransientRBEvaluation(const Parallel::Communicator &comm_in)
Constructor.
std::vector< DenseMatrix< Number > > RB_M_q_vector
Dense matrices for the RB mass matrices.
DenseVector< Number > old_RB_solution
The RB solution at the previous time-level.
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.
virtual Real rb_solve_again()
If a solve has already been performed, then we cached some data and we can perform a new solve much m...
virtual Real residual_scaling_numer(Real alpha_LB)
Specifies the residual scaling on the numerator to be used in the a posteriori error bound.
virtual Real compute_residual_dual_norm(const unsigned int N) override
Compute the dual norm of the residual for the solution saved in RB_solution_vector.
virtual void legacy_read_offline_data_from_files(const std::string &directory_name="offline_data", bool read_error_bound_data=true, const bool read_binary_data=true) override
Read in the saved Offline reduced basis data to initialize the system for Online solves.
virtual void clear_riesz_representors() override
Clear all the Riesz representors that are used to compute the RB residual (and hence error bound).
virtual void legacy_write_offline_data_to_files(const std::string &directory_name="offline_data", const bool write_binary_data=true) override
Write out all the data to text files in order to segregate the Offline stage from the Online stage.
virtual Real rb_solve(unsigned int N) override
Perform online solve with the N RB basis functions, for the set of parameters in current_params,...
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.
This class implements a C++ interface to the XDR (eXternal Data Representation) format.
Definition xdr_cxx.h:68
void close()
Closes the file if it is open.
Definition xdr_cxx.C:278
The libMesh namespace provides an interface to certain functionality in the library.
T libmesh_real(T a)
libmesh_assert(ctx)
OStreamProxy out
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
XdrMODE
Defines an enum for read/write mode in Xdr format.
IntRange< T > make_range(T beg, T end)
The 2-parameter make_range() helper function returns an IntRange<T> when both input parameters are of...
Definition int_range.h:176
static const bool value
Definition xdr_io.C:55