MFEM  v4.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, Lawrence Livermore National Security, LLC. Produced at
2 // the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
3 // reserved. See file COPYRIGHT for details.
4 //
5 // This file is part of the MFEM library. For more information and source code
6 // availability see http://mfem.org.
7 //
8 // MFEM is free software; you can redistribute it and/or modify it under the
9 // terms of the GNU Lesser General Public License (as published by the Free
10 // Software Foundation) version 2.1 dated February 1999.
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  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
68 void 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  yblock.Update(y.GetData(),row_offsets);
74  xblock.Update(x.GetData(),col_offsets);
75 
76  y = 0.0;
77  for (int iRow=0; iRow < nRowBlocks; ++iRow)
78  {
79  tmp.SetSize(row_offsets[iRow+1] - row_offsets[iRow]);
80  for (int jCol=0; jCol < nColBlocks; ++jCol)
81  {
82  if (op(iRow,jCol))
83  {
84  op(iRow,jCol)->Mult(xblock.GetBlock(jCol), tmp);
85  yblock.GetBlock(iRow).Add(coef(iRow,jCol), tmp);
86  }
87  }
88  }
89 }
90 
91 // Action of the transpose operator
92 void BlockOperator::MultTranspose (const Vector & x, Vector & y) const
93 {
94  MFEM_ASSERT(x.Size() == height, "incorrect input Vector size");
95  MFEM_ASSERT(y.Size() == width, "incorrect output Vector size");
96 
97  y = 0.0;
98 
99  xblock.Update(x.GetData(),row_offsets);
100  yblock.Update(y.GetData(),col_offsets);
101 
102  for (int iRow=0; iRow < nColBlocks; ++iRow)
103  {
104  tmp.SetSize(col_offsets[iRow+1] - col_offsets[iRow]);
105  for (int jCol=0; jCol < nRowBlocks; ++jCol)
106  {
107  if (op(jCol,iRow))
108  {
109  op(jCol,iRow)->MultTranspose(xblock.GetBlock(jCol), tmp);
110  yblock.GetBlock(iRow).Add(coef(jCol,iRow), tmp);
111  }
112  }
113  }
114 
115 }
116 
118 {
119  if (owns_blocks)
120  {
121  for (int iRow=0; iRow < nRowBlocks; ++iRow)
122  {
123  for (int jCol=0; jCol < nColBlocks; ++jCol)
124  {
125  delete op(jCol,iRow);
126  }
127  }
128  }
129 }
130 
131 //-----------------------------------------------------------------------
133  const Array<int> & offsets_):
134  Solver(offsets_.Last()),
135  owns_blocks(0),
136  nBlocks(offsets_.Size() - 1),
137  offsets(0),
138  op(nBlocks)
139 
140 {
141  op = static_cast<Operator *>(NULL);
142  offsets.MakeRef(offsets_);
143 }
144 
146 {
147  MFEM_VERIFY(offsets[iblock+1] - offsets[iblock] == opt->Height() &&
148  offsets[iblock+1] - offsets[iblock] == opt->Width(),
149  "incompatible Operator dimensions");
150 
151  op[iblock] = opt;
152 }
153 
154 // Operator application
156 {
157  MFEM_ASSERT(x.Size() == width, "incorrect input Vector size");
158  MFEM_ASSERT(y.Size() == height, "incorrect output Vector size");
159 
160  yblock.Update(y.GetData(), offsets);
161  xblock.Update(x.GetData(), offsets);
162 
163  for (int i=0; i<nBlocks; ++i)
164  {
165  if (op[i])
166  {
167  op[i]->Mult(xblock.GetBlock(i), yblock.GetBlock(i));
168  }
169  else
170  {
171  yblock.GetBlock(i) = xblock.GetBlock(i);
172  }
173  }
174 }
175 
176 // Action of the transpose operator
178  Vector & y) const
179 {
180  MFEM_ASSERT(x.Size() == height, "incorrect input Vector size");
181  MFEM_ASSERT(y.Size() == width, "incorrect output Vector size");
182 
183  yblock.Update(y.GetData(), offsets);
184  xblock.Update(x.GetData(), offsets);
185 
186  for (int i=0; i<nBlocks; ++i)
187  {
188  if (op[i])
189  {
190  (op[i])->MultTranspose(xblock.GetBlock(i), yblock.GetBlock(i));
191  }
192  else
193  {
194  yblock.GetBlock(i) = xblock.GetBlock(i);
195  }
196  }
197 }
198 
200 {
201  if (owns_blocks)
202  {
203  for (int i=0; i<nBlocks; ++i)
204  {
205  delete op[i];
206  }
207  }
208 }
209 
211  const Array<int> & offsets_)
212  : Solver(offsets_.Last()),
213  owns_blocks(0),
214  nBlocks(offsets_.Size() - 1),
215  offsets(0),
216  op(nBlocks, nBlocks)
217 {
218  op = static_cast<Operator *>(NULL);
219  offsets.MakeRef(offsets_);
220 }
221 
223  Operator *op)
224 {
225  MFEM_VERIFY(offsets[iblock+1] - offsets[iblock] == op->Height() &&
226  offsets[iblock+1] - offsets[iblock] == op->Width(),
227  "incompatible Operator dimensions");
228 
229  SetBlock(iblock, iblock, op);
230 }
231 
233  Operator *opt)
234 {
235  MFEM_VERIFY(iRow >= iCol,"cannot set block in upper triangle");
236  MFEM_VERIFY(offsets[iRow+1] - offsets[iRow] == opt->NumRows() &&
237  offsets[iCol+1] - offsets[iCol] == opt->NumCols(),
238  "incompatible Operator dimensions");
239 
240  op(iRow, iCol) = opt;
241 }
242 
243 // Operator application
245  Vector & y) const
246 {
247  MFEM_ASSERT(x.Size() == width, "incorrect input Vector size");
248  MFEM_ASSERT(y.Size() == height, "incorrect output Vector size");
249 
250  yblock.Update(y.GetData(),offsets);
251  xblock.Update(x.GetData(),offsets);
252 
253  y = 0.0;
254  for (int iRow=0; iRow < nBlocks; ++iRow)
255  {
256  tmp.SetSize(offsets[iRow+1] - offsets[iRow]);
257  tmp2.SetSize(offsets[iRow+1] - offsets[iRow]);
258  tmp2 = 0.0;
259  tmp2 += xblock.GetBlock(iRow);
260  for (int jCol=0; jCol < iRow; ++jCol)
261  {
262  if (op(iRow,jCol))
263  {
264  op(iRow,jCol)->Mult(yblock.GetBlock(jCol), tmp);
265  tmp2 -= tmp;
266  }
267  }
268  if (op(iRow,iRow))
269  {
270  op(iRow,iRow)->Mult(tmp2, yblock.GetBlock(iRow));
271  }
272  else
273  {
274  yblock.GetBlock(iRow) = tmp2;
275  }
276  }
277 }
278 
279 // Action of the transpose operator
281  Vector & y) const
282 {
283  MFEM_ASSERT(x.Size() == height, "incorrect input Vector size");
284  MFEM_ASSERT(y.Size() == width, "incorrect output Vector size");
285 
286  yblock.Update(y.GetData(),offsets);
287  xblock.Update(x.GetData(),offsets);
288 
289  y = 0.0;
290  for (int iRow=nBlocks-1; iRow >=0; --iRow)
291  {
292  tmp.SetSize(offsets[iRow+1] - offsets[iRow]);
293  tmp2.SetSize(offsets[iRow+1] - offsets[iRow]);
294  tmp2 = 0.0;
295  tmp2 += xblock.GetBlock(iRow);
296  for (int jCol=iRow+1; jCol < nBlocks; ++jCol)
297  {
298  if (op(jCol,iRow))
299  {
300  op(jCol,iRow)->MultTranspose(yblock.GetBlock(jCol), tmp);
301  tmp2 -= tmp;
302  }
303  }
304  if (op(iRow,iRow))
305  {
306  op(iRow,iRow)->MultTranspose(tmp2, yblock.GetBlock(iRow));
307  }
308  else
309  {
310  yblock.GetBlock(iRow) = tmp2;
311  }
312  }
313 }
314 
316 {
317  if (owns_blocks)
318  {
319  for (int iRow=0; iRow < nBlocks; ++iRow)
320  {
321  for (int jCol=0; jCol < nBlocks; ++jCol)
322  {
323  delete op(jCol,iRow);
324  }
325  }
326  }
327 }
328 
329 }
void SetSize(int s)
Resize the vector to size s.
Definition: vector.hpp:400
int Width() const
Get the width (size of input) of the Operator. Synonym with NumCols().
Definition: operator.hpp:42
int Size() const
Returns the size of the vector.
Definition: vector.hpp:150
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 * GetData() const
Return a pointer to the beginning of the Vector data.
Definition: vector.hpp:159
int Height() const
Get the height (size of output) of the Operator. Synonym with NumRows().
Definition: operator.hpp:36
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:39
int NumCols() const
Get the number of columns (size of input) of the Operator. Synonym with Width().
Definition: operator.hpp:45
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:24
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:190
virtual void Mult(const Vector &x, Vector &y) const
Operator application.
void MakeRef(T *, int)
Make this Array a reference to a pointer.
Definition: array.hpp:803
Vector data type.
Definition: vector.hpp:48
BlockLowerTriangularPreconditioner(const Array< int > &offsets)
Base class for solvers.
Definition: operator.hpp:279
Abstract operator.
Definition: operator.hpp:21
int width
Dimension of the input / number of columns in the matrix.
Definition: operator.hpp:25
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:84