deal.II version GIT relicensing-6834-g5b78e6bcdf 2026-10-01 11:20:01+00:00
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
Loading...
Searching...
No Matches
constrained_linear_operator.h
Go to the documentation of this file.
1// -----------------------------------------------------------------------------
2//
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception OR LGPL-2.1-or-later
4// Copyright (C) 2015 - 2024 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Detailed license information governing the source code and contributions
9// can be found in LICENSE.md and CONTRIBUTING.md at the top level directory.
10//
11// -----------------------------------------------------------------------------
12
13#ifndef dealii_constrained_linear_operator_h
14#define dealii_constrained_linear_operator_h
15
16#include <deal.II/base/config.h>
17
21
22
24
25
60template <typename Range, typename Domain, typename Payload>
65{
66 LinearOperator<Range, Domain, Payload> return_op = exemplar;
67
68 return_op.vmult_add = [&constraints](Range &v, const Domain &u) {
70 ::ExcMessage("The domain and range vectors must be different "
71 "storage locations"));
72
73 // First, add vector u to v unconditionally and clean up constrained
74 // degrees of freedom later.
75 v += u;
76
77 const auto &locally_owned_elements = v.locally_owned_elements();
78 for (const auto &line : constraints.get_lines())
79 {
80 const auto i = line.index;
81 if (locally_owned_elements.is_element(i))
82 {
83 v(i) -= u(i);
84 const auto &entries = line.entries;
85 for (types::global_dof_index j = 0; j < entries.size(); ++j)
86 {
87 const auto pos = entries[j].first;
88 v(i) += u(pos) * entries[j].second;
89 }
90 }
91 }
92
93 v.compress(VectorOperation::add);
94 };
95
96 return_op.Tvmult_add = [&constraints](Domain &v, const Range &u) {
98 ::ExcMessage("The domain and range vectors must be different "
99 "storage locations"));
100
101 // First, add vector u to v unconditionally and clean up constrained
102 // degrees of freedom later.
103 v += u;
104
105 const auto &locally_owned_elements = v.locally_owned_elements();
106 for (const auto &line : constraints.get_lines())
107 {
108 const auto i = line.index;
109
110 if (locally_owned_elements.is_element(i))
111 {
112 v(i) -= u(i);
113 }
114
115 const auto &entries = line.entries;
116 for (types::global_dof_index j = 0; j < entries.size(); ++j)
117 {
118 const auto pos = entries[j].first;
119 if (locally_owned_elements.is_element(pos))
120 v(pos) += u(i) * entries[j].second;
121 }
122 }
123
124 v.compress(VectorOperation::add);
125 };
126
127 return_op.vmult = [vmult_add = return_op.vmult_add](Range &v,
128 const Domain &u) {
129 v = 0.;
130 vmult_add(v, u);
131 };
132
133 return_op.Tvmult = [Tvmult_add = return_op.Tvmult_add](Domain &v,
134 const Range &u) {
135 v = 0.;
136 Tvmult_add(v, u);
137 };
138
139 return return_op;
140}
141
142
153template <typename Range, typename Domain, typename Payload>
158{
159 LinearOperator<Range, Domain, Payload> return_op = exemplar;
160
161 return_op.vmult_add = [&constraints](Range &v, const Domain &u) {
162 const auto &locally_owned_elements = v.locally_owned_elements();
163 for (const auto &line : constraints.get_lines())
164 {
165 const auto i = line.index;
166 if (locally_owned_elements.is_element(i))
167 {
168 v(i) += u(i);
169 }
170 }
171
172 v.compress(VectorOperation::add);
173 };
174
175 return_op.Tvmult_add = [&constraints](Domain &v, const Range &u) {
176 const auto &locally_owned_elements = v.locally_owned_elements();
177 for (const auto &line : constraints.get_lines())
178 {
179 const auto i = line.index;
180 if (locally_owned_elements.is_element(i))
181 {
182 v(i) += u(i);
183 }
184 }
185
186 v.compress(VectorOperation::add);
187 };
188
189 return_op.vmult = [vmult_add = return_op.vmult_add](Range &v,
190 const Domain &u) {
191 v = 0.;
192 vmult_add(v, u);
193 };
194
195 return_op.Tvmult = [Tvmult_add = return_op.Tvmult_add](Domain &v,
196 const Range &u) {
197 v = 0.;
198 Tvmult_add(v, u);
199 };
200
201 return return_op;
202}
203
204
241template <typename Range, typename Domain, typename Payload>
246{
247 const auto C = distribute_constraints_linear_operator(constraints, linop);
248 const auto Ct = transpose_operator(C);
249 const auto Id_c = project_to_constrained_linear_operator(constraints, linop);
250 return Ct * linop * C + Id_c;
251}
252
253
287template <typename Range, typename Domain, typename Payload>
292 const Range &right_hand_side)
293{
294 PackagedOperation<Range> return_comp;
295
296 return_comp.reinit_vector = linop.reinit_range_vector;
297
298 return_comp.apply_add = [&constraints, &linop, &right_hand_side](Range &v) {
299 const auto C = distribute_constraints_linear_operator(constraints, linop);
300 const auto Ct = transpose_operator(C);
301
302 GrowingVectorMemory<Domain> vector_memory;
303 typename VectorMemory<Domain>::Pointer k(vector_memory);
304 linop.reinit_domain_vector(*k, /*bool fast=*/false);
305 constraints.distribute(*k);
306
307 v += Ct * (right_hand_side - linop * *k);
308 };
309
310 return_comp.apply = [apply_add = return_comp.apply_add](Range &v) {
311 v = 0.;
312 apply_add(v);
313 };
314
315 return return_comp;
316}
317
321
322#endif
LineRange get_lines() const
void distribute(VectorType &vec) const
std::function< void(Range &v, const Domain &u)> vmult_add
std::function< void(Domain &v, const Range &u)> Tvmult
std::function< void(Domain &v, bool omit_zeroing_entries)> reinit_domain_vector
std::function< void(Range &v, const Domain &u)> vmult
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(Range &v, bool omit_zeroing_entries)> reinit_vector
std::function< void(Range &v)> apply
std::function< void(Range &v)> apply_add
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:38
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:39
#define Assert(cond, exc)
static ::ExceptionBase & ExcMessage(std::string arg1)
LinearOperator< Domain, Range, Payload > transpose_operator(const LinearOperator< Range, Domain, Payload > &op)
PackagedOperation< Range > constrained_right_hand_side(const AffineConstraints< typename Range::value_type > &constraints, const LinearOperator< Range, Domain, Payload > &linop, const Range &right_hand_side)
LinearOperator< Range, Domain, Payload > constrained_linear_operator(const AffineConstraints< typename Range::value_type > &constraints, const LinearOperator< Range, Domain, Payload > &linop)
LinearOperator< Range, Domain, Payload > project_to_constrained_linear_operator(const AffineConstraints< typename Range::value_type > &constraints, const LinearOperator< Range, Domain, Payload > &exemplar)
LinearOperator< Range, Domain, Payload > distribute_constraints_linear_operator(const AffineConstraints< typename Range::value_type > &constraints, const LinearOperator< Range, Domain, Payload > &exemplar)
static bool equal(const T *p1, const T *p2)