ExaDG
Loading...
Searching...
No Matches
operator_base.h
1/* ______________________________________________________________________
2 *
3 * ExaDG - High-Order Discontinuous Galerkin for the Exa-Scale
4 *
5 * Copyright (C) 2021 by the ExaDG authors
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 * ______________________________________________________________________
20 */
21
22#ifndef OPERATION_BASE_H
23#define OPERATION_BASE_H
24
25// deal.II
26#include <deal.II/base/subscriptor.h>
27#include <deal.II/dofs/dof_handler.h>
28#include <deal.II/lac/affine_constraints.h>
29#include <deal.II/lac/la_parallel_vector.h>
30#include <deal.II/lac/lapack_full_matrix.h>
31#ifdef DEAL_II_WITH_TRILINOS
32# include <deal.II/lac/trilinos_sparse_matrix.h>
33#endif
34#ifdef DEAL_II_WITH_PETSC
35# include <deal.II/lac/petsc_sparse_matrix.h>
36#endif
37#include <deal.II/matrix_free/matrix_free.h>
38
39// ExaDG
40#include <exadg/matrix_free/categorization.h>
41#include <exadg/matrix_free/integrators.h>
42
43#include <exadg/solvers_and_preconditioners/preconditioners/elementwise_preconditioners.h>
44#include <exadg/solvers_and_preconditioners/preconditioners/enum_types.h>
45#include <exadg/solvers_and_preconditioners/solvers/enum_types.h>
46#include <exadg/solvers_and_preconditioners/solvers/wrapper_elementwise_solvers.h>
47#include <exadg/solvers_and_preconditioners/utilities/invert_diagonal.h>
48
49#include <exadg/utilities/lazy_ptr.h>
50
51#include <exadg/operators/elementwise_operator.h>
52#include <exadg/operators/integrator_flags.h>
53#include <exadg/operators/mapping_flags.h>
54#include <exadg/operators/operator_type.h>
55
56namespace ExaDG
57{
59{
61 : dof_index(0),
62 dof_index_inhomogeneous(dealii::numbers::invalid_unsigned_int),
63 quad_index(0),
64 operator_is_singular(false),
65 use_cell_based_loops(false),
66 implement_block_diagonal_preconditioner_matrix_free(false),
67 solver_block_diagonal(Elementwise::Solver::GMRES),
68 preconditioner_block_diagonal(Elementwise::Preconditioner::InverseMassMatrix),
69 solver_data_block_diagonal(SolverData(1000, 1.e-12, 1.e-2, 1000))
70 {
71 }
72
73 unsigned int dof_index;
74
75 // In addition to the "standard" dof_index above, we need a separate dof index to evaluate
76 // inhomogeneous boundary data correctly. This "inhomogeneous" dof index corresponds to an
77 // AffineConstraints object that only applies periodicity and hanging node constraints.
78 unsigned int dof_index_inhomogeneous;
79
80 unsigned int quad_index;
81
82 // Solution of linear systems of equations and preconditioning
83 bool operator_is_singular;
84
85 bool use_cell_based_loops;
86
87 // block Jacobi preconditioner
88 bool implement_block_diagonal_preconditioner_matrix_free;
89
90 // elementwise iterative solution of block Jacobi problems
91 Elementwise::Solver solver_block_diagonal;
92 Elementwise::Preconditioner preconditioner_block_diagonal;
93 SolverData solver_data_block_diagonal;
94};
95
96template<int dim, typename Number, int n_components = 1>
97class OperatorBase : public dealii::Subscriptor
98{
99public:
101
102 typedef dealii::LinearAlgebra::distributed::Vector<Number> VectorType;
103 typedef std::pair<unsigned int, unsigned int> Range;
104 typedef CellIntegrator<dim, n_components, Number> IntegratorCell;
105 typedef FaceIntegrator<dim, n_components, Number> IntegratorFace;
106
107 static unsigned int const vectorization_length = dealii::VectorizedArray<Number>::size();
108
109 typedef dealii::LAPACKFullMatrix<Number> LAPACKMatrix;
110
111 typedef dealii::FullMatrix<dealii::TrilinosScalar> FullMatrix_;
112
113 OperatorBase();
114
115 virtual ~OperatorBase()
116 {
117 }
118
119 /*
120 * Getters and setters.
121 */
122 void
123 set_time(double const time) const;
124
125 double
126 get_time() const;
127
128 unsigned int
129 get_level() const;
130
131 dealii::AffineConstraints<Number> const &
132 get_affine_constraints() const;
133
134 dealii::MatrixFree<dim, Number> const &
135 get_matrix_free() const;
136
137 unsigned int
138 get_dof_index() const;
139
140 unsigned int
141 get_quad_index() const;
142
143 /*
144 * Returns whether the operator is singular, e.g., the Laplace operator with pure Neumann boundary
145 * conditions is singular.
146 */
147 bool
148 operator_is_singular() const;
149
150 void
151 vmult(VectorType & dst, VectorType const & src) const;
152
153 void
154 vmult_add(VectorType & dst, VectorType const & src) const;
155
156 void
157 vmult_interface_down(VectorType & dst, VectorType const & src) const;
158
159 void
160 vmult_add_interface_up(VectorType & dst, VectorType const & src) const;
161
162 dealii::types::global_dof_index
163 m() const;
164
165 dealii::types::global_dof_index
166 n() const;
167
168 Number
169 el(unsigned int const, unsigned int const) const;
170
171 bool
172 is_empty_locally() const;
173
174 void
175 initialize_dof_vector(VectorType & vector) const;
176
177 /*
178 * For time-dependent problems, the function set_time() needs to be called prior to the present
179 * function.
180 */
181 virtual void
182 set_inhomogeneous_boundary_values(VectorType & solution) const;
183
184 void
185 set_constrained_dofs_to_zero(VectorType & vector) const;
186
187 void
188 calculate_inverse_diagonal(VectorType & diagonal) const;
189
190 /*
191 * Initialize block diagonal preconditioner: initialize everything related to block diagonal
192 * preconditioner.
193 */
194 void
195 initialize_block_diagonal_preconditioner(bool const initialize) const;
196
197 /*
198 * Update block diagonal preconditioner: Recompute block matrices in case of matrix-based
199 * implementation.
200 */
201 void
202 update_block_diagonal_preconditioner() const;
203
208 void
209 apply_inverse_block_diagonal(VectorType & dst, VectorType const & src) const;
210
211 /*
212 * Algebraic multigrid (AMG): sparse matrix (Trilinos) methods
213 */
214#ifdef DEAL_II_WITH_TRILINOS
215 void
216 init_system_matrix(dealii::TrilinosWrappers::SparseMatrix & system_matrix,
217 MPI_Comm const & mpi_comm) const;
218
219 void
220 calculate_system_matrix(dealii::TrilinosWrappers::SparseMatrix & system_matrix) const;
221#endif
222
223 /*
224 * Algebraic multigrid (AMG): sparse matrix (PETSc) methods
225 */
226#ifdef DEAL_II_WITH_PETSC
227 void
228 init_system_matrix(dealii::PETScWrappers::MPI::SparseMatrix & system_matrix,
229 MPI_Comm const & mpi_comm) const;
230
231 void
232 calculate_system_matrix(dealii::PETScWrappers::MPI::SparseMatrix & system_matrix) const;
233#endif
234
235 /*
236 * Evaluate the homogeneous part of an operator. The homogeneous operator is the operator that is
237 * obtained for homogeneous boundary conditions. This operation is typically applied in linear
238 * iterative solvers (as well as multigrid preconditioners and smoothers). Operations of this type
239 * are called apply_...() and vmult_...() as required by deal.II interfaces.
240 */
241 void
242 apply(VectorType & dst, VectorType const & src) const;
243
244 /*
245 * See function apply() for a description.
246 */
247 void
248 apply_add(VectorType & dst, VectorType const & src) const;
249
250 /*
251 * evaluate inhomogeneous parts of operator related to inhomogeneous boundary face integrals.
252 * Operations of this type are called rhs_...() since these functions are called to calculate the
253 * vector forming the right-hand side vector of linear systems of equations. Functions of type
254 * rhs only make sense for linear operators (but they have e.g. no meaning for linearized
255 * operators of nonlinear problems). For this reason, these functions are currently defined
256 * 'virtual' to provide the opportunity to override and assert these functions in derived classes.
257 *
258 * For continuous Galerkin discretizations, this function calls internally the member function
259 * set_inhomogeneous_boundary_values(). Hence, prior to calling this function, one needs to call
260 * set_time() for a correct evaluation in case of time-dependent problems.
261 *
262 * This function sets the dst vector to zero, and afterwards calls rhs_add().
263 */
264 virtual void
265 rhs(VectorType & dst) const;
266
267 /*
268 * See function rhs() for a description.
269 */
270 virtual void
271 rhs_add(VectorType & dst) const;
272
273 /*
274 * Evaluate the operator including homogeneous and inhomogeneous contributions. The typical use
275 * case would be explicit time integration where a splitting into homogeneous and inhomogeneous
276 * contributions is not required. Functions of type evaluate only make sense for linear operators
277 * (but they have e.g. no meaning for linearized operators of nonlinear problems). For this
278 * reason, these functions are currently defined 'virtual' to provide the opportunity to override
279 * and assert these functions in derived classes.
280 *
281 * Unlike the function rhs(), this function does not internally call the function
282 * set_inhomogeneous_boundary_values() prior to evaluation. Hence, one needs to explicitly call
283 * the function set_inhomogeneous_boundary_values() in case of continuous Galerkin discretizations
284 * with inhomogeneous Dirichlet boundary conditions before calling the present function.
285 */
286 virtual void
287 evaluate(VectorType & dst, VectorType const & src) const;
288
289 /*
290 * See function evaluate() for a description.
291 */
292 virtual void
293 evaluate_add(VectorType & dst, VectorType const & src) const;
294
295 /*
296 * point Jacobi preconditioner (diagonal)
297 */
298 void
299 calculate_diagonal(VectorType & diagonal) const;
300
301 void
302 add_diagonal(VectorType & diagonal) const;
303
304 /*
305 * block Jacobi preconditioner (block-diagonal)
306 */
307 void
308 add_block_diagonal_matrices(std::vector<LAPACKMatrix> & matrices) const;
309
310 void
311 apply_inverse_block_diagonal_matrix_based(VectorType & dst, VectorType const & src) const;
312
313 // matrix-free implementation
314
315 // This function has to initialize everything related to the block diagonal preconditioner when
316 // using the matrix-free variant with elementwise iterative solvers and matrix-free operator
317 // evaluation.
318 void
319 initialize_block_diagonal_preconditioner_matrix_free(bool const initialize) const;
320
321 // updates block diagonal preconditioner when using the matrix-free variant with elementwise
322 // iterative solvers and matrix-free operator evaluation.
323 void
324 update_block_diagonal_preconditioner_matrix_free() const;
325
326 // initializes block diagonal preconditioner for matrix-based variant
327 void
328 initialize_block_diagonal_preconditioner_matrix_based(bool const initialize) const;
329
330 // updates block diagonal preconditioner for matrix-based variant
331 void
332 update_block_diagonal_preconditioner_matrix_based() const;
333
334 void
335 apply_add_block_diagonal_elementwise(unsigned int const cell,
336 dealii::VectorizedArray<Number> * const dst,
337 dealii::VectorizedArray<Number> const * const src,
338 unsigned int const problem_size) const;
339
340 /*
341 * additive Schwarz preconditioner (cellwise block-diagonal)
342 */
343 virtual void
344 compute_factorized_additive_schwarz_matrices() const;
345
346 void
347 apply_inverse_additive_schwarz_matrices(VectorType & dst, VectorType const & src) const;
348
349protected:
350 void
351 reinit(dealii::MatrixFree<dim, Number> const & matrix_free,
352 dealii::AffineConstraints<Number> const & constraints,
353 OperatorBaseData const & data);
354
355 void
356 reinit_cell(IntegratorCell & integrator, unsigned int const cell) const;
357
358 void
359 reinit_face(IntegratorFace & integrator_m,
360 IntegratorFace & integrator_p,
361 unsigned int const face) const;
362
363 void
364 reinit_boundary_face(IntegratorFace & integrator_m, unsigned int const face) const;
365
366 void
367 reinit_face_cell_based(IntegratorFace & integrator_m,
368 IntegratorFace & integrator_p,
369 unsigned int const cell,
370 unsigned int const face,
371 dealii::types::boundary_id const boundary_id) const;
372
373 /*
374 * These methods have to be overwritten by derived classes because these functions are
375 * operator-specific and define how the operator looks like.
376 */
377
378 // standard integration procedure with separate loops for cell and face integrals
379 virtual void
380 do_cell_integral(IntegratorCell & integrator) const;
381
382 virtual void
383 do_face_integral(IntegratorFace & integrator_m, IntegratorFace & integrator_p) const;
384
385 virtual void
386 do_boundary_integral(IntegratorFace & integrator,
387 OperatorType const & operator_type,
388 dealii::types::boundary_id const & boundary_id) const;
389
390 virtual void
391 do_boundary_integral_continuous(IntegratorFace & integrator,
392 dealii::types::boundary_id const & boundary_id) const;
393
394 // The computation of the diagonal and block-diagonal requires face integrals of type
395 // interior (int) and exterior (ext)
396 virtual void
397 do_face_int_integral(IntegratorFace & integrator_m, IntegratorFace & integrator_p) const;
398
399 virtual void
400 do_face_ext_integral(IntegratorFace & integrator_m, IntegratorFace & integrator_p) const;
401
402 // This function is currently only needed due to limitations of deal.II which do
403 // currently not allow to access neighboring data in case of cell-based face loops.
404 // Once this functionality is available, this function should be removed again.
405 // Since only special operators need to evaluate neighboring data, this function
406 // simply redirects to do_face_int_integral() if this function is not overwritten
407 // by a derived class (such as convective terms that require an additional
408 // evaluation of velocity fields for example).
409 virtual void
410 do_face_int_integral_cell_based(IntegratorFace & integrator_m,
411 IntegratorFace & integrator_p) const;
412
413 /*
414 * Matrix-free object.
415 */
417
418 /*
419 * Physical time (required for time-dependent problems).
420 */
421 mutable double time;
422
423 /*
424 * Constraint matrix.
425 */
427
428 mutable dealii::AffineConstraints<double> constraint_double;
429
430 /*
431 * Cell and face integrator flags.
432 */
433 IntegratorFlags integrator_flags;
434
435private:
436 /*
437 * Is the operator used as a multigrid level operator?
438 */
439 bool is_mg;
440
441protected:
442 /*
443 * Is the discretization based on discontinuous Galerkin method?
444 */
445 bool is_dg;
446
447 /*
448 * Block Jacobi preconditioner/smoother: matrix-free version with elementwise iterative solver
449 */
453 typedef Elementwise::
454 IterativeSolver<dim, n_components, Number, ELEMENTWISE_OPERATOR, ELEMENTWISE_PRECONDITIONER>
456
457 mutable std::shared_ptr<ELEMENTWISE_OPERATOR> elementwise_operator;
458 mutable std::shared_ptr<ELEMENTWISE_PRECONDITIONER> elementwise_preconditioner;
459 mutable std::shared_ptr<ELEMENTWISE_SOLVER> elementwise_solver;
460
461private:
462 virtual void
463 reinit_cell_derived(IntegratorCell & integrator, unsigned int const cell) const;
464
465 virtual void
466 reinit_face_derived(IntegratorFace & integrator_m,
467 IntegratorFace & integrator_p,
468 unsigned int const face) const;
469
470 virtual void
471 reinit_boundary_face_derived(IntegratorFace & integrator_m, unsigned int const face) const;
472
473 virtual void
474 reinit_face_cell_based_derived(IntegratorFace & integrator_m,
475 IntegratorFace & integrator_p,
476 unsigned int const cell,
477 unsigned int const face,
478 dealii::types::boundary_id const boundary_id) const;
479
480 /*
481 * Helper functions:
482 *
483 * The diagonal, block-diagonal, as well as the system matrix (assembled into a sparse matrix) are
484 * computed columnwise. This means that column i of the block-matrix is computed by evaluating the
485 * operator for a unit vector which takes a value of 1 in row i and is 0 for all other entries.
486 */
487 void
488 create_standard_basis(unsigned int j, IntegratorCell & integrator) const;
489
490 void
491 create_standard_basis(unsigned int j, IntegratorFace & integrator) const;
492
493 void
494 create_standard_basis(unsigned int j,
495 IntegratorFace & integrator_1,
496 IntegratorFace & integrator_2) const;
497
498 /*
499 * This function calculates cell integrals for the full (= homogeneous + inhomogeneous) part,
500 * where inhomogeneous part may occur for continuous Galerkin discretizations due to inhomogeneous
501 * Dirichlet BCs. A prerequisite to call this function is to set inhomogeneous Dirichlet degrees
502 * of freedom appropriately in the DoF-vector src. In case the DoF-vector src is zero apart from
503 * the inhomogeneous Dirichlet degrees of freedom, this function calculates only the inhomogeneous
504 * part of the operator, because the homogeneous operator is zero in this case. For DG
505 * discretizations, this function is equivalent to cell_loop().
506 */
507 void
508 cell_loop_full_operator(dealii::MatrixFree<dim, Number> const & matrix_free,
509 VectorType & dst,
510 VectorType const & src,
511 Range const & range) const;
512
513 /*
514 * This function loops over all cells and calculates cell integrals.
515 */
516 void
517 cell_loop(dealii::MatrixFree<dim, Number> const & matrix_free,
518 VectorType & dst,
519 VectorType const & src,
520 Range const & range) const;
521
522 /*
523 * This function loops over all interior faces and calculates face integrals.
524 */
525 void
526 face_loop(dealii::MatrixFree<dim, Number> const & matrix_free,
527 VectorType & dst,
528 VectorType const & src,
529 Range const & range) const;
530
531 /*
532 * The following functions loop over all boundary faces and calculate boundary face integrals.
533 * Depending on the operator type, we distinguish between boundary face integrals of type
534 * homogeneous, inhomogeneous, and full.
535 */
536
537 // homogeneous operator
538 void
539 boundary_face_loop_hom_operator(dealii::MatrixFree<dim, Number> const & matrix_free,
540 VectorType & dst,
541 VectorType const & src,
542 Range const & range) const;
543
544 // inhomogeneous operator
545 void
546 boundary_face_loop_inhom_operator(dealii::MatrixFree<dim, Number> const & matrix_free,
547 VectorType & dst,
548 VectorType const & src,
549 Range const & range) const;
550
551 // full operator
552 void
553 boundary_face_loop_full_operator(dealii::MatrixFree<dim, Number> const & matrix_free,
554 VectorType & dst,
555 VectorType const & src,
556 Range const & range) const;
557
558 /*
559 * inhomogeneous operator: For the inhomogeneous operator, we only have to calculate boundary face
560 * integrals. The matrix-free implementation, however, does not offer interfaces for boundary face
561 * integrals only. Hence we have to provide empty functions for cell and interior face integrals.
562 */
563 void
564 cell_loop_empty(dealii::MatrixFree<dim, Number> const & matrix_free,
565 VectorType & dst,
566 VectorType const & src,
567 Range const & range) const;
568
569 void
570 face_loop_empty(dealii::MatrixFree<dim, Number> const & matrix_free,
571 VectorType & dst,
572 VectorType const & src,
573 Range const & range) const;
574
575 /*
576 * Calculate diagonal.
577 */
578 void
579 cell_loop_diagonal(dealii::MatrixFree<dim, Number> const & matrix_free,
580 VectorType & dst,
581 VectorType const & src,
582 Range const & range) const;
583
584 void
585 face_loop_diagonal(dealii::MatrixFree<dim, Number> const & matrix_free,
586 VectorType & dst,
587 VectorType const & src,
588 Range const & range) const;
589
590 void
591 boundary_face_loop_diagonal(dealii::MatrixFree<dim, Number> const & matrix_free,
592 VectorType & dst,
593 VectorType const & src,
594 Range const & range) const;
595
596 void
597 cell_based_loop_diagonal(dealii::MatrixFree<dim, Number> const & matrix_free,
598 VectorType & dst,
599 VectorType const & src,
600 Range const & range) const;
601
602 /*
603 * Calculate (assemble) block diagonal.
604 */
605 void
606 cell_loop_block_diagonal(dealii::MatrixFree<dim, Number> const & matrix_free,
607 std::vector<LAPACKMatrix> & matrices,
608 std::vector<LAPACKMatrix> const & src,
609 Range const & range) const;
610
611 void
612 face_loop_block_diagonal(dealii::MatrixFree<dim, Number> const & matrix_free,
613 std::vector<LAPACKMatrix> & matrices,
614 std::vector<LAPACKMatrix> const & src,
615 Range const & range) const;
616
617 void
618 boundary_face_loop_block_diagonal(dealii::MatrixFree<dim, Number> const & matrix_free,
619 std::vector<LAPACKMatrix> & matrices,
620 std::vector<LAPACKMatrix> const & src,
621 Range const & range) const;
622
623 // cell-based variant for computation of both cell and face integrals
624 void
625 cell_based_loop_block_diagonal(dealii::MatrixFree<dim, Number> const & matrix_free,
626 std::vector<LAPACKMatrix> & matrices,
627 std::vector<LAPACKMatrix> const & src,
628 Range const & range) const;
629
630 /*
631 * Apply inverse block diagonal:
632 *
633 * we compute dst = B^{-1} * src
634 */
635 void
636 cell_loop_apply_inverse_block_diagonal_matrix_based(
637 dealii::MatrixFree<dim, Number> const & matrix_free,
638 VectorType & dst,
639 VectorType const & src,
640 Range const & range) const;
641
642 /*
643 * Set up sparse matrix internally for templated matrix type (Trilinos or
644 * PETSc matrices)
645 */
646 template<typename SparseMatrix>
647 void
648 internal_init_system_matrix(SparseMatrix & system_matrix,
649 dealii::DynamicSparsityPattern & dsp,
650 MPI_Comm const & mpi_comm) const;
651
652 template<typename SparseMatrix>
653 void
654 internal_calculate_system_matrix(SparseMatrix & system_matrix) const;
655
656 /*
657 * Calculate sparse matrix.
658 */
659 template<typename SparseMatrix>
660 void
661 cell_loop_calculate_system_matrix(dealii::MatrixFree<dim, Number> const & matrix_free,
662 SparseMatrix & dst,
663 SparseMatrix const & src,
664 Range const & range) const;
665
666 template<typename SparseMatrix>
667 void
668 face_loop_calculate_system_matrix(dealii::MatrixFree<dim, Number> const & matrix_free,
669 SparseMatrix & dst,
670 SparseMatrix const & src,
671 Range const & range) const;
672
673 template<typename SparseMatrix>
674 void
675 boundary_face_loop_calculate_system_matrix(dealii::MatrixFree<dim, Number> const & matrix_free,
676 SparseMatrix & dst,
677 SparseMatrix const & src,
678 Range const & range) const;
679
680 /*
681 * This function sets entries of the DoF-vector corresponding to constraint DoFs to one.
682 */
683 void
684 set_constrained_dofs_to_one(VectorType & vector) const;
685
686 /*
687 * Do we have to evaluate (boundary) face integrals for this operator? For example, operators
688 * such as the mass operator only involve cell integrals.
689 */
690 bool
691 evaluate_face_integrals() const;
692
693 /*
694 * Compute factorized additive Schwarz matrices.
695 */
696 template<typename SparseMatrix>
697 void
698 internal_compute_factorized_additive_schwarz_matrices() const;
699
700 /*
701 * Data structure containing all operator-specific data.
702 */
703 OperatorBaseData data;
704
705 /*
706 * Multigrid level: 0 <= level <= max_level. If the operator is not used as a multigrid
707 * level operator, this variable takes a value of dealii::numbers::invalid_unsigned_int.
708 */
709 unsigned int level;
710
711 /*
712 * Vector of matrices for block-diagonal preconditioners.
713 */
714 mutable std::vector<LAPACKMatrix> matrices;
715
716 /*
717 * Vector with weights for additive Schwarz preconditioner.
718 */
719 mutable VectorType weights;
720
721 unsigned int n_mpi_processes;
722};
723} // namespace ExaDG
724
725#endif
Definition wrapper_elementwise_solvers.h:61
Definition elementwise_operator.h:33
Definition elementwise_preconditioners.h:41
Definition operator_base.h:98
void apply_inverse_block_diagonal(VectorType &dst, VectorType const &src) const
Definition operator_base.cpp:500
Definition lazy_ptr.h:29
Definition driver.cpp:33
Definition integrator_flags.h:30
Definition operator_base.h:59
Definition solver_data.h:34