20#include <dolfinx/common/IndexMap.h>
21#include <dolfinx/la/petsc.h>
39template <dolfinx::scalar T, std::
floating_po
int U>
55template <std::
floating_po
int T>
57 const std::optional<std::string>& type)
59 if (!type or *type != MATIS)
62 auto topology =
mesh.topology();
64 std::shared_ptr<const common::IndexMap> cells
65 = topology->index_map(topology->dim());
67 if (cells->num_ghosts() > 0)
69 throw std::invalid_argument(
70 "A MATIS matrix requires one non-overlapping subdomain per process. "
71 "Create the mesh with GhostMode::none.");
85template <std::
floating_po
int T>
87 std::optional<std::string> type = std::nullopt)
89 impl::check_matis_mesh(*a.
mesh(), type);
107template <std::
floating_po
int T>
110 std::optional<std::string> type = std::nullopt)
113 std::array<std::vector<std::shared_ptr<const FunctionSpace<T>>>, 2> V
115 std::array<std::vector<int>, 2> bs_dofs;
116 for (std::size_t i = 0; i < 2; ++i)
118 for (
auto& _V : V[i])
119 bs_dofs[i].push_back(_V->dofmap()->bs());
123 std::shared_ptr<const mesh::Mesh<T>>
mesh;
124 std::vector<std::vector<std::unique_ptr<la::SparsityPattern>>> patterns(
126 for (std::size_t row = 0; row < V[0].size(); ++row)
128 for (std::size_t col = 0; col < V[1].size(); ++col)
132 patterns[row].push_back(std::make_unique<la::SparsityPattern>(
138 patterns[row].push_back(
nullptr);
143 throw std::invalid_argument(
"Could not find a Mesh.");
145 impl::check_matis_mesh(*
mesh, type);
148 std::array<std::vector<std::pair<
149 std::reference_wrapper<const common::IndexMap>,
int>>,
152 for (std::size_t d = 0; d < 2; ++d)
154 for (
auto& space : V[d])
156 maps[d].emplace_back(*space->dofmap()->index_map,
157 space->dofmap()->index_map_bs());
162 std::vector<std::vector<const la::SparsityPattern*>> p(V[0].size());
163 for (std::size_t row = 0; row < V[0].size(); ++row)
164 for (std::size_t col = 0; col < V[1].size(); ++col)
165 p[row].push_back(patterns[row][col].get());
177 std::array<std::vector<PetscInt>, 2> _maps;
178 for (
int d = 0; d < 2; ++d)
180 if (d == 1 and V[0] == V[1])
191 std::pair<std::reference_wrapper<const common::IndexMap>,
int>>& map
193 std::vector<PetscInt>& _map = _maps[d];
196 const auto [rank_offset, local_offset, ghosts, _]
198 const std::size_t num_ghosts
199 = std::accumulate(ghosts.begin(), ghosts.end(), std::size_t(0),
200 [](std::size_t n,
auto& g) { return n + g.size(); });
201 _map.reserve(local_offset.back() + num_ghosts);
202 for (std::size_t f = 0; f < map.size(); ++f)
204 auto offset = local_offset[f];
206 int bs = map[f].second;
208 = std::views::iota(std::int32_t(0), bs * imap.
size_local())
209 | std::views::transform([offset, rank_offset](std::int32_t i)
210 {
return i + rank_offset + offset; });
211 _map.insert(_map.end(), owned.begin(), owned.end());
212 _map.insert(_map.end(), ghosts[f].begin(), ghosts[f].end());
218 ISLocalToGlobalMapping l2g0 =
nullptr, l2g1 =
nullptr;
220 ISLocalToGlobalMappingCreate(
mesh->comm(), 1, _maps[0].size(),
221 _maps[0].data(), PETSC_COPY_VALUES, &l2g0),
222 "ISLocalToGlobalMappingCreate");
226 ISLocalToGlobalMappingCreate(
mesh->comm(), 1, _maps[1].size(),
227 _maps[1].data(), PETSC_COPY_VALUES, &l2g1),
228 "ISLocalToGlobalMappingCreate");
236 "ISLocalToGlobalMappingDestroy");
240 "ISLocalToGlobalMappingDestroy");
249template <std::
floating_po
int T>
252 std::optional<std::vector<std::vector<std::optional<std::string>>>> types)
256 throw std::invalid_argument(
257 "Rectangular array of forms must be non-empty.");
265 int cols = a.front().size();
266 std::vector<Mat> mats(rows * cols,
nullptr);
267 std::shared_ptr<const mesh::Mesh<T>>
mesh;
268 for (
int i = 0; i < rows; ++i)
270 for (
int j = 0; j < cols; ++j)
275 mats[i * cols + j] =
create_matrix(*form, types->at(i).at(j));
284 throw std::invalid_argument(
"Could not find a Mesh.");
296 MatNestSetSubMats(A, rows,
nullptr, cols,
nullptr, mats.data()),
297 "MatNestSetSubMats");
321 std::pair<std::reference_wrapper<const common::IndexMap>,
int>>& maps);
326 std::pair<std::reference_wrapper<const common::IndexMap>,
int>>& maps);
342template <std::
floating_po
int T>
345 std::span<const PetscScalar> constants,
346 const std::map<std::pair<IntegralType, int>,
347 std::pair<std::span<const PetscScalar>,
int>>& coeffs)
351 "VecGhostGetLocalForm");
354 PetscScalar* array =
nullptr;
356 std::span<PetscScalar> _b(array, n);
360 "VecGhostRestoreLocalForm");
373template <std::
floating_po
int T>
378 "VecGhostGetLocalForm");
381 PetscScalar* array =
nullptr;
383 std::span<PetscScalar> _b(array, n);
387 "VecGhostRestoreLocalForm");
425template <std::
floating_po
int T>
430 const std::vector<std::span<const PetscScalar>>& constants,
431 const std::vector<std::map<std::pair<IntegralType, int>,
432 std::pair<std::span<const PetscScalar>,
int>>>&
434 const std::vector<std::span<const std::int8_t>>& bc_markers1,
435 const std::vector<std::span<const PetscScalar>>& bc_values1,
436 const std::vector<Vec>& x0, PetscScalar alpha)
438 if (!x0.empty() and x0.size() != a.size())
439 throw std::invalid_argument(
"Mismatch between x0 and a in apply_lifting.");
443 "VecGhostGetLocalForm");
446 PetscScalar* array =
nullptr;
448 std::span<PetscScalar> _b(array, n);
457 std::vector<std::span<const PetscScalar>> x0_ref;
458 std::vector<Vec> x0_local(a.size());
459 std::vector<const PetscScalar*> x0_array(a.size());
460 for (std::size_t i = 0; i < a.size(); ++i)
464 "VecGhostGetLocalForm");
469 x0_ref.emplace_back(x0_array[i], n0);
475 for (std::size_t i = 0; i < x0_local.size(); ++i)
478 "VecRestoreArrayRead");
480 "VecGhostRestoreLocalForm");
486 "VecGhostRestoreLocalForm");
519template <std::
floating_po
int T>
527 const std::vector<Vec>& x0, PetscScalar alpha)
529 std::vector<std::map<std::pair<IntegralType, int>,
530 std::pair<std::vector<PetscScalar>,
int>>>
532 std::vector<std::vector<PetscScalar>> constants;
533 for (
const auto& _a : a)
539 coeffs.push_back(coefficients);
544 coeffs.emplace_back();
545 constants.emplace_back();
549 std::vector<std::span<const PetscScalar>> _constants(constants.begin(),
551 std::vector<std::map<std::pair<IntegralType, int>,
552 std::pair<std::span<const PetscScalar>,
int>>>
554 std::ranges::transform(coeffs, std::back_inserter(_coeffs),
559 std::vector<std::span<const std::int8_t>>(bc_markers1.begin(),
561 std::vector<std::span<const PetscScalar>>(bc_values1.begin(),
582template <std::
floating_po
int T>
586 std::optional<const Vec> x0, PetscScalar alpha = 1)
590 PetscScalar* array =
nullptr;
592 std::span<PetscScalar> _b(array, n);
597 "VecGhostGetLocalForm");
600 const PetscScalar* x0_array =
nullptr;
603 std::span<const PetscScalar> _x0(x0_array, n0);
605 bc.get().set(_b, _x0, alpha);
607 "VecRestoreArrayRead");
609 "VecGhostRestoreLocalForm");
614 bc.get().set(_b, std::nullopt, alpha);
627template <std::
floating_po
int T>
630 Vec x_local =
nullptr;
632 "VecGhostGetLocalForm");
636 std::span<PetscScalar> _u = u.
x()->array();
637 if (
static_cast<std::size_t
>(n) != _u.size())
639 throw std::invalid_argument(std::format(
640 "Vector has {} local entries, function has {}.", n, _u.size()));
643 const PetscScalar* array =
nullptr;
645 std::ranges::copy(std::span<const PetscScalar>(array, n), _u.begin());
647 "VecRestoreArrayRead");
649 "VecGhostRestoreLocalForm");
678template <std::
floating_po
int T>
679void assemble_operator(Mat A,
const Form<PetscScalar, T>& a,
680 std::span<const std::int8_t> dof_marker0,
681 std::span<const std::int8_t> dof_marker1)
687 if (a.function_spaces()[0]->dofmap()->index_map_bs() == 1
688 and a.function_spaces()[1]->dofmap()->index_map_bs() == 1)
691 dof_marker0, dof_marker1);
696 dof_marker0, dof_marker1);
701 if (a.function_spaces()[0] == a.function_spaces()[1])
704 std::shared_ptr<const DofMap> dofmap0
705 = a.function_spaces()[0]->dofmaps().front();
707 const std::int32_t num_owned
708 = dof_marker0.empty()
710 : dofmap0->index_map_bs() * dofmap0->index_map->size_local();
711 std::vector<std::int32_t> rows;
712 std::ranges::copy_if(
713 std::views::iota(std::int32_t(0), num_owned), std::back_inserter(rows),
714 [&dof_marker0](std::int32_t i) {
return dof_marker0[i] != 0; });
753template <std::
floating_po
int T>
762 "VecGhostUpdateBegin");
764 "VecGhostUpdateEnd");
768 Vec b_local =
nullptr;
770 "VecGhostGetLocalForm");
773 "VecGhostRestoreLocalForm");
780 std::optional<std::reference_wrapper<const Form<PetscScalar, T>>>>
783 a, std::vector<std::vector<
790 apply_lifting(b, a, {std::span<const PetscScalar>(constants)},
792 {std::span<const std::int8_t>(bc_markers1.front())},
793 {std::span<const PetscScalar>(bc_values1.front())}, {x},
797 "VecGhostUpdateBegin");
799 "VecGhostUpdateEnd");
804 PetscScalar* b_array =
nullptr;
806 const PetscScalar* x_array =
nullptr;
810 auto [dofs, owned] = bc.get().dof_indices();
811 for (std::int32_t dof : dofs.first(owned))
812 b_array[dof] = x_array[dof] - bc_values1.front()[dof];
815 "VecRestoreArrayRead");
820 "VecGhostUpdateBegin");
822 "VecGhostUpdateEnd");
858template <std::
floating_po
int T>
868 throw std::invalid_argument(
869 "Preconditioner form must have the same function spaces as the "
874 "VecGhostUpdateBegin");
876 "VecGhostUpdateEnd");
881 std::array<std::vector<std::int8_t>, 2> markers;
882 auto [dof_marker0, dof_marker1]
885 impl::assemble_operator(Jmat, J, dof_marker0, dof_marker1);
887 impl::assemble_operator(Pmat, *P, dof_marker0, dof_marker1);
Functions supporting assembly of a finite element fem::Form.
std::pair< std::vector< std::vector< std::int8_t > >, std::vector< std::vector< T > > > bc_lifting_data(const std::vector< std::optional< std::reference_wrapper< const Form< T, U > > > > &a, const std::vector< std::vector< std::reference_wrapper< const DirichletBC< T, U > > > > &bcs1)
Constrained dof markers and boundary condition values on the trial space of each form in a,...
Definition assembler.h:235
std::array< std::span< const std::int8_t >, 2 > bc_dof_markers_pair(const Form< T, U > &a, const std::vector< std::reference_wrapper< const DirichletBC< T, U > > > &bcs, std::array< std::vector< std::int8_t >, 2 > &storage)
Mark the dofs of the test and trial spaces of a that the boundary conditions in bcs constrain.
Definition assembler.h:215
Distribution of a global index range [0, N) across MPI ranks.
Definition IndexMap.h:191
std::int32_t size_local() const noexcept
Return the number of owned indices.
Definition IndexMap.cpp:1081
Definition DirichletBC.h:261
std::shared_ptr< const la::Vector< value_type > > x() const
Underlying vector (const version).
Definition Function.h:151
Definition SparsityPattern.h:28
void finalize()
Finalize sparsity pattern and communicate off-process entries.
Definition SparsityPattern.cpp:513
static auto set_block_fn(Mat A, InsertMode mode)
Return a function with an interface for adding or inserting values into the matrix A using blocked in...
Definition petsc.h:316
static auto set_fn(Mat A, InsertMode mode)
Return a function with an interface for adding or inserting values into the matrix A (calls MatSetVal...
Definition petsc.h:280
A Mesh consists of a set of connected and numbered mesh topological entities, and geometry data.
Definition Mesh.h:25
void check(PetscErrorCode ierr, std::string_view petsc_function, std::source_location loc=std::source_location::current())
Throw a std::runtime_error via error() if ierr indicates a PETSc call failed.
Definition petsc.h:41
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 IndexMap >, int > > &maps)
Compute layout data for a concatenated index map.
Definition IndexMap.cpp:767
Helper functions for assembly into PETSc data structures.
Definition petsc.h:44
Mat create_matrix(const Form< PetscScalar, T > &a, std::optional< std::string > type=std::nullopt)
Create a matrix.
Definition petsc.h:86
void assemble_jacobian(const Vec x, Mat Jmat, Mat Pmat, const Form< PetscScalar, T > &J, const std::vector< std::reference_wrapper< const DirichletBC< PetscScalar, T > > > &bcs, Function< PetscScalar, T > &u, const Form< PetscScalar, T > *P=nullptr)
Assemble the Jacobian of a nonlinear problem into Jmat, and a preconditioner into Pmat.
Definition petsc.h:859
void apply_lifting(Vec b, const std::vector< std::optional< std::reference_wrapper< 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::span< const std::int8_t > > &bc_markers1, const std::vector< std::span< const PetscScalar > > &bc_values1, const std::vector< Vec > &x0, PetscScalar alpha)
Modify RHS vector to account for Dirichlet boundary conditions, with the constrained dofs and their v...
Definition petsc.h:426
Mat create_matrix_block(const std::vector< std::vector< const Form< PetscScalar, T > * > > &a, std::optional< std::string > type=std::nullopt)
Initialise a monolithic matrix for an array of bilinear forms.
Definition petsc.h:108
Mat create_matrix_nest(const std::vector< std::vector< const Form< PetscScalar, T > * > > &a, std::optional< std::vector< std::vector< std::optional< std::string > > > > types)
Create nested (MatNest) matrix.
Definition petsc.h:250
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:343
void set_bc(Vec b, const std::vector< std::reference_wrapper< const DirichletBC< PetscScalar, T > > > &bcs, std::optional< const Vec > x0, PetscScalar alpha=1)
Entries in b that are constrained by a Dirichlet boundary conditions are set to alpha * (x_bc - x0),...
Definition petsc.h:583
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:21
void assemble_residual(const Vec x, Vec b, const Form< PetscScalar, T > &F, const Form< PetscScalar, T > &J, const std::vector< std::reference_wrapper< const DirichletBC< PetscScalar, T > > > &bcs, Function< PetscScalar, T > &u)
Assemble the residual of a nonlinear problem into b, with Dirichlet conditions applied.
Definition petsc.h:754
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:65
Finite element method functionality.
Definition assemble_expression_impl.h:28
void assemble_matrix(la::MatSet< T > auto mat_add, const Form< T, U > &a, std::span< const T > constants, const std::map< std::pair< IntegralType, int >, std::pair< std::span< const T >, int > > &coefficients, std::span< const std::int8_t > dof_marker0, std::span< const std::int8_t > dof_marker1)
Assemble bilinear form into a matrix. Matrix must already be initialised. Does not zero or finalise t...
Definition assembler.h:588
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
std::map< std::pair< IntegralType, int >, std::pair< std::span< const T >, int > > make_coefficients_span(const std::map< std::pair< IntegralType, int >, std::pair< std::vector< T >, int > > &coeffs)
Create a map of std::spans from a map of std::vectors.
Definition assembler.h:54
void pack_coefficients(const Form< T, U > &form, std::map< std::pair< IntegralType, int >, std::pair< std::vector< T >, int > > &coeffs)
Pack coefficients of a Form.
Definition pack.h:267
std::pair< std::vector< T >, int > allocate_coefficient_storage(const Form< T, U > &form, IntegralType integral_type, int idx)
Allocate storage for coefficients of a pair (integral_type, idx) from a Form.
Definition pack.h:189
void assemble_vector(V &&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:140
void apply_lifting(V &&b, const std::vector< std::optional< std::reference_wrapper< 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::span< const std::int8_t > > &bc_markers1, const std::vector< std::span< const T > > &bc_values1, const std::vector< std::span< const T > > &x0, T alpha)
Modify the right-hand side vector to account for constraints (Dirichlet boundary condition constraint...
Definition assembler.h:311
la::SparsityPattern create_sparsity_pattern(const Form< T, U > &a)
Create a sparsity pattern for a given form.
Definition sparsitypattern.h:66
std::vector< T > pack_constants(const std::vector< std::reference_wrapper< const fem::Constant< T > > > &c)
Pack constants of an Expression or Form into a single array ready for assembly.
Definition pack.h:459
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:476
Mat create_matrix(MPI_Comm comm, const SparsityPattern &sp, std::optional< std::string_view > type=std::nullopt, std::optional< ISLocalToGlobalMapping > rlgmap=std::nullopt, std::optional< ISLocalToGlobalMapping > clgmap=std::nullopt)
Create a PETSc Mat. Caller is responsible for destroying the returned object.
Definition petsc.cpp:262
void set_diagonal(MatSet< T > auto &&set_fn, const common::LocalIndexRange auto &rows, T diagonal=T(1))
Set a value on the diagonal of a matrix for specified rows.
Definition utils.h:51
Mesh data structures and algorithms on meshes.
Definition DofMap.h:32
Functions supporting the packing of coefficient data.
Functions for constructing finite element sparsity patterns.