DOLFINx 0.12.0.0
DOLFINx C++
Loading...
Searching...
No Matches
sparsitypattern.h
Go to the documentation of this file.
1// Copyright (C) 2013-2026 Johan Hake, Jan Blechta, Garth N. Wells and Paul T.
2// Kühner
3//
4// This file is part of DOLFINx (https://www.fenicsproject.org)
5//
6// SPDX-License-Identifier: LGPL-3.0-or-later
7
8#pragma once
9
10#include "DofMap.h"
11#include "Form.h"
12#include "FunctionSpace.h"
13#include "sparsitybuild.h"
14#include <array>
15#include <concepts>
16#include <cstddef>
17#include <dolfinx/common/Timer.h>
18#include <dolfinx/la/SparsityPattern.h>
19#include <functional>
20#include <memory>
21#include <set>
22#include <span>
23#include <stdexcept>
24#include <utility>
25#include <vector>
26
29
30namespace dolfinx::fem
31{
39template <dolfinx::scalar T, std::floating_point U>
40std::vector<std::vector<std::array<std::shared_ptr<const FunctionSpace<U>>, 2>>>
41extract_function_spaces(const std::vector<std::vector<const Form<T, U>*>>& a)
42{
43 std::vector<
44 std::vector<std::array<std::shared_ptr<const FunctionSpace<U>>, 2>>>
45 spaces(
46 a.size(),
47 std::vector<std::array<std::shared_ptr<const FunctionSpace<U>>, 2>>(
48 a.front().size()));
49 for (std::size_t i = 0; i < a.size(); ++i)
50 {
51 for (std::size_t j = 0; j < a[i].size(); ++j)
52 {
53 if (const Form<T, U>* form = a[i][j]; form)
54 spaces[i][j] = {form->function_spaces()[0], form->function_spaces()[1]};
55 }
56 }
57 return spaces;
58}
59
65template <dolfinx::scalar T, std::floating_point U>
67{
68 std::shared_ptr mesh = a.mesh();
69 assert(mesh);
70
71 // Get index maps and block sizes from the DOF maps. Note that in
72 // mixed-topology meshes, despite there being multiple DOF maps, the
73 // index maps and block sizes are the same.
74 std::array<std::reference_wrapper<const DofMap>, 2> dofmaps{
75 *a.function_spaces().at(0)->dofmaps().front(),
76 *a.function_spaces().at(1)->dofmaps().front()};
77
78 const std::array index_maps{dofmaps[0].get().index_map,
79 dofmaps[1].get().index_map};
80 const std::array bs
81 = {dofmaps[0].get().index_map_bs(), dofmaps[1].get().index_map_bs()};
82
83 la::SparsityPattern pattern(mesh->comm(), index_maps, bs);
84 build_sparsity_pattern(pattern, a);
85 return pattern;
86}
87
93template <dolfinx::scalar T, std::floating_point U>
95{
96 if (a.rank() != 2)
97 {
98 throw std::invalid_argument(
99 "Cannot create sparsity pattern. Form is not a bilinear.");
100 }
101
102 std::shared_ptr mesh = a.mesh();
103 assert(mesh);
104 std::shared_ptr mesh0 = a.function_spaces().at(0)->mesh();
105 assert(mesh0);
106 std::shared_ptr mesh1 = a.function_spaces().at(1)->mesh();
107 assert(mesh1);
108
109 const std::set<IntegralType> types = a.integral_types();
110 if (types.find(IntegralType::interior_facet) != types.end()
111 or types.find(IntegralType::exterior_facet) != types.end())
112 {
113 // FIXME: cleanup these calls? Some of the happen internally again.
114 int tdim = mesh->topology()->dim();
115 mesh->topology_mutable()->create_entities(tdim - 1);
116 mesh->topology_mutable()->create_connectivity(tdim - 1, tdim);
117 }
118
119 common::Timer t0("Build sparsity");
120
121 auto extract_cells = [](std::span<const std::int32_t> facets)
122 {
123 assert(facets.size() % 2 == 0);
124 std::vector<std::int32_t> cells;
125 cells.reserve(facets.size() / 2);
126 for (std::size_t i = 0; i < facets.size(); i += 2)
127 cells.push_back(facets[i]);
128 return cells;
129 };
130
131 const int num_cell_types = mesh->topology()->cell_types().size();
132 for (int cell_type_idx = 0; cell_type_idx < num_cell_types; ++cell_type_idx)
133 {
134 std::array<std::reference_wrapper<const DofMap>, 2> dofmaps{
135 *a.function_spaces().at(0)->dofmaps().at(cell_type_idx),
136 *a.function_spaces().at(1)->dofmaps().at(cell_type_idx)};
137
138 // Create and build sparsity pattern
139 for (auto type : types)
140 {
141 switch (type)
142 {
144 for (int i = 0; i < a.num_integrals(type, cell_type_idx); ++i)
145 {
147 pattern,
148 std::pair{a.domain_arg(type, 0, i, cell_type_idx),
149 a.domain_arg(type, 1, i, cell_type_idx)},
150 {{dofmaps[0], dofmaps[1]}});
151 }
152 break;
154 for (int i = 0; i < a.num_integrals(type, cell_type_idx); ++i)
155 {
157 pattern,
158 {extract_cells(a.domain_arg(type, 0, i, 0)),
159 extract_cells(a.domain_arg(type, 1, i, 0))},
160 {{dofmaps[0], dofmaps[1]}});
161 }
162 break;
166 for (int i = 0; i < a.num_integrals(type, cell_type_idx); ++i)
167 {
169 pattern,
170 std::pair{extract_cells(a.domain_arg(type, 0, i, 0)),
171 extract_cells(a.domain_arg(type, 1, i, 0))},
172 {{dofmaps[0], dofmaps[1]}});
173 }
174 break;
175 default:
176 throw std::invalid_argument("Unsupported integral type");
177 }
178 }
179 }
180
181 t0.stop();
182}
183} // namespace dolfinx::fem
Degree-of-freedom map representations and tools.
Timer for measuring and logging elapsed time durations.
Definition Timer.h:41
std::chrono::duration< double, Period > stop()
Stop timer and return elapsed time.
Definition Timer.h:128
A representation of finite element variational forms.
Definition Form.h:177
int num_integrals(IntegralType type, int kernel_idx) const
Get number of integrals (kernels) for a given integral type and kernel index.
Definition Form.h:542
int rank() const
Rank of the form.
Definition Form.h:455
std::shared_ptr< const mesh::Mesh< geometry_type > > mesh() const
Common mesh for the form (the 'integration domain').
Definition Form.h:459
std::set< IntegralType > integral_types() const
Get types of integrals in the form.
Definition Form.h:492
const std::vector< std::shared_ptr< const FunctionSpace< geometry_type > > > & function_spaces() const
Function spaces for all arguments.
Definition Form.h:467
std::span< const std::int32_t > domain_arg(IntegralType type, int rank, int idx, int kernel_idx) const
Argument function mesh integration entity indices.
Definition Form.h:630
This class represents a finite element function space defined by a mesh, a finite element,...
Definition FunctionSpace.h:35
Definition SparsityPattern.h:28
void interior_facets(la::SparsityPattern &pattern, std::array< std::span< const std::int32_t >, 2 > cells, std::array< std::reference_wrapper< const DofMap >, 2 > dofmaps)
Iterate over interior facets and insert entries into sparsity pattern.
Definition sparsitybuild.cpp:16
void cells(la::SparsityPattern &pattern, const std::pair< R0, R1 > &cells, std::array< std::reference_wrapper< const DofMap >, 2 > dofmaps)
Iterate over cells and insert entries into sparsity pattern.
Definition sparsitybuild.h:37
Finite element method functionality.
Definition assemble_expression_impl.h:22
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 sparsitypattern.h:41
@ vertex
Vertex.
Definition Form.h:47
@ interior_facet
Interior facet.
Definition Form.h:46
@ ridge
Ridge.
Definition Form.h:48
@ cell
Cell.
Definition Form.h:44
@ exterior_facet
Exterior facet.
Definition Form.h:45
la::SparsityPattern create_sparsity_pattern(const Form< T, U > &a)
Create a sparsity pattern for a given form.
Definition sparsitypattern.h:66
void build_sparsity_pattern(la::SparsityPattern &pattern, const Form< T, U > &a)
Build a sparsity pattern for a given form.
Definition sparsitypattern.h:94
Mesh data structures and algorithms on meshes.
Definition DofMap.h:32