1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
|
# Copyright (C) 2020-2021 Jørgen S. Dokken
#
# This file is part of DOLFINX_MPC
#
# SPDX-License-Identifier: MIT
from __future__ import annotations
from collections.abc import Sequence
from typing import Optional, Union
from petsc4py import PETSc as _PETSc
import dolfinx.cpp as _cpp
import dolfinx.fem as _fem
from dolfinx_mpc import cpp
from .multipointconstraint import MultiPointConstraint
def assemble_matrix(
form: _fem.Form,
constraint: Union[MultiPointConstraint, Sequence[MultiPointConstraint]],
bcs: Optional[Sequence[_fem.DirichletBC]] = None,
diagval: _PETSc.ScalarType = 1, # type: ignore
A: Optional[_PETSc.Mat] = None, # type: ignore
) -> _PETSc.Mat: # type: ignore
"""
Assemble a compiled DOLFINx bilinear form into a PETSc matrix with corresponding multi point constraints
and Dirichlet boundary conditions.
Args:
form: The compiled bilinear variational form
constraint: The multi point constraint
bcs: Sequence of Dirichlet boundary conditions
diagval: Value to set on the diagonal of the matrix
A: PETSc matrix to assemble into
Returns:
_PETSc.Mat: The matrix with the assembled bi-linear form #type: ignore
"""
bcs = [] if bcs is None else [bc._cpp_object for bc in bcs]
if not isinstance(constraint, Sequence):
assert form.function_spaces[0] == form.function_spaces[1]
constraint = (constraint, constraint)
# Generate matrix with MPC sparsity pattern
if A is None:
A = cpp.mpc.create_matrix(form._cpp_object, constraint[0]._cpp_object, constraint[1]._cpp_object)
A.zeroEntries()
# Assemble matrix in C++
cpp.mpc.assemble_matrix(A, form._cpp_object, constraint[0]._cpp_object, constraint[1]._cpp_object, bcs, diagval)
# Add one on diagonal for Dirichlet boundary conditions
if form.function_spaces[0] is form.function_spaces[1]:
A.assemblyBegin(_PETSc.Mat.AssemblyType.FLUSH) # type: ignore
A.assemblyEnd(_PETSc.Mat.AssemblyType.FLUSH) # type: ignore
_cpp.fem.petsc.insert_diagonal(A, form.function_spaces[0], bcs, diagval)
A.assemble()
return A
def create_sparsity_pattern(form: _fem.Form, mpc: Union[MultiPointConstraint, Sequence[MultiPointConstraint]]):
"""
Create sparsity-pattern for MPC given a compiled DOLFINx form
Args:
form: The form
mpc: For square forms, the MPC. For rectangular forms a list of 2 MPCs on
axis 0 & 1, respectively
"""
if isinstance(mpc, Sequence):
assert len(mpc) == 2
for mpc_ in mpc:
mpc_._not_finalized() # type: ignore
return cpp.mpc.create_sparsity_pattern(form._cpp_object, mpc[0]._cpp_object, mpc[1]._cpp_object)
else:
mpc._not_finalized() # type: ignore
return cpp.mpc.create_sparsity_pattern(
form._cpp_object,
mpc._cpp_object, # type: ignore
mpc._cpp_object, # type: ignore
) # type: ignore
def create_matrix_nest(a: Sequence[Sequence[_fem.Form]], constraints: Sequence[MultiPointConstraint]):
"""
Create a PETSc matrix of type "nest" with appropriate sparsity pattern
given the provided multi points constraints
Args:
a: The compiled bilinear variational form provided in a rank 2 list
constraints: An ordered list of multi point constraints
"""
assert len(constraints) == len(a)
A_ = [[None for _ in range(len(a[0]))] for _ in range(len(a))]
for i, a_row in enumerate(a):
for j, a_block in enumerate(a_row):
if a[i][j] is None:
continue
A_[i][j] = cpp.mpc.create_matrix(
a[i][j]._cpp_object, constraints[i]._cpp_object, constraints[j]._cpp_object
)
A = _PETSc.Mat().createNest( # type: ignore
A_, comm=constraints[0].function_space.mesh.comm
)
return A
def assemble_matrix_nest(
A: _PETSc.Mat, # type: ignore
a: Sequence[Sequence[_fem.Form]],
constraints: Sequence[MultiPointConstraint],
bcs: Sequence[_fem.DirichletBC] = [],
diagval: _PETSc.ScalarType = 1, # type: ignore
):
"""
Assemble a compiled DOLFINx bilinear form into a PETSc matrix of type
"nest" with corresponding multi point constraints and Dirichlet boundary
conditions.
Args:
a: The compiled bilinear variational form provided in a rank 2 list
constraints: An ordered list of multi point constraints
bcs: Sequence of Dirichlet boundary conditions
diagval: Value to set on the diagonal of the matrix (Default 1)
A: PETSc matrix to assemble into
"""
for i, a_row in enumerate(a):
for j, a_block in enumerate(a_row):
if a_block is not None:
Asub = A.getNestSubMatrix(i, j)
assemble_matrix(a_block, (constraints[i], constraints[j]), bcs=bcs, diagval=diagval, A=Asub)
|