MFEM  v4.0
Finite element discretization library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
operator.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 #include "vector.hpp"
13 #include "dtensor.hpp"
14 #include "operator.hpp"
15 #include "../general/forall.hpp"
16 
17 #include <iostream>
18 #include <iomanip>
19 
20 namespace mfem
21 {
22 
23 void Operator::FormLinearSystem(const Array<int> &ess_tdof_list,
24  Vector &x, Vector &b,
25  Operator* &Aout, Vector &X, Vector &B,
26  int copy_interior)
27 {
28  const Operator *P = this->GetProlongation();
29  const Operator *R = this->GetRestriction();
30  Operator *rap;
31 
32  if (P)
33  {
34  // Variational restriction with P
35  B.SetSize(P->Width(), b);
36  P->MultTranspose(b, B);
37  X.SetSize(R->Height(), x);
38  R->Mult(x, X);
39  rap = new RAPOperator(*P, *this, *P);
40  }
41  else
42  {
43  // rap, X and B point to the same data as this, x and b, respectively
44  X.NewMemoryAndSize(x.GetMemory(), x.Size(), false);
45  B.NewMemoryAndSize(b.GetMemory(), b.Size(), false);
46  rap = this;
47  }
48 
49  if (!copy_interior) { X.SetSubVectorComplement(ess_tdof_list, 0.0); }
50 
51  // Impose the boundary conditions through a ConstrainedOperator, which owns
52  // the rap operator when P and R are non-trivial
53  ConstrainedOperator *A = new ConstrainedOperator(rap, ess_tdof_list,
54  rap != this);
55  A->EliminateRHS(X, B);
56  Aout = A;
57 }
58 
59 void Operator::RecoverFEMSolution(const Vector &X, const Vector &b, Vector &x)
60 {
61  const Operator *P = this->GetProlongation();
62  if (P)
63  {
64  // Apply conforming prolongation
65  x.SetSize(P->Height());
66  P->Mult(X, x);
67  }
68  else
69  {
70  // X and x point to the same data
71 
72  // If the validity flags of X's Memory were changed (e.g. if it was moved
73  // to device memory) then we need to tell x about that.
74  x.SyncMemory(X);
75  }
76 }
77 
78 void Operator::PrintMatlab(std::ostream & out, int n, int m) const
79 {
80  using namespace std;
81  if (n == 0) { n = width; }
82  if (m == 0) { m = height; }
83 
84  Vector x(n), y(m);
85  x = 0.0;
86 
87  out << setiosflags(ios::scientific | ios::showpos);
88  for (int i = 0; i < n; i++)
89  {
90  x(i) = 1.0;
91  Mult(x, y);
92  for (int j = 0; j < m; j++)
93  {
94  if (y(j))
95  {
96  out << j+1 << " " << i+1 << " " << y(j) << '\n';
97  }
98  }
99  x(i) = 0.0;
100  }
101 }
102 
103 
105  bool ownA, bool ownB)
106  : Operator(A->Height(), B->Width()),
107  A(A), B(B), ownA(ownA), ownB(ownB), z(A->Width())
108 {
109  MFEM_VERIFY(A->Width() == B->Height(),
110  "incompatible Operators: A->Width() = " << A->Width()
111  << ", B->Height() = " << B->Height());
112 }
113 
115 {
116  if (ownA) { delete A; }
117  if (ownB) { delete B; }
118 }
119 
120 
122  const Operator &P_)
123  : Operator(Rt_.Width(), P_.Width()), Rt(Rt_), A(A_), P(P_)
124 {
125  MFEM_VERIFY(Rt.Height() == A.Height(),
126  "incompatible Operators: Rt.Height() = " << Rt.Height()
127  << ", A.Height() = " << A.Height());
128  MFEM_VERIFY(A.Width() == P.Height(),
129  "incompatible Operators: A.Width() = " << A.Width()
130  << ", P.Height() = " << P.Height());
131 
132  mem_class = Rt.GetMemoryClass()*P.GetMemoryClass();
133  MemoryType mem_type = GetMemoryType(A.GetMemoryClass()*mem_class);
134  Px.SetSize(P.Height(), mem_type);
135  APx.SetSize(A.Height(), mem_type);
136 }
137 
138 
140  const Operator *A, const Operator *B, const Operator *C,
141  bool ownA, bool ownB, bool ownC)
142  : Operator(A->Height(), C->Width())
143  , A(A), B(B), C(C)
144  , ownA(ownA), ownB(ownB), ownC(ownC)
145 {
146  MFEM_VERIFY(A->Width() == B->Height(),
147  "incompatible Operators: A->Width() = " << A->Width()
148  << ", B->Height() = " << B->Height());
149  MFEM_VERIFY(B->Width() == C->Height(),
150  "incompatible Operators: B->Width() = " << B->Width()
151  << ", C->Height() = " << C->Height());
152 
153  mem_class = A->GetMemoryClass()*C->GetMemoryClass();
154  MemoryType mem_type = GetMemoryType(mem_class*B->GetMemoryClass());
155  t1.SetSize(C->Height(), mem_type);
156  t2.SetSize(B->Height(), mem_type);
157 }
158 
160 {
161  if (ownA) { delete A; }
162  if (ownB) { delete B; }
163  if (ownC) { delete C; }
164 }
165 
166 
168  bool _own_A)
169  : Operator(A->Height(), A->Width()), A(A), own_A(_own_A)
170 {
171  // 'mem_class' should work with A->Mult() and MFEM_FORALL():
173  MemoryType mem_type = GetMemoryType(mem_class);
174  constraint_list.MakeRef(list);
175  // typically z and w are large vectors, so store them on the device
176  z.SetSize(height, mem_type); z.UseDevice(true);
177  w.SetSize(height, mem_type); w.UseDevice(true);
178 }
179 
181 {
182  w = 0.0;
183  const int csz = constraint_list.Size();
184  auto idx = constraint_list.Read();
185  auto d_x = x.Read();
186  // Use read+write access - we are modifying sub-vector of w
187  auto d_w = w.ReadWrite();
188  MFEM_FORALL(i, csz,
189  {
190  const int id = idx[i];
191  d_w[id] = d_x[id];
192  });
193 
194  A->Mult(w, z);
195 
196  b -= z;
197  // Use read+write access - we are modifying sub-vector of b
198  auto d_b = b.ReadWrite();
199  MFEM_FORALL(i, csz,
200  {
201  const int id = idx[i];
202  d_b[id] = d_x[id];
203  });
204 }
205 
206 void ConstrainedOperator::Mult(const Vector &x, Vector &y) const
207 {
208  const int csz = constraint_list.Size();
209  if (csz == 0)
210  {
211  A->Mult(x, y);
212  return;
213  }
214 
215  z = x;
216 
217  auto idx = constraint_list.Read();
218  // Use read+write access - we are modifying sub-vector of z
219  auto d_z = z.ReadWrite();
220  MFEM_FORALL(i, csz, d_z[idx[i]] = 0.0;);
221 
222  A->Mult(z, y);
223 
224  auto d_x = x.Read();
225  // Use read+write access - we are modifying sub-vector of y
226  auto d_y = y.ReadWrite();
227  MFEM_FORALL(i, csz,
228  {
229  const int id = idx[i];
230  d_y[id] = d_x[id];
231  });
232 }
233 
234 }
static MemoryClass GetMemoryClass()
Get the current Device MemoryClass. This is the MemoryClass used by most MFEM device kernels to acces...
Definition: device.hpp:214
int Size() const
Logical size of the array.
Definition: array.hpp:118
virtual ~ProductOperator()
Definition: operator.cpp:114
Array< int > constraint_list
List of constrained indices/dofs.
Definition: operator.hpp:424
void SyncMemory(const Vector &v)
Update the memory location of the vector to match v.
Definition: vector.hpp:180
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
void UseDevice(bool use_dev) const
Enable execution of Vector operations using the mfem::Device.
Definition: vector.hpp:86
virtual void Mult(const Vector &x, Vector &y) const
Constrained operator action.
Definition: operator.cpp:206
int Size() const
Returns the size of the vector.
Definition: vector.hpp:150
ProductOperator(const Operator *A, const Operator *B, bool ownA, bool ownB)
Definition: operator.cpp:104
virtual void Mult(const Vector &x, Vector &y) const =0
Operator application: y=A(x).
Memory< double > & GetMemory()
Return a reference to the Memory object used by the Vector.
Definition: vector.hpp:173
virtual void MultTranspose(const Vector &x, Vector &y) const
Action of the transpose operator: y=A^t(x). The default behavior in class Operator is to generate an ...
Definition: operator.hpp:63
virtual const Operator * GetProlongation() const
Prolongation operator from linear algebra (linear system) vectors, to input vectors for the operator...
Definition: operator.hpp:76
double * ReadWrite(bool on_dev=true)
Shortcut for mfem::ReadWrite(vec.GetMemory(), vec.Size(), on_dev).
Definition: vector.hpp:342
virtual MemoryClass GetMemoryClass() const
Return the MemoryClass preferred by the Operator.
Definition: operator.hpp:56
int Height() const
Get the height (size of output) of the Operator. Synonym with NumRows().
Definition: operator.hpp:36
const T * Read(bool on_dev=true) const
Shortcut for mfem::Read(a.GetMemory(), a.Size(), on_dev).
Definition: array.hpp:261
The operator x -&gt; R*A*P*x constructed through the actions of R^T, A and P.
Definition: operator.hpp:363
RAPOperator(const Operator &Rt_, const Operator &A_, const Operator &P_)
Construct the RAP operator given R^T, A and P.
Definition: operator.cpp:121
virtual const Operator * GetRestriction() const
Restriction operator from input vectors for the operator to linear algebra (linear system) vectors...
Definition: operator.hpp:79
void SetSubVectorComplement(const Array< int > &dofs, const double val)
Set all vector entries NOT in the &#39;dofs&#39; array to the given &#39;val&#39;.
Definition: vector.cpp:633
Vector w
Auxiliary vectors.
Definition: operator.hpp:427
MemoryType
Memory types supported by MFEM.
Definition: mem_manager.hpp:27
void FormLinearSystem(const Array< int > &ess_tdof_list, Vector &x, Vector &b, Operator *&A, Vector &X, Vector &B, int copy_interior=0)
Form a constrained linear system using a matrix-free approach.
Definition: operator.cpp:23
virtual void RecoverFEMSolution(const Vector &X, const Vector &b, Vector &x)
Reconstruct a solution vector x (e.g. a GridFunction) from the solution X of a constrained linear sys...
Definition: operator.cpp:59
int height
Dimension of the output / number of rows in the matrix.
Definition: operator.hpp:24
const double * Read(bool on_dev=true) const
Shortcut for mfem::Read(vec.GetMemory(), vec.Size(), on_dev).
Definition: vector.hpp:326
void EliminateRHS(const Vector &x, Vector &b) const
Eliminate &quot;essential boundary condition&quot; values specified in x from the given right-hand side b...
Definition: operator.cpp:180
void PrintMatlab(std::ostream &out, int n=0, int m=0) const
Prints operator with input size n and output size m in Matlab format.
Definition: operator.cpp:78
void NewMemoryAndSize(const Memory< double > &mem, int s, bool own_mem)
Reset the Vector to use the given external Memory mem and size s.
Definition: vector.hpp:449
MemoryType GetMemoryType(MemoryClass mc)
Return a suitable MemoryType for a given MemoryClass.
Definition: mem_manager.cpp:23
ConstrainedOperator(Operator *A, const Array< int > &list, bool own_A=false)
Constructor from a general Operator and a list of essential indices/dofs.
Definition: operator.cpp:167
TripleProductOperator(const Operator *A, const Operator *B, const Operator *C, bool ownA, bool ownB, bool ownC)
Definition: operator.cpp:139
void MakeRef(T *, int)
Make this Array a reference to a pointer.
Definition: array.hpp:803
Vector data type.
Definition: vector.hpp:48
Operator * A
The unconstrained Operator.
Definition: operator.hpp:425
Square Operator for imposing essential boundary conditions using only the action, Mult()...
Definition: operator.hpp:421
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
Definition: globals.hpp:64
Abstract operator.
Definition: operator.hpp:21
int width
Dimension of the input / number of columns in the matrix.
Definition: operator.hpp:25