MFEM  v4.2.0
Finite element discretization library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
blockoperator.cpp
Go to the documentation of this file.
1 // Copyright (c) 2010-2020, 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 
18 namespace mfem
19 {
20 
22  : Operator(offsets.Last()),
23  owns_blocks(0),
24  nRowBlocks(offsets.Size() - 1),
25  nColBlocks(offsets.Size() - 1),
26  row_offsets(0),
27  col_offsets(0),
28  op(nRowBlocks, nRowBlocks),
29  coef(nRowBlocks, nColBlocks)
30 {
31  op = static_cast<Operator *>(NULL);
32  row_offsets.MakeRef(offsets);
33  col_offsets.MakeRef(offsets);
34 }
35 
37  const Array<int> & col_offsets_)
38  : Operator(row_offsets_.Last(), col_offsets_.Last()),
39  owns_blocks(0),
40  nRowBlocks(row_offsets_.Size()-1),
41  nColBlocks(col_offsets_.Size()-1),
42  row_offsets(0),
43  col_offsets(0),
44  op(nRowBlocks, nColBlocks),
45  coef(nRowBlocks, nColBlocks)
46 {
47  op = static_cast<Operator *>(NULL);
48  row_offsets.MakeRef(row_offsets_);
49  col_offsets.MakeRef(col_offsets_);
50 }
51 
52 void BlockOperator::SetDiagonalBlock(int iblock, Operator *op, double c)
53 {
54  SetBlock(iblock, iblock, op, c);
55 }
56 
57 void BlockOperator::SetBlock(int iRow, int iCol, Operator *opt, double c)
58 {
59  if (owns_blocks && op(iRow, iCol))
60  {
61  delete op(iRow, iCol);
62  }
63  op(iRow, iCol) = opt;
64  coef(iRow, iCol) = c;
65 
66  MFEM_VERIFY(row_offsets[iRow+1] - row_offsets[iRow] == opt->NumRows() &&
67  col_offsets[iCol+1] - col_offsets[iCol] == opt->NumCols(),
68  "incompatible Operator dimensions");
69 }
70 
71 // Operator application
72 void BlockOperator::Mult (const Vector & x, Vector & y) const
73 {
74  MFEM_ASSERT(x.Size() == width, "incorrect input Vector size");
75  MFEM_ASSERT(y.Size() == height, "incorrect output Vector size");
76 
77  x.Read();
78  y.Write(); y = 0.0;
79 
80  xblock.Update(const_cast<Vector&>(x),col_offsets);
81  yblock.Update(y,row_offsets);
82 
83  for (int iRow=0; iRow < nRowBlocks; ++iRow)
84  {
85  tmp.SetSize(row_offsets[iRow+1] - row_offsets[iRow]);
86  for (int jCol=0; jCol < nColBlocks; ++jCol)
87  {
88  if (op(iRow,jCol))
89  {
90  op(iRow,jCol)->Mult(xblock.GetBlock(jCol), tmp);
91  yblock.GetBlock(iRow).Add(coef(iRow,jCol), tmp);
92  }
93  }
94  }
95 
96  for (int iRow=0; iRow < nRowBlocks; ++iRow)
97  {
98  yblock.GetBlock(iRow).SyncAliasMemory(y);
99  }
100 
101  // Destroy alias vectors to prevent dangling aliases when the base vectors
102  // are deleted
103  for (int i=0; i < xblock.NumBlocks(); ++i) { xblock.GetBlock(i).Destroy(); }
104  for (int i=0; i < yblock.NumBlocks(); ++i) { yblock.GetBlock(i).Destroy(); }
105 }
106 
107 // Action of the transpose operator
108 void BlockOperator::MultTranspose (const Vector & x, Vector & y) const
109 {
110  MFEM_ASSERT(x.Size() == height, "incorrect input Vector size");
111  MFEM_ASSERT(y.Size() == width, "incorrect output Vector size");
112 
113  x.Read();
114  y.Write(); y = 0.0;
115 
116  xblock.Update(const_cast<Vector&>(x),row_offsets);
117  yblock.Update(y,col_offsets);
118 
119  for (int iRow=0; iRow < nColBlocks; ++iRow)
120  {
121  tmp.SetSize(col_offsets[iRow+1] - col_offsets[iRow]);
122  for (int jCol=0; jCol < nRowBlocks; ++jCol)
123  {
124  if (op(jCol,iRow))
125  {
126  op(jCol,iRow)->MultTranspose(xblock.GetBlock(jCol), tmp);
127  yblock.GetBlock(iRow).Add(coef(jCol,iRow), tmp);
128  }
129  }
130  }
131 
132  for (int iRow=0; iRow < nColBlocks; ++iRow)
133  {
134  yblock.GetBlock(iRow).SyncAliasMemory(y);
135  }
136 
137  // Destroy alias vectors to prevent dangling aliases when the base vectors
138  // are deleted
139  for (int i=0; i < xblock.NumBlocks(); ++i) { xblock.GetBlock(i).Destroy(); }
140  for (int i=0; i < yblock.NumBlocks(); ++i) { yblock.GetBlock(i).Destroy(); }
141 }
142 
144 {
145  if (owns_blocks)
146  {
147  for (int iRow=0; iRow < nRowBlocks; ++iRow)
148  {
149  for (int jCol=0; jCol < nColBlocks; ++jCol)
150  {
151  delete op(jCol,iRow);
152  }
153  }
154  }
155 }
156 
157 //-----------------------------------------------------------------------
159  const Array<int> & offsets_):
160  Solver(offsets_.Last()),
161  owns_blocks(0),
162  nBlocks(offsets_.Size() - 1),
163  offsets(0),
164  op(nBlocks)
165 {
166  op = static_cast<Operator *>(NULL);
167  offsets.MakeRef(offsets_);
168 }
169 
171 {
172  MFEM_VERIFY(offsets[iblock+1] - offsets[iblock] == opt->Height() &&
173  offsets[iblock+1] - offsets[iblock] == opt->Width(),
174  "incompatible Operator dimensions");
175 
176  if (owns_blocks && op[iblock])
177  {
178  delete op[iblock];
179  }
180  op[iblock] = opt;
181 }
182 
183 // Operator application
185 {
186  MFEM_ASSERT(x.Size() == width, "incorrect input Vector size");
187  MFEM_ASSERT(y.Size() == height, "incorrect output Vector size");
188 
189  x.Read();
190  y.Write(); y = 0.0;
191 
192  xblock.Update(const_cast<Vector&>(x),offsets);
193  yblock.Update(y,offsets);
194 
195  for (int i=0; i<nBlocks; ++i)
196  {
197  if (op[i])
198  {
199  op[i]->Mult(xblock.GetBlock(i), yblock.GetBlock(i));
200  }
201  else
202  {
203  yblock.GetBlock(i) = xblock.GetBlock(i);
204  }
205  }
206 
207  for (int i=0; i<nBlocks; ++i)
208  {
209  yblock.GetBlock(i).SyncAliasMemory(y);
210  }
211 
212  // Destroy alias vectors to prevent dangling aliases when the base vectors
213  // are deleted
214  for (int i=0; i < xblock.NumBlocks(); ++i) { xblock.GetBlock(i).Destroy(); }
215  for (int i=0; i < yblock.NumBlocks(); ++i) { yblock.GetBlock(i).Destroy(); }
216 }
217 
218 // Action of the transpose operator
220  Vector & y) const
221 {
222  MFEM_ASSERT(x.Size() == height, "incorrect input Vector size");
223  MFEM_ASSERT(y.Size() == width, "incorrect output Vector size");
224 
225  x.Read();
226  y.Write(); y = 0.0;
227 
228  xblock.Update(const_cast<Vector&>(x),offsets);
229  yblock.Update(y,offsets);
230 
231  for (int i=0; i<nBlocks; ++i)
232  {
233  if (op[i])
234  {
235  (op[i])->MultTranspose(xblock.GetBlock(i), yblock.GetBlock(i));
236  }
237  else
238  {
239  yblock.GetBlock(i) = xblock.GetBlock(i);
240  }
241  }
242 
243  for (int i=0; i<nBlocks; ++i)
244  {
245  yblock.GetBlock(i).SyncAliasMemory(y);
246  }
247 
248  // Destroy alias vectors to prevent dangling aliases when the base vectors
249  // are deleted
250  for (int i=0; i < xblock.NumBlocks(); ++i) { xblock.GetBlock(i).Destroy(); }
251  for (int i=0; i < yblock.NumBlocks(); ++i) { yblock.GetBlock(i).Destroy(); }
252 }
253 
255 {
256  if (owns_blocks)
257  {
258  for (int i=0; i<nBlocks; ++i)
259  {
260  delete op[i];
261  }
262  }
263 }
264 
266  const Array<int> & offsets_)
267  : Solver(offsets_.Last()),
268  owns_blocks(0),
269  nBlocks(offsets_.Size() - 1),
270  offsets(0),
271  op(nBlocks, nBlocks)
272 {
273  op = static_cast<Operator *>(NULL);
274  offsets.MakeRef(offsets_);
275 }
276 
278  Operator *op)
279 {
280  MFEM_VERIFY(offsets[iblock+1] - offsets[iblock] == op->Height() &&
281  offsets[iblock+1] - offsets[iblock] == op->Width(),
282  "incompatible Operator dimensions");
283 
284  SetBlock(iblock, iblock, op);
285 }
286 
288  Operator *opt)
289 {
290  MFEM_VERIFY(iRow >= iCol,"cannot set block in upper triangle");
291  MFEM_VERIFY(offsets[iRow+1] - offsets[iRow] == opt->NumRows() &&
292  offsets[iCol+1] - offsets[iCol] == opt->NumCols(),
293  "incompatible Operator dimensions");
294 
295  op(iRow, iCol) = opt;
296 }
297 
298 // Operator application
300  Vector & y) const
301 {
302  MFEM_ASSERT(x.Size() == width, "incorrect input Vector size");
303  MFEM_ASSERT(y.Size() == height, "incorrect output Vector size");
304 
305  yblock.Update(y.GetData(),offsets);
306  xblock.Update(x.GetData(),offsets);
307 
308  y = 0.0;
309  for (int iRow=0; iRow < nBlocks; ++iRow)
310  {
311  tmp.SetSize(offsets[iRow+1] - offsets[iRow]);
312  tmp2.SetSize(offsets[iRow+1] - offsets[iRow]);
313  tmp2 = 0.0;
314  tmp2 += xblock.GetBlock(iRow);
315  for (int jCol=0; jCol < iRow; ++jCol)
316  {
317  if (op(iRow,jCol))
318  {
319  op(iRow,jCol)->Mult(yblock.GetBlock(jCol), tmp);
320  tmp2 -= tmp;
321  }
322  }
323  if (op(iRow,iRow))
324  {
325  op(iRow,iRow)->Mult(tmp2, yblock.GetBlock(iRow));
326  }
327  else
328  {
329  yblock.GetBlock(iRow) = tmp2;
330  }
331  }
332 }
333 
334 // Action of the transpose operator
336  Vector & y) const
337 {
338  MFEM_ASSERT(x.Size() == height, "incorrect input Vector size");
339  MFEM_ASSERT(y.Size() == width, "incorrect output Vector size");
340 
341  yblock.Update(y.GetData(),offsets);
342  xblock.Update(x.GetData(),offsets);
343 
344  y = 0.0;
345  for (int iRow=nBlocks-1; iRow >=0; --iRow)
346  {
347  tmp.SetSize(offsets[iRow+1] - offsets[iRow]);
348  tmp2.SetSize(offsets[iRow+1] - offsets[iRow]);
349  tmp2 = 0.0;
350  tmp2 += xblock.GetBlock(iRow);
351  for (int jCol=iRow+1; jCol < nBlocks; ++jCol)
352  {
353  if (op(jCol,iRow))
354  {
355  op(jCol,iRow)->MultTranspose(yblock.GetBlock(jCol), tmp);
356  tmp2 -= tmp;
357  }
358  }
359  if (op(iRow,iRow))
360  {
361  op(iRow,iRow)->MultTranspose(tmp2, yblock.GetBlock(iRow));
362  }
363  else
364  {
365  yblock.GetBlock(iRow) = tmp2;
366  }
367  }
368 }
369 
371 {
372  if (owns_blocks)
373  {
374  for (int iRow=0; iRow < nBlocks; ++iRow)
375  {
376  for (int jCol=0; jCol < nBlocks; ++jCol)
377  {
378  delete op(jCol,iRow);
379  }
380  }
381  }
382 }
383 
384 }
void SetSize(int s)
Resize the vector to size s.
Definition: vector.hpp:459
int Width() const
Get the width (size of input) of the Operator. Synonym with NumCols().
Definition: operator.hpp:71
int Size() const
Returns the size of the vector.
Definition: vector.hpp:160
void Update(double *data, const Array< int > &bOffsets)
Update method.
Definition: blockvector.cpp:77
virtual void MultTranspose(const Vector &x, Vector &y) const
Action of the transpose operator.
double * Write(bool on_dev=true)
Shortcut for mfem::Write(vec.GetMemory(), vec.Size(), on_dev).
Definition: vector.hpp:380
double * GetData() const
Return a pointer to the beginning of the Vector data.
Definition: vector.hpp:169
int Height() const
Get the height (size of output) of the Operator. Synonym with NumRows().
Definition: operator.hpp:65
void SetBlock(int iRow, int iCol, Operator *op)
Add a block op in the block-entry (iblock, jblock).
virtual void Mult(const Vector &x, Vector &y) const
Operator application.
BlockDiagonalPreconditioner(const Array< int > &offsets)
Constructor that specifies the block structure.
BlockOperator(const Array< int > &offsets)
virtual void Mult(const Vector &x, Vector &y) const
Operator application.
void SetDiagonalBlock(int iblock, Operator *op, double c=1.0)
Add block op in the block-entry (iblock, iblock).
virtual void MultTranspose(const Vector &x, Vector &y) const
Action of the transpose operator.
int NumRows() const
Get the number of rows (size of output) of the Operator. Synonym with Height().
Definition: operator.hpp:68
int NumCols() const
Get the number of columns (size of input) of the Operator. Synonym with Width().
Definition: operator.hpp:74
virtual void MultTranspose(const Vector &x, Vector &y) const
Action of the transpose operator.
int height
Dimension of the output / number of rows in the matrix.
Definition: operator.hpp:27
void SetDiagonalBlock(int iblock, Operator *op)
Add block op in the block-entry (iblock, iblock).
Vector & Add(const double a, const Vector &Va)
(*this) += a * Va
Definition: vector.cpp:213
const double * Read(bool on_dev=true) const
Shortcut for mfem::Read(vec.GetMemory(), vec.Size(), on_dev).
Definition: vector.hpp:372
void Destroy()
Destroy a vector.
Definition: vector.hpp:530
virtual void Mult(const Vector &x, Vector &y) const
Operator application.
int NumBlocks() const
Return the number of blocks.
Definition: blockvector.hpp:76
void MakeRef(T *, int)
Make this Array a reference to a pointer.
Definition: array.hpp:839
Vector data type.
Definition: vector.hpp:51
BlockLowerTriangularPreconditioner(const Array< int > &offsets)
Base class for solvers.
Definition: operator.hpp:634
Abstract operator.
Definition: operator.hpp:24
int width
Dimension of the input / number of columns in the matrix.
Definition: operator.hpp:28
void SetBlock(int iRow, int iCol, Operator *op, double c=1.0)
Add a block op in the block-entry (iblock, jblock).
void SetDiagonalBlock(int iblock, Operator *op)
Add a square block op in the block-entry (iblock, iblock).
Vector & GetBlock(int i)
Get the i-th vector in the block.
Definition: blockvector.hpp:87
void SyncAliasMemory(const Vector &v)
Update the alias memory location of the vector to match v.
Definition: vector.hpp:193