MFEM v4.7.0
Finite element discretization library
Loading...
Searching...
No Matches
blockoperator.cpp
Go to the documentation of this file.
1// Copyright (c) 2010-2024, Lawrence Livermore National Security, LLC. Produced
2// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
3// LICENSE and NOTICE for details. LLNL-CODE-806117.
4//
5// This file is part of the MFEM library. For more information and source code
6// availability visit https://mfem.org.
7//
8// MFEM is free software; you can redistribute it and/or modify it under the
9// terms of the BSD-3 license. We welcome feedback and contributions, see file
10// CONTRIBUTING.md for details.
11
12
13#include "../general/array.hpp"
14#include "operator.hpp"
15#include "blockvector.hpp"
16#include "blockoperator.hpp"
17
18namespace mfem
19{
20
22 : Operator(offsets.Last()),
23 owns_blocks(0),
24 nRowBlocks(offsets.Size() - 1),
25 nColBlocks(offsets.Size() - 1),
26 row_offsets(offsets),
27 col_offsets(offsets),
28 op(nRowBlocks, nRowBlocks),
29 coef(nRowBlocks, nColBlocks)
30{
31 op = static_cast<Operator *>(NULL);
32}
33
35 const Array<int> & col_offsets_)
36 : Operator(row_offsets_.Last(), col_offsets_.Last()),
37 owns_blocks(0),
38 nRowBlocks(row_offsets_.Size()-1),
39 nColBlocks(col_offsets_.Size()-1),
40 row_offsets(row_offsets_),
41 col_offsets(col_offsets_),
42 op(nRowBlocks, nColBlocks),
43 coef(nRowBlocks, nColBlocks)
44{
45 op = static_cast<Operator *>(NULL);
46}
47
49{
50 SetBlock(iblock, iblock, opt, c);
51}
52
53void BlockOperator::SetBlock(int iRow, int iCol, Operator *opt, real_t c)
54{
55 if (owns_blocks && op(iRow, iCol))
56 {
57 delete op(iRow, iCol);
58 }
59 op(iRow, iCol) = opt;
60 coef(iRow, iCol) = c;
61
62 MFEM_VERIFY(row_offsets[iRow+1] - row_offsets[iRow] == opt->NumRows() &&
63 col_offsets[iCol+1] - col_offsets[iCol] == opt->NumCols(),
64 "incompatible Operator dimensions");
65}
66
67// Operator application
68void BlockOperator::Mult (const Vector & x, Vector & y) const
69{
70 MFEM_ASSERT(x.Size() == width, "incorrect input Vector size");
71 MFEM_ASSERT(y.Size() == height, "incorrect output Vector size");
72
73 x.Read();
74 y.Write(); y = 0.0;
75
76 xblock.Update(const_cast<Vector&>(x),col_offsets);
77 yblock.Update(y,row_offsets);
78
79 for (int iRow=0; iRow < nRowBlocks; ++iRow)
80 {
81 tmp.SetSize(row_offsets[iRow+1] - row_offsets[iRow]);
82 for (int jCol=0; jCol < nColBlocks; ++jCol)
83 {
84 if (op(iRow,jCol) && coef(iRow,jCol) != 0.)
85 {
86 op(iRow,jCol)->Mult(xblock.GetBlock(jCol), tmp);
87 yblock.GetBlock(iRow).Add(coef(iRow,jCol), tmp);
88 }
89 }
90 }
91
92 for (int iRow=0; iRow < nRowBlocks; ++iRow)
93 {
94 yblock.GetBlock(iRow).SyncAliasMemory(y);
95 }
96}
97
98// Action of the transpose operator
99void BlockOperator::MultTranspose (const Vector & x, Vector & y) const
100{
101 MFEM_ASSERT(x.Size() == height, "incorrect input Vector size");
102 MFEM_ASSERT(y.Size() == width, "incorrect output Vector size");
103
104 x.Read();
105 y.Write(); y = 0.0;
106
107 xblock.Update(const_cast<Vector&>(x),row_offsets);
108 yblock.Update(y,col_offsets);
109
110 for (int iRow=0; iRow < nColBlocks; ++iRow)
111 {
112 tmp.SetSize(col_offsets[iRow+1] - col_offsets[iRow]);
113 for (int jCol=0; jCol < nRowBlocks; ++jCol)
114 {
115 if (op(jCol,iRow) && coef(jCol,iRow) != 0.)
116 {
117 op(jCol,iRow)->MultTranspose(xblock.GetBlock(jCol), tmp);
118 yblock.GetBlock(iRow).Add(coef(jCol,iRow), tmp);
119 }
120 }
121 }
122
123 for (int iRow=0; iRow < nColBlocks; ++iRow)
124 {
125 yblock.GetBlock(iRow).SyncAliasMemory(y);
126 }
127}
128
130{
131 if (owns_blocks)
132 {
133 for (int iRow=0; iRow < nRowBlocks; ++iRow)
134 {
135 for (int jCol=0; jCol < nColBlocks; ++jCol)
136 {
137 delete op(iRow,jCol);
138 }
139 }
140 }
141}
142
143//-----------------------------------------------------------------------
145 const Array<int> & offsets_):
146 Solver(offsets_.Last()),
147 owns_blocks(0),
148 nBlocks(offsets_.Size() - 1),
149 offsets(0),
150 ops(nBlocks)
151{
152 ops = static_cast<Operator *>(NULL);
153 offsets.MakeRef(offsets_);
154}
155
157{
158 MFEM_VERIFY(offsets[iblock+1] - offsets[iblock] == op->Height() &&
159 offsets[iblock+1] - offsets[iblock] == op->Width(),
160 "incompatible Operator dimensions");
161
162 if (owns_blocks && ops[iblock])
163 {
164 delete ops[iblock];
165 }
166 ops[iblock] = op;
167}
168
169// Operator application
171{
172 MFEM_ASSERT(x.Size() == width, "incorrect input Vector size");
173 MFEM_ASSERT(y.Size() == height, "incorrect output Vector size");
174
175 x.Read();
176 y.Write(); y = 0.0;
177
178 xblock.Update(const_cast<Vector&>(x),offsets);
179 yblock.Update(y,offsets);
180
181 for (int i=0; i<nBlocks; ++i)
182 {
183 if (ops[i])
184 {
185 ops[i]->Mult(xblock.GetBlock(i), yblock.GetBlock(i));
186 }
187 else
188 {
189 yblock.GetBlock(i) = xblock.GetBlock(i);
190 }
191 }
192
193 for (int i=0; i<nBlocks; ++i)
194 {
195 yblock.GetBlock(i).SyncAliasMemory(y);
196 }
197}
198
199// Action of the transpose operator
201 Vector & y) const
202{
203 MFEM_ASSERT(x.Size() == height, "incorrect input Vector size");
204 MFEM_ASSERT(y.Size() == width, "incorrect output Vector size");
205
206 x.Read();
207 y.Write(); y = 0.0;
208
209 xblock.Update(const_cast<Vector&>(x),offsets);
210 yblock.Update(y,offsets);
211
212 for (int i=0; i<nBlocks; ++i)
213 {
214 if (ops[i])
215 {
216 (ops[i])->MultTranspose(xblock.GetBlock(i), yblock.GetBlock(i));
217 }
218 else
219 {
220 yblock.GetBlock(i) = xblock.GetBlock(i);
221 }
222 }
223
224 for (int i=0; i<nBlocks; ++i)
225 {
226 yblock.GetBlock(i).SyncAliasMemory(y);
227 }
228}
229
231{
232 if (owns_blocks)
233 {
234 for (int i=0; i<nBlocks; ++i)
235 {
236 delete ops[i];
237 }
238 }
239}
240
242 const Array<int> & offsets_)
243 : Solver(offsets_.Last()),
244 owns_blocks(0),
245 nBlocks(offsets_.Size() - 1),
246 offsets(0),
247 ops(nBlocks, nBlocks)
248{
249 ops = static_cast<Operator *>(NULL);
250 offsets.MakeRef(offsets_);
251}
252
254 Operator *op)
255{
256 MFEM_VERIFY(offsets[iblock+1] - offsets[iblock] == op->Height() &&
257 offsets[iblock+1] - offsets[iblock] == op->Width(),
258 "incompatible Operator dimensions");
259
260 SetBlock(iblock, iblock, op);
261}
262
264 Operator *op)
265{
266 MFEM_VERIFY(iRow >= iCol,"cannot set block in upper triangle");
267 MFEM_VERIFY(offsets[iRow+1] - offsets[iRow] == op->NumRows() &&
268 offsets[iCol+1] - offsets[iCol] == op->NumCols(),
269 "incompatible Operator dimensions");
270
271 ops(iRow, iCol) = op;
272}
273
274// Operator application
276 Vector & y) const
277{
278 MFEM_ASSERT(x.Size() == width, "incorrect input Vector size");
279 MFEM_ASSERT(y.Size() == height, "incorrect output Vector size");
280
281 yblock.Update(y.GetData(),offsets);
282 xblock.Update(x.GetData(),offsets);
283
284 y = 0.0;
285 for (int iRow=0; iRow < nBlocks; ++iRow)
286 {
287 tmp.SetSize(offsets[iRow+1] - offsets[iRow]);
288 tmp2.SetSize(offsets[iRow+1] - offsets[iRow]);
289 tmp2 = 0.0;
290 tmp2 += xblock.GetBlock(iRow);
291 for (int jCol=0; jCol < iRow; ++jCol)
292 {
293 if (ops(iRow,jCol))
294 {
295 ops(iRow,jCol)->Mult(yblock.GetBlock(jCol), tmp);
296 tmp2 -= tmp;
297 }
298 }
299 if (ops(iRow,iRow))
300 {
301 ops(iRow,iRow)->Mult(tmp2, yblock.GetBlock(iRow));
302 }
303 else
304 {
305 yblock.GetBlock(iRow) = tmp2;
306 }
307 }
308}
309
310// Action of the transpose operator
312 Vector & y) const
313{
314 MFEM_ASSERT(x.Size() == height, "incorrect input Vector size");
315 MFEM_ASSERT(y.Size() == width, "incorrect output Vector size");
316
317 yblock.Update(y.GetData(),offsets);
318 xblock.Update(x.GetData(),offsets);
319
320 y = 0.0;
321 for (int iRow=nBlocks-1; iRow >=0; --iRow)
322 {
323 tmp.SetSize(offsets[iRow+1] - offsets[iRow]);
324 tmp2.SetSize(offsets[iRow+1] - offsets[iRow]);
325 tmp2 = 0.0;
326 tmp2 += xblock.GetBlock(iRow);
327 for (int jCol=iRow+1; jCol < nBlocks; ++jCol)
328 {
329 if (ops(jCol,iRow))
330 {
331 ops(jCol,iRow)->MultTranspose(yblock.GetBlock(jCol), tmp);
332 tmp2 -= tmp;
333 }
334 }
335 if (ops(iRow,iRow))
336 {
337 ops(iRow,iRow)->MultTranspose(tmp2, yblock.GetBlock(iRow));
338 }
339 else
340 {
341 yblock.GetBlock(iRow) = tmp2;
342 }
343 }
344}
345
347{
348 if (owns_blocks)
349 {
350 for (int iRow=0; iRow < nBlocks; ++iRow)
351 {
352 for (int jCol=0; jCol < nBlocks; ++jCol)
353 {
354 delete ops(jCol,iRow);
355 }
356 }
357 }
358}
359
360}
void MakeRef(T *data_, int size_, bool own_data=false)
Make this Array a reference to a pointer.
Definition: array.hpp:882
virtual void MultTranspose(const Vector &x, Vector &y) const
Action of the transpose operator.
virtual void Mult(const Vector &x, Vector &y) const
Operator application.
BlockDiagonalPreconditioner(const Array< int > &offsets)
Constructor that specifies the block structure.
void SetDiagonalBlock(int iblock, Operator *op)
Add a square block op in the block-entry (iblock, iblock).
virtual void MultTranspose(const Vector &x, Vector &y) const
Action of the transpose operator.
void SetDiagonalBlock(int iblock, Operator *op)
Add block op in the block-entry (iblock, iblock).
BlockLowerTriangularPreconditioner(const Array< int > &offsets)
virtual void Mult(const Vector &x, Vector &y) const
Operator application.
void SetBlock(int iRow, int iCol, Operator *op)
Add a block opt in the block-entry (iblock, jblock).
void SetDiagonalBlock(int iblock, Operator *op, real_t c=1.0)
Add block op in the block-entry (iblock, iblock).
BlockOperator(const Array< int > &offsets)
void SetBlock(int iRow, int iCol, Operator *op, real_t c=1.0)
Add a block op in the block-entry (iblock, jblock).
virtual void Mult(const Vector &x, Vector &y) const
Operator application.
virtual void MultTranspose(const Vector &x, Vector &y) const
Action of the transpose operator.
void Update(real_t *data, const Array< int > &bOffsets)
Update method.
Definition: blockvector.cpp:95
Vector & GetBlock(int i)
Get the i-th vector in the block.
Definition: blockvector.hpp:93
Abstract operator.
Definition: operator.hpp:25
int width
Dimension of the input / number of columns in the matrix.
Definition: operator.hpp:28
int Height() const
Get the height (size of output) of the Operator. Synonym with NumRows().
Definition: operator.hpp:66
int height
Dimension of the output / number of rows in the matrix.
Definition: operator.hpp:27
int NumCols() const
Get the number of columns (size of input) of the Operator. Synonym with Width().
Definition: operator.hpp:75
int Width() const
Get the width (size of input) of the Operator. Synonym with NumCols().
Definition: operator.hpp:72
int NumRows() const
Get the number of rows (size of output) of the Operator. Synonym with Height().
Definition: operator.hpp:69
Base class for solvers.
Definition: operator.hpp:683
Vector data type.
Definition: vector.hpp:80
virtual const real_t * Read(bool on_dev=true) const
Shortcut for mfem::Read(vec.GetMemory(), vec.Size(), on_dev).
Definition: vector.hpp:474
void SyncAliasMemory(const Vector &v) const
Update the alias memory location of the vector to match v.
Definition: vector.hpp:259
int Size() const
Returns the size of the vector.
Definition: vector.hpp:218
void SetSize(int s)
Resize the vector to size s.
Definition: vector.hpp:538
real_t * GetData() const
Return a pointer to the beginning of the Vector data.
Definition: vector.hpp:227
virtual real_t * Write(bool on_dev=true)
Shortcut for mfem::Write(vec.GetMemory(), vec.Size(), on_dev).
Definition: vector.hpp:482
Vector & Add(const real_t a, const Vector &Va)
(*this) += a * Va
Definition: vector.cpp:247
float real_t
Definition: config.hpp:43