deal.II version GIT relicensing-7058-gb35ee29762 2026-11-11 09:30: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 - 2026 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
71template <typename Range, typename Domain, typename Payload>
76{
77 LinearOperator<Range, Domain, Payload> return_op = exemplar;
78
79 return_op.vmult_add = [&constraints](Range &v, const Domain &u) {
81 ::ExcMessage("The domain and range vectors must be different "
82 "storage locations"));
83
84 // First, add vector u to v unconditionally and clean up constrained
85 // degrees of freedom later.
86 v += u;
87
88 const auto &locally_owned_elements = v.locally_owned_elements();
89 for (const auto &line : constraints.get_lines())
90 {
91 const auto i = line.index;
92 if (locally_owned_elements.is_element(i))
93 {
94 v(i) -= u(i);
95 const auto &entries = line.entries;
96 for (types::global_dof_index j = 0; j < entries.size(); ++j)
97 {
98 const auto pos = entries[j].first;
99 v(i) += u(pos) * entries[j].second;
100 }
101 }
102 }
103
104 v.compress(VectorOperation::add);
105 };
106
107 return_op.Tvmult_add = [&constraints](Domain &v, const Range &u) {
109 ::ExcMessage("The domain and range vectors must be different "
110 "storage locations"));
111
112 // First, add vector u to v unconditionally and clean up constrained
113 // degrees of freedom later.
114 v += u;
115
116 const auto &locally_owned_elements = v.locally_owned_elements();
117 for (const auto &line : constraints.get_lines())
118 {
119 const auto i = line.index;
120
121 if (locally_owned_elements.is_element(i))
122 {
123 v(i) -= u(i);
124 }
125
126 const auto &entries = line.entries;
127 for (types::global_dof_index j = 0; j < entries.size(); ++j)
128 {
129 const auto pos = entries[j].first;
130 if (locally_owned_elements.is_element(pos))
131 v(pos) += u(i) * entries[j].second;
132 }
133 }
134
135 v.compress(VectorOperation::add);
136 };
137
138 return_op.vmult = [vmult_add = return_op.vmult_add](Range &v,
139 const Domain &u) {
140 v = 0.;
141 vmult_add(v, u);
142 };
143
144 return_op.Tvmult = [Tvmult_add = return_op.Tvmult_add](Domain &v,
145 const Range &u) {
146 v = 0.;
147 Tvmult_add(v, u);
148 };
149
150 return return_op;
151}
152
153
164template <typename Range, typename Domain, typename Payload>
169{
170 LinearOperator<Range, Domain, Payload> return_op = exemplar;
171
172 return_op.vmult_add = [&constraints](Range &v, const Domain &u) {
173 const auto &locally_owned_elements = v.locally_owned_elements();
174 for (const auto &line : constraints.get_lines())
175 {
176 const auto i = line.index;
177 if (locally_owned_elements.is_element(i))
178 {
179 v(i) += u(i);
180 }
181 }
182
183 v.compress(VectorOperation::add);
184 };
185
186 return_op.Tvmult_add = [&constraints](Domain &v, const Range &u) {
187 const auto &locally_owned_elements = v.locally_owned_elements();
188 for (const auto &line : constraints.get_lines())
189 {
190 const auto i = line.index;
191 if (locally_owned_elements.is_element(i))
192 {
193 v(i) += u(i);
194 }
195 }
196
197 v.compress(VectorOperation::add);
198 };
199
200 return_op.vmult = [vmult_add = return_op.vmult_add](Range &v,
201 const Domain &u) {
202 v = 0.;
203 vmult_add(v, u);
204 };
205
206 return_op.Tvmult = [Tvmult_add = return_op.Tvmult_add](Domain &v,
207 const Range &u) {
208 v = 0.;
209 Tvmult_add(v, u);
210 };
211
212 return return_op;
213}
214
215
256template <typename Range, typename Domain, typename Payload>
261{
262 const auto C = distribute_constraints_linear_operator(constraints, linop);
263 const auto Ct = transpose_operator(C);
264 const auto Id_c = project_to_constrained_linear_operator(constraints, linop);
265 return Ct * linop * C + Id_c;
266}
267
268
306template <typename Range, typename Domain, typename Payload>
311 const Range &right_hand_side)
312{
313 PackagedOperation<Range> return_comp;
314
315 return_comp.reinit_vector = linop.reinit_range_vector;
316
317 return_comp.apply_add = [&constraints, &linop, &right_hand_side](Range &v) {
318 const auto C = distribute_constraints_linear_operator(constraints, linop);
319 const auto Ct = transpose_operator(C);
320
321 GrowingVectorMemory<Domain> vector_memory;
322 typename VectorMemory<Domain>::Pointer k(vector_memory);
323 linop.reinit_domain_vector(*k, /*bool fast=*/false);
324 constraints.distribute(*k);
325
326 v += Ct * (right_hand_side - linop * *k);
327 };
328
329 return_comp.apply = [apply_add = return_comp.apply_add](Range &v) {
330 v = 0.;
331 apply_add(v);
332 };
333
334 return return_comp;
335}
336
340
341#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)