Note: this is documentation for an old release. View the latest documentation at docs.fenicsproject.org/dolfinx/v0.9.0/cpp/doxygen/d0/d75/fem_2petsc_8h_source.html
DOLFINx 0.7.3
DOLFINx C++ interface
Loading...
Searching...
No Matches
petsc.h
1// Copyright (C) 2018-2021 Garth N. Wells
2//
3// This file is part of DOLFINx (https://www.fenicsproject.org)
4//
5// SPDX-License-Identifier: LGPL-3.0-or-later
6
7#pragma once
8
9#include "Form.h"
10#include "assembler.h"
11#include "utils.h"
12#include <concepts>
13#include <dolfinx/la/petsc.h>
14#include <map>
15#include <memory>
16#include <petscmat.h>
17#include <petscvec.h>
18#include <span>
19#include <utility>
20#include <vector>
21
22namespace dolfinx::common
23{
24class IndexMap;
25}
26
27namespace dolfinx::fem
28{
29template <dolfinx::scalar T, std::floating_point U>
30class DirichletBC;
31
33namespace petsc
34{
41template <std::floating_point T>
43 const std::string& type = std::string())
44{
46 pattern.finalize();
47 return la::petsc::create_matrix(a.mesh()->comm(), pattern, type);
48}
49
58template <std::floating_point T>
60 const std::vector<std::vector<const Form<PetscScalar, T>*>>& a,
61 const std::string& type = std::string())
62{
63 // Extract and check row/column ranges
64 std::array<std::vector<std::shared_ptr<const FunctionSpace<T>>>, 2> V
66 std::array<std::vector<int>, 2> bs_dofs;
67 for (std::size_t i = 0; i < 2; ++i)
68 {
69 for (auto& _V : V[i])
70 bs_dofs[i].push_back(_V->dofmap()->bs());
71 }
72
73 // Build sparsity pattern for each block
74 std::shared_ptr<const mesh::Mesh<T>> mesh;
75 std::vector<std::vector<std::unique_ptr<la::SparsityPattern>>> patterns(
76 V[0].size());
77 for (std::size_t row = 0; row < V[0].size(); ++row)
78 {
79 for (std::size_t col = 0; col < V[1].size(); ++col)
80 {
81 if (const Form<PetscScalar, T>* form = a[row][col]; form)
82 {
83 patterns[row].push_back(std::make_unique<la::SparsityPattern>(
85 if (!mesh)
86 mesh = form->mesh();
87 }
88 else
89 patterns[row].push_back(nullptr);
90 }
91 }
92
93 if (!mesh)
94 throw std::runtime_error("Could not find a Mesh.");
95
96 // Compute offsets for the fields
97 std::array<std::vector<std::pair<
98 std::reference_wrapper<const common::IndexMap>, int>>,
99 2>
100 maps;
101 for (std::size_t d = 0; d < 2; ++d)
102 {
103 for (auto space : V[d])
104 {
105 maps[d].emplace_back(*space->dofmap()->index_map,
106 space->dofmap()->index_map_bs());
107 }
108 }
109
110 // Create merged sparsity pattern
111 std::vector<std::vector<const la::SparsityPattern*>> p(V[0].size());
112 for (std::size_t row = 0; row < V[0].size(); ++row)
113 for (std::size_t col = 0; col < V[1].size(); ++col)
114 p[row].push_back(patterns[row][col].get());
115
116 la::SparsityPattern pattern(mesh->comm(), p, maps, bs_dofs);
117 pattern.finalize();
118
119 // FIXME: Add option to pass customised local-to-global map to PETSc
120 // Mat constructor
121
122 // Initialise matrix
123 Mat A = la::petsc::create_matrix(mesh->comm(), pattern, type);
124
125 // Create row and column local-to-global maps (field0, field1, field2,
126 // etc), i.e. ghosts of field0 appear before owned indices of field1
127 std::array<std::vector<PetscInt>, 2> _maps;
128 for (int d = 0; d < 2; ++d)
129 {
130 // FIXME: Index map concatenation has already been computed inside
131 // the SparsityPattern constructor, but we also need it here to
132 // build the PETSc local-to-global map. Compute outside and pass
133 // into SparsityPattern constructor.
134
135 // FIXME: avoid concatenating the same maps twice in case that V[0]
136 // == V[1].
137
138 // Concatenate the block index map in the row and column directions
139 auto [rank_offset, local_offset, ghosts, _]
140 = common::stack_index_maps(maps[d]);
141 for (std::size_t f = 0; f < maps[d].size(); ++f)
142 {
143 const common::IndexMap& map = maps[d][f].first.get();
144 const int bs = maps[d][f].second;
145 const std::int32_t size_local = bs * map.size_local();
146 const std::vector global = map.global_indices();
147 for (std::int32_t i = 0; i < size_local; ++i)
148 _maps[d].push_back(i + rank_offset + local_offset[f]);
149 for (std::size_t i = size_local; i < bs * global.size(); ++i)
150 _maps[d].push_back(ghosts[f][i - size_local]);
151 }
152 }
153
154 // Create PETSc local-to-global map/index sets and attach to matrix
155 ISLocalToGlobalMapping petsc_local_to_global0;
156 ISLocalToGlobalMappingCreate(MPI_COMM_SELF, 1, _maps[0].size(),
157 _maps[0].data(), PETSC_COPY_VALUES,
158 &petsc_local_to_global0);
159 if (V[0] == V[1])
160 {
161 MatSetLocalToGlobalMapping(A, petsc_local_to_global0,
162 petsc_local_to_global0);
163 ISLocalToGlobalMappingDestroy(&petsc_local_to_global0);
164 }
165 else
166 {
167
168 ISLocalToGlobalMapping petsc_local_to_global1;
169 ISLocalToGlobalMappingCreate(MPI_COMM_SELF, 1, _maps[1].size(),
170 _maps[1].data(), PETSC_COPY_VALUES,
171 &petsc_local_to_global1);
172 MatSetLocalToGlobalMapping(A, petsc_local_to_global0,
173 petsc_local_to_global1);
174 ISLocalToGlobalMappingDestroy(&petsc_local_to_global0);
175 ISLocalToGlobalMappingDestroy(&petsc_local_to_global1);
176 }
177
178 return A;
179}
180
184template <std::floating_point T>
186 const std::vector<std::vector<const Form<PetscScalar, T>*>>& a,
187 const std::vector<std::vector<std::string>>& types)
188{
189 // Extract and check row/column ranges
191
192 std::vector<std::vector<std::string>> _types(
193 a.size(), std::vector<std::string>(a.front().size()));
194 if (!types.empty())
195 _types = types;
196
197 // Loop over each form and create matrix
198 int rows = a.size();
199 int cols = a.front().size();
200 std::vector<Mat> mats(rows * cols, nullptr);
201 std::shared_ptr<const mesh::Mesh<T>> mesh;
202 for (int i = 0; i < rows; ++i)
203 {
204 for (int j = 0; j < cols; ++j)
205 {
206 if (const Form<PetscScalar, T>* form = a[i][j]; form)
207 {
208 mats[i * cols + j] = create_matrix(*form, _types[i][j]);
209 mesh = form->mesh();
210 }
211 }
212 }
213
214 if (!mesh)
215 throw std::runtime_error("Could not find a Mesh.");
216
217 // Initialise block (MatNest) matrix
218 Mat A;
219 MatCreate(mesh->comm(), &A);
220 MatSetType(A, MATNEST);
221 MatNestSetSubMats(A, rows, nullptr, cols, nullptr, mats.data());
222 MatSetUp(A);
223
224 // De-reference Mat objects
225 for (std::size_t i = 0; i < mats.size(); ++i)
226 {
227 if (mats[i])
228 MatDestroy(&mats[i]);
229 }
230
231 return A;
232}
233
238 const std::vector<
239 std::pair<std::reference_wrapper<const common::IndexMap>, int>>& maps);
240
243 const std::vector<
244 std::pair<std::reference_wrapper<const common::IndexMap>, int>>& maps);
245
246// -- Vectors ----------------------------------------------------------------
247
260template <std::floating_point T>
262 Vec b, const Form<PetscScalar, T>& L,
263 std::span<const PetscScalar> constants,
264 const std::map<std::pair<IntegralType, int>,
265 std::pair<std::span<const PetscScalar>, int>>& coeffs)
266{
267 Vec b_local;
268 VecGhostGetLocalForm(b, &b_local);
269 PetscInt n = 0;
270 VecGetSize(b_local, &n);
271 PetscScalar* array = nullptr;
272 VecGetArray(b_local, &array);
273 std::span<PetscScalar> _b(array, n);
274 fem::assemble_vector(_b, L, constants, coeffs);
275 VecRestoreArray(b_local, &array);
276 VecGhostRestoreLocalForm(b, &b_local);
277}
278
288template <std::floating_point T>
290{
291 Vec b_local;
292 VecGhostGetLocalForm(b, &b_local);
293 PetscInt n = 0;
294 VecGetSize(b_local, &n);
295 PetscScalar* array = nullptr;
296 VecGetArray(b_local, &array);
297 std::span<PetscScalar> _b(array, n);
299 VecRestoreArray(b_local, &array);
300 VecGhostRestoreLocalForm(b, &b_local);
301}
302
303// FIXME: clarify how x0 is used
304// FIXME: if bcs entries are set
305
306// FIXME: need to pass an array of Vec for x0?
307// FIXME: clarify zeroing of vector
308
324template <std::floating_point T>
326 Vec b, const std::vector<std::shared_ptr<const Form<PetscScalar, T>>>& a,
327 const std::vector<std::span<const PetscScalar>>& constants,
328 const std::vector<std::map<std::pair<IntegralType, int>,
329 std::pair<std::span<const PetscScalar>, int>>>&
330 coeffs,
331 const std::vector<
332 std::vector<std::shared_ptr<const DirichletBC<PetscScalar, T>>>>& bcs1,
333 const std::vector<Vec>& x0, PetscScalar scale)
334{
335 Vec b_local;
336 VecGhostGetLocalForm(b, &b_local);
337 PetscInt n = 0;
338 VecGetSize(b_local, &n);
339 PetscScalar* array = nullptr;
340 VecGetArray(b_local, &array);
341 std::span<PetscScalar> _b(array, n);
342
343 if (x0.empty())
344 fem::apply_lifting(_b, a, constants, coeffs, bcs1, {}, scale);
345 else
346 {
347 std::vector<std::span<const PetscScalar>> x0_ref;
348 std::vector<Vec> x0_local(a.size());
349 std::vector<const PetscScalar*> x0_array(a.size());
350 for (std::size_t i = 0; i < a.size(); ++i)
351 {
352 assert(x0[i]);
353 VecGhostGetLocalForm(x0[i], &x0_local[i]);
354 PetscInt n = 0;
355 VecGetSize(x0_local[i], &n);
356 VecGetArrayRead(x0_local[i], &x0_array[i]);
357 x0_ref.emplace_back(x0_array[i], n);
358 }
359
360 std::vector x0_tmp(x0_ref.begin(), x0_ref.end());
361 fem::apply_lifting(_b, a, constants, coeffs, bcs1, x0_tmp, scale);
362
363 for (std::size_t i = 0; i < x0_local.size(); ++i)
364 {
365 VecRestoreArrayRead(x0_local[i], &x0_array[i]);
366 VecGhostRestoreLocalForm(x0[i], &x0_local[i]);
367 }
368 }
369
370 VecRestoreArray(b_local, &array);
371 VecGhostRestoreLocalForm(b, &b_local);
372}
373
374// FIXME: clarify how x0 is used
375// FIXME: if bcs entries are set
376
377// FIXME: need to pass an array of Vec for x0?
378// FIXME: clarify zeroing of vector
379
392template <std::floating_point T>
394 Vec b,
395 const std::vector<std::shared_ptr<const Form<PetscScalar, double>>>& a,
396 const std::vector<
397 std::vector<std::shared_ptr<const DirichletBC<PetscScalar, double>>>>&
398 bcs1,
399 const std::vector<Vec>& x0, PetscScalar scale)
400{
401 Vec b_local;
402 VecGhostGetLocalForm(b, &b_local);
403 PetscInt n = 0;
404 VecGetSize(b_local, &n);
405 PetscScalar* array = nullptr;
406 VecGetArray(b_local, &array);
407 std::span<PetscScalar> _b(array, n);
408
409 if (x0.empty())
410 fem::apply_lifting<PetscScalar>(_b, a, bcs1, {}, scale);
411 else
412 {
413 std::vector<std::span<const PetscScalar>> x0_ref;
414 std::vector<Vec> x0_local(a.size());
415 std::vector<const PetscScalar*> x0_array(a.size());
416 for (std::size_t i = 0; i < a.size(); ++i)
417 {
418 assert(x0[i]);
419 VecGhostGetLocalForm(x0[i], &x0_local[i]);
420 PetscInt n = 0;
421 VecGetSize(x0_local[i], &n);
422 VecGetArrayRead(x0_local[i], &x0_array[i]);
423 x0_ref.emplace_back(x0_array[i], n);
424 }
425
426 std::vector x0_tmp(x0_ref.begin(), x0_ref.end());
427 fem::apply_lifting<PetscScalar>(_b, a, bcs1, x0_tmp, scale);
428
429 for (std::size_t i = 0; i < x0_local.size(); ++i)
430 {
431 VecRestoreArrayRead(x0_local[i], &x0_array[i]);
432 VecGhostRestoreLocalForm(x0[i], &x0_local[i]);
433 }
434 }
435
436 VecRestoreArray(b_local, &array);
437 VecGhostRestoreLocalForm(b, &b_local);
438}
439
440// -- Setting bcs ------------------------------------------------------------
441
442// FIXME: Move these function elsewhere?
443
444// FIXME: clarify x0
445// FIXME: clarify what happens with ghosts
446
450template <std::floating_point T>
452 Vec b,
453 const std::vector<std::shared_ptr<const DirichletBC<PetscScalar, T>>>& bcs,
454 const Vec x0, PetscScalar scale = 1)
455{
456 PetscInt n = 0;
457 VecGetLocalSize(b, &n);
458 PetscScalar* array = nullptr;
459 VecGetArray(b, &array);
460 std::span<PetscScalar> _b(array, n);
461 if (x0)
462 {
463 Vec x0_local;
464 VecGhostGetLocalForm(x0, &x0_local);
465 PetscInt n = 0;
466 VecGetSize(x0_local, &n);
467 const PetscScalar* array = nullptr;
468 VecGetArrayRead(x0_local, &array);
469 std::span<const PetscScalar> _x0(array, n);
470 fem::set_bc(_b, bcs, _x0, scale);
471 VecRestoreArrayRead(x0_local, &array);
472 VecGhostRestoreLocalForm(x0, &x0_local);
473 }
474 else
475 fem::set_bc(_b, bcs, scale);
476
477 VecRestoreArray(b, &array);
478}
479
480} // namespace petsc
481} // namespace dolfinx::fem
This class represents the distribution index arrays across processes. An index array is a contiguous ...
Definition IndexMap.h:64
std::int32_t size_local() const noexcept
Number of indices owned by this process.
Definition IndexMap.cpp:391
std::vector< std::int64_t > global_indices() const
Build list of indices with global indexing.
Definition IndexMap.cpp:448
Object for setting (strong) Dirichlet boundary conditions.
Definition DirichletBC.h:251
A representation of finite element variational forms.
Definition Form.h:66
std::shared_ptr< const mesh::Mesh< U > > mesh() const
Extract common mesh for the form.
Definition Form.h:138
Sparsity pattern data structure that can be used to initialize sparse matrices. After assembly,...
Definition SparsityPattern.h:26
void finalize()
Finalize sparsity pattern and communicate off-process entries.
Definition SparsityPattern.cpp:226
Miscellaneous classes, functions and types.
Definition dolfinx_common.h:8
std::tuple< std::int64_t, std::vector< std::int32_t >, std::vector< std::vector< std::int64_t > >, std::vector< std::vector< int > > > stack_index_maps(const std::vector< std::pair< std::reference_wrapper< const common::IndexMap >, int > > &maps)
Compute layout data and ghost indices for a stacked (concatenated) index map, i.e....
Definition IndexMap.cpp:145
void set_bc(Vec b, const std::vector< std::shared_ptr< const DirichletBC< PetscScalar, T > > > &bcs, const Vec x0, PetscScalar scale=1)
Set bc values in owned (local) part of the PETSc vector, multiplied by 'scale'. The vectors b and x0 ...
Definition petsc.h:451
void apply_lifting(Vec b, const std::vector< std::shared_ptr< const Form< PetscScalar, T > > > &a, const std::vector< std::span< const PetscScalar > > &constants, const std::vector< std::map< std::pair< IntegralType, int >, std::pair< std::span< const PetscScalar >, int > > > &coeffs, const std::vector< std::vector< std::shared_ptr< const DirichletBC< PetscScalar, T > > > > &bcs1, const std::vector< Vec > &x0, PetscScalar scale)
Modify RHS vector to account for Dirichlet boundary conditions.
Definition petsc.h:325
Mat create_matrix_block(const std::vector< std::vector< const Form< PetscScalar, T > * > > &a, const std::string &type=std::string())
Initialise a monolithic matrix for an array of bilinear forms.
Definition petsc.h:59
void assemble_vector(Vec b, const Form< PetscScalar, T > &L, std::span< const PetscScalar > constants, const std::map< std::pair< IntegralType, int >, std::pair< std::span< const PetscScalar >, int > > &coeffs)
Assemble linear form into an already allocated PETSc vector.
Definition petsc.h:261
Mat create_matrix_nest(const std::vector< std::vector< const Form< PetscScalar, T > * > > &a, const std::vector< std::vector< std::string > > &types)
Create nested (MatNest) matrix.
Definition petsc.h:185
Vec create_vector_block(const std::vector< std::pair< std::reference_wrapper< const common::IndexMap >, int > > &maps)
Initialise monolithic vector. Vector is not zeroed.
Definition petsc.cpp:15
Mat create_matrix(const Form< PetscScalar, T > &a, const std::string &type=std::string())
Create a matrix.
Definition petsc.h:42
Vec create_vector_nest(const std::vector< std::pair< std::reference_wrapper< const common::IndexMap >, int > > &maps)
Create nested (VecNest) vector. Vector is not zeroed.
Definition petsc.cpp:60
Finite element method functionality.
Definition assemble_matrix_impl.h:25
void assemble_vector(std::span< T > b, const Form< T, U > &L, std::span< const T > constants, const std::map< std::pair< IntegralType, int >, std::pair< std::span< const T >, int > > &coefficients)
Assemble linear form into a vector.
Definition assembler.h:109
void apply_lifting(std::span< T > b, const std::vector< std::shared_ptr< const Form< T, U > > > &a, const std::vector< std::span< const T > > &constants, const std::vector< std::map< std::pair< IntegralType, int >, std::pair< std::span< const T >, int > > > &coeffs, const std::vector< std::vector< std::shared_ptr< const DirichletBC< T, U > > > > &bcs1, const std::vector< std::span< const T > > &x0, T scale)
Modify b such that:
Definition assembler.h:150
std::vector< std::vector< std::array< std::shared_ptr< const FunctionSpace< U > >, 2 > > > extract_function_spaces(const std::vector< std::vector< const Form< T, U > * > > &a)
Extract test (0) and trial (1) function spaces pairs for each bilinear form for a rectangular array o...
Definition utils.h:135
void set_bc(std::span< T > b, const std::vector< std::shared_ptr< const DirichletBC< T, U > > > &bcs, std::span< const T > x0, T scale=1)
Set bc values in owned (local) part of the vector, multiplied by 'scale'. The vectors b and x0 must h...
Definition assembler.h:438
la::SparsityPattern create_sparsity_pattern(const Form< T, U > &a)
Create a sparsity pattern for a given form.
Definition utils.h:160
std::array< std::vector< std::shared_ptr< const FunctionSpace< T > > >, 2 > common_function_spaces(const std::vector< std::vector< std::array< std::shared_ptr< const FunctionSpace< T > >, 2 > > > &V)
Extract FunctionSpaces for (0) rows blocks and (1) columns blocks from a rectangular array of (test,...
Definition FunctionSpace.h:343
Mat create_matrix(MPI_Comm comm, const SparsityPattern &sp, const std::string &type=std::string())
Create a PETSc Mat. Caller is responsible for destroying the returned object.
Definition petsc.cpp:232