Reduced Lagrange Multipliers
 
Loading...
Searching...
No Matches
augmented_lagrangian_preconditioner.h
Go to the documentation of this file.
2
4
6
11#include <deal.II/lac/vector.h>
12
13#ifdef DEAL_II_WITH_TRILINOS
16
17# include <EpetraExt_MatrixMatrix.h>
18# include <Epetra_Comm.h>
19# include <Epetra_CrsMatrix.h>
20# include <Epetra_Map.h>
21# include <Epetra_RowMatrixTransposer.h>
22#endif
23
24
25#ifndef augmented_lagrangian_prec_h
26# define augmented_lagrangian_prec_h
27
28using namespace dealii;
29
30namespace UtilitiesAL
31{
32
33 template <typename VectorType,
34 typename BlockVectorType = TrilinosWrappers::MPI::BlockVector>
36 {
37 public:
39 const LinearOperator<VectorType> Aug_inv_,
43 const double gamma_ = 1e1)
44 {
45 static_assert(
46 std::is_same<VectorType, TrilinosWrappers::MPI::Vector>::value == true);
47 Aug_inv = Aug_inv_;
48 C = C_;
49 Ct = Ct_;
50 invW = invW_;
51 gamma = gamma_;
52 }
53
54 void
55 vmult(BlockVectorType &v, const BlockVectorType &u) const
56 {
57 v.block(0) = 0.;
58 v.block(1) = 0.;
59
60 v.block(1) = -gamma * invW * u.block(1);
61 v.block(0) = Aug_inv * (u.block(0) - Ct * v.block(1));
62 }
63
64 private:
70 double gamma;
71 };
72
73 template <typename MatrixType = SparseMatrix<double>,
74 typename VectorType = Vector<typename MatrixType::value_type>,
75 typename PreconditionerType = TrilinosWrappers::PreconditionAMG>
76 void
77 create_augmented_block(const MatrixType &A,
78 const MatrixType &Ct,
79 const VectorType &scaling_vector,
80 const double gamma,
81 MatrixType &augmented_matrix)
82 {
83# ifdef DEAL_II_WITH_TRILINOS
84
85
86 if constexpr (std::is_same_v<TrilinosWrappers::SparseMatrix, MatrixType>)
87 {
88 Assert((std::is_same_v<TrilinosWrappers::MPI::Vector, VectorType>),
89 ExcMessage("You must use Trilinos vectors, as you are using "
90 "Trilinos matrices."));
91
92
93 Epetra_CrsMatrix A_trilinos = A.trilinos_matrix();
94 Epetra_CrsMatrix Ct_trilinos = Ct.trilinos_matrix();
95 auto multi_vector = scaling_vector.trilinos_vector();
96
97
98 Assert((A_trilinos.NumGlobalRows() !=
99 Ct_trilinos.DomainMap().NumGlobalElements()),
100 ExcMessage("Number of columns in C must match dimension of A"));
101
102
103 // Ensure the MultiVector has only one column.
104 Assert((multi_vector.NumVectors() == 1),
105 ExcMessage("The MultiVector must have exactly one column."));
106
107
108 // Create diagonal matrix from first vector of v
109 // Explicitly cast the map to Epetra_Map
110 const Epetra_Map &map =
111 static_cast<const Epetra_Map &>(multi_vector.Map());
112
113
114 // Create a diagonal matrix with 1 nonzero entry per row
115 Epetra_CrsMatrix diag_matrix(Copy, map, 1);
116 for (int i = 0; i < multi_vector.Map().NumMyElements(); ++i)
117 {
118 int global_row = multi_vector.Map().GID(i);
119 double val = multi_vector[0][i]; // Access first vector
120 diag_matrix.InsertGlobalValues(global_row, 1, &val, &global_row);
121 }
122 diag_matrix.FillComplete();
123
124
125 Epetra_CrsMatrix *W =
126 new Epetra_CrsMatrix(Copy, Ct_trilinos.RowMap(), 0);
127 EpetraExt::MatrixMatrix::Multiply(
128 Ct_trilinos, false, diag_matrix, false, *W);
129
130
131 // Compute Ct^T * W, which is equivalent to (C^T * diag(V)) * C
132 Epetra_CrsMatrix *CtT_W = new Epetra_CrsMatrix(Copy, W->RangeMap(), 0);
133 EpetraExt::MatrixMatrix::Multiply(
134 *W, false /* transpose */, Ct_trilinos, true, *CtT_W);
135
136
137 // Add A to the result, scaling with gamma
138 Epetra_CrsMatrix *result =
139 new Epetra_CrsMatrix(Copy,
140 A_trilinos.RowMap(),
141 A_trilinos.MaxNumEntries());
142 EpetraExt::MatrixMatrix::Add(
143 A_trilinos, false, 1.0, *CtT_W, false, gamma, result);
144 result->FillComplete();
145
146
147 // Initialize the final Trilinos matrix
148 augmented_matrix.reinit(*result, true /*copy_values*/);
149
150
151 // Delete unnecessary objects.
152 delete W;
153 delete CtT_W;
154 delete result;
155 }
156 else
157 {
158 // PETSc not supported so far.
159 AssertThrow(false, ExcNotImplemented("Matrix type not supported!"));
160 }
161# else
163 false,
164 ExcMessage(
165 "This function requires deal.II to be configured with Trilinos."));
166
167
168 (void)velocity_dh;
169 (void)C;
170 (void)Ct;
171 (void)scaling_vector;
172 (void)velocity_constraints;
173 (void)gamma;
174 (void)augmented_matrix;
175# endif
176 }
177
178
184 template <int spacedim, typename VectorType>
185 void
186 set_null_space(Teuchos::ParameterList &parameter_list,
187 std::unique_ptr<Epetra_MultiVector> &ptr_distributed_modes,
188 const Epetra_RowMatrix &matrix,
189 const std::vector<VectorType> &modes)
190 {
191 static_assert((spacedim == 2 || spacedim == 3),
192 "This function only works for 2D and 3D.");
193
194# ifdef DEAL_II_WITH_TRILINOS
195
196
197 using size_type = TrilinosWrappers::PreconditionAMG::size_type;
198 const Epetra_Map &domain_map = matrix.OperatorDomainMap();
199 constexpr size_type modes_dimension = spacedim == 3 ? 6 : 3;
200
201 ptr_distributed_modes.reset(
202 new Epetra_MultiVector(domain_map, modes_dimension));
203 Assert(ptr_distributed_modes, ExcNotInitialized());
204 Epetra_MultiVector &distributed_modes = *ptr_distributed_modes;
205
206 const size_type global_size = TrilinosWrappers::n_global_rows(matrix);
207
208 Assert(global_size == static_cast<size_type>(
209 TrilinosWrappers::global_length(distributed_modes)),
210 ExcDimensionMismatch(
211 global_size, TrilinosWrappers::global_length(distributed_modes)));
212
213 const size_type my_size = domain_map.NumMyElements();
214
215 // Reshape null space as a contiguous vector of doubles so that
216 // Trilinos can read from it.
217 [[maybe_unused]] const size_type expected_mode_size = global_size;
218 for (size_type d = 0; d < modes_dimension; ++d)
219 {
220 Assert(modes[d].size() == expected_mode_size,
221 ExcDimensionMismatch(modes[d].size(), expected_mode_size));
222 for (size_type row = 0; row < my_size; ++row)
223 {
224 const TrilinosWrappers::types::int_type mode_index =
225 TrilinosWrappers::global_index(domain_map, row);
226 distributed_modes[d][row] =
227 static_cast<double>(modes[d][mode_index]);
228 }
229 }
230
231 parameter_list.set("null space: type", "pre-computed");
232 parameter_list.set("null space: dimension", distributed_modes.NumVectors());
233 parameter_list.set("null space: vectors", distributed_modes.Values());
234
235
236# else
238 false,
239 ExcMessage(
240 "This function requires deal.II to be configured with Trilinos."));
241
242# endif
243 }
244
245} // namespace UtilitiesAL
246
247#endif
void vmult(BlockVectorType &v, const BlockVectorType &u) const
BlockPreconditionerAugmentedLagrangian(const LinearOperator< VectorType > Aug_inv_, const LinearOperator< VectorType > C_, const LinearOperator< VectorType > Ct_, const LinearOperator< VectorType > invW_, const double gamma_=1e1)
#define Assert(cond, exc)
#define AssertThrow(cond, exc)
std::size_t size
SymmetricTensor< 2, dim, Number > C(const Tensor< 2, dim, Number > &F)
SymmetricTensor< 2, dim, Number > d(const Tensor< 2, dim, Number > &F, const Tensor< 2, dim, Number > &dF_dt)
TrilinosWrappers::types::int_type global_index(const Epetra_BlockMap &map, const ::types::global_dof_index i)
TrilinosWrappers::types::int_type n_global_rows(const Epetra_CrsGraph &graph)
TrilinosWrappers::types::int_type global_length(const Epetra_MultiVector &vector)
void create_augmented_block(const MatrixType &A, const MatrixType &Ct, const VectorType &scaling_vector, const double gamma, MatrixType &augmented_matrix)
void set_null_space(Teuchos::ParameterList &parameter_list, std::unique_ptr< Epetra_MultiVector > &ptr_distributed_modes, const Epetra_RowMatrix &matrix, const std::vector< VectorType > &modes)
Set the null space of the matrix using a pre-computed set of vectors. Needed for the AMG precondition...