Reference documentation for deal.II version 8.5.1
constrained_linear_operator.h
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2015 - 2016 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE at
12 // the top level of the deal.II distribution.
13 //
14 // ---------------------------------------------------------------------
15 
16 #ifndef dealii__constrained_linear_operator_h
17 #define dealii__constrained_linear_operator_h
18 
19 #include <deal.II/lac/linear_operator.h>
20 #include <deal.II/lac/packaged_operation.h>
21 #include <deal.II/lac/constraint_matrix.h>
22 
23 #ifdef DEAL_II_WITH_CXX11
24 
25 DEAL_II_NAMESPACE_OPEN
26 
27 
32 
33 
63 template <typename Range, typename Domain>
65  const ConstraintMatrix &constraint_matrix,
66  const LinearOperator<Range, Domain> &exemplar)
67 {
68  LinearOperator<Range, Domain> return_op = exemplar;
69 
70  return_op.vmult_add = [&constraint_matrix](Range &v, const Domain &u)
71  {
73  ::ExcMessage("The domain and range vectors must be different "
74  "storage locations"));
75 
76  for (auto i : v.locally_owned_elements())
77  {
78  if (constraint_matrix.is_constrained(i))
79  {
80  const auto *entries = constraint_matrix.get_constraint_entries(i);
81  for (types::global_dof_index j = 0; j < entries->size(); ++j)
82  {
83  const auto pos = (*entries)[j].first;
84  v(i) += u(pos) * (*entries)[j].second;
85  }
86  }
87  else
88  v(i) += u(i);
89  }
90  };
91 
92  return_op.Tvmult_add = [&constraint_matrix](Domain &v, const Range &u)
93  {
95  ::ExcMessage("The domain and range vectors must be different "
96  "storage locations"));
97 
98  for (auto i : v.locally_owned_elements())
99  {
100  if (constraint_matrix.is_constrained(i))
101  {
102  const auto *entries = constraint_matrix.get_constraint_entries(i);
103  for (types::global_dof_index j = 0; j < entries->size(); ++j)
104  {
105  const auto pos = (*entries)[j].first;
106  v(pos) += u(i) * (*entries)[j].second;
107  }
108  }
109  else
110  v(i)+=u(i);
111  }
112  };
113 
114  // lambda capture expressions are a C++14 feature...
115  const auto vmult_add = return_op.vmult_add;
116  return_op.vmult = [vmult_add](Range &v, const Domain &u)
117  {
118  v = 0.;
119  vmult_add(v, u);
120  };
121 
122  // lambda capture expressions are a C++14 feature...
123  const auto Tvmult_add = return_op.Tvmult_add;
124  return_op.Tvmult = [Tvmult_add](Domain &v, const Range &u)
125  {
126  v = 0.;
127  Tvmult_add(v, u);
128  };
129 
130  return return_op;
131 }
132 
133 
145 template <typename Range, typename Domain>
147  const ConstraintMatrix &constraint_matrix,
148  const LinearOperator<Range, Domain> &exemplar)
149 {
150  LinearOperator<Range, Domain> return_op = exemplar;
151 
152  return_op.vmult_add = [&constraint_matrix](Range &v, const Domain &u)
153  {
154  for (auto i : v.locally_owned_elements())
155  if (constraint_matrix.is_constrained(i))
156  v(i) += u(i);
157  };
158 
159  return_op.Tvmult_add = [&constraint_matrix](Domain &v, const Range &u)
160  {
161  for (auto i : v.locally_owned_elements())
162  if (constraint_matrix.is_constrained(i))
163  v(i) += u(i);
164  };
165 
166  return_op.vmult = [&constraint_matrix](Range &v, const Domain &u)
167  {
168  Assert(!::PointerComparison::equal(&v, &u),
169  ::ExcMessage("The domain and range vectors must be different "
170  "storage locations"));
171 
172  v = 0.;
173  for (auto i : v.locally_owned_elements())
174  if (constraint_matrix.is_constrained(i))
175  v(i) = u(i);
176  };
177 
178  return_op.Tvmult = [&constraint_matrix](Domain &v, const Range &u)
179  {
180  Assert(!::PointerComparison::equal(&v, &u),
181  ::ExcMessage("The domain and range vectors must be different "
182  "storage locations"));
183  v = 0.;
184  for (auto i : v.locally_owned_elements())
185  if (constraint_matrix.is_constrained(i))
186  v(i) = u(i);
187  };
188 
189  return return_op;
190 }
191 
192 
230 template <typename Range, typename Domain>
233  const LinearOperator<Range, Domain> &linop)
234 {
235  const auto C =
236  distribute_constraints_linear_operator(constraint_matrix, linop);
237  const auto Ct = transpose_operator(C);
238  const auto Id_c =
239  project_to_constrained_linear_operator(constraint_matrix, linop);
240  return Ct * linop * C + Id_c;
241 }
242 
243 
278 template <typename Range, typename Domain>
281  const LinearOperator<Range, Domain> &linop,
282  const Range &right_hand_side)
283 {
284  PackagedOperation<Range> return_comp;
285 
286  return_comp.reinit_vector = linop.reinit_range_vector;
287 
288  return_comp.apply_add =
289  [&constraint_matrix, &linop, &right_hand_side](Range &v)
290  {
291  const auto C =
292  distribute_constraints_linear_operator(constraint_matrix, linop);
293  const auto Ct = transpose_operator(C);
294 
295  static GrowingVectorMemory<Domain> vector_memory;
296  Domain *k = vector_memory.alloc();
297  linop.reinit_domain_vector(*k, /*bool fast=*/ false);
298  constraint_matrix.distribute(*k);
299 
300  v += Ct * (right_hand_side - linop **k);
301 
302  vector_memory.free(k);
303  };
304 
305  // lambda capture expressions are a C++14 feature...
306  const auto apply_add = return_comp.apply_add;
307  return_comp.apply = [apply_add](Range &v)
308  {
309  v = 0.;
310  apply_add(v);
311  };
312 
313  return return_comp;
314 }
315 
317 
318 DEAL_II_NAMESPACE_CLOSE
319 
320 #endif // DEAL_II_WITH_CXX11
321 #endif
std::function< void(Range &v)> apply
LinearOperator< Range, Domain > project_to_constrained_linear_operator(const ConstraintMatrix &constraint_matrix, const LinearOperator< Range, Domain > &exemplar)
std::function< void(Range &v, bool omit_zeroing_entries)> reinit_vector
std::function< void(Range &v, bool omit_zeroing_entries)> reinit_range_vector
std::function< void(Domain &v, const Range &u)> Tvmult_add
std::function< void(Domain &v, const Range &u)> Tvmult
LinearOperator< Domain, Range, Payload > transpose_operator(const LinearOperator< Range, Domain, Payload > &op)
static ::ExceptionBase & ExcMessage(std::string arg1)
LinearOperator< Range, Domain > constrained_linear_operator(const ConstraintMatrix &constraint_matrix, const LinearOperator< Range, Domain > &linop)
PackagedOperation< Range > constrained_right_hand_side(const ConstraintMatrix &constraint_matrix, const LinearOperator< Range, Domain > &linop, const Range &right_hand_side)
unsigned int global_dof_index
Definition: types.h:88
virtual VectorType * alloc()
#define Assert(cond, exc)
Definition: exceptions.h:313
static bool equal(const T *p1, const T *p2)
std::function< void(Range &v, const Domain &u)> vmult
virtual void free(const VectorType *const)
std::function< void(Range &v)> apply_add
void distribute(VectorType &vec) const
std::function< void(Range &v, const Domain &u)> vmult_add
LinearOperator< Range, Domain > distribute_constraints_linear_operator(const ConstraintMatrix &constraint_matrix, const LinearOperator< Range, Domain > &exemplar)
const std::vector< std::pair< size_type, double > > * get_constraint_entries(const size_type line) const
bool is_constrained(const size_type index) const