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 Jørgen S. Dokken
#
# This file is part of DOLFINX_MPC
#
# SPDX-License-Identifier: MIT
import contextlib
from typing import List, Sequence
import dolfinx.cpp as _cpp
import dolfinx.fem as _fem
import ufl
from dolfinx.common import Timer
from petsc4py import PETSc as _PETSc
import dolfinx_mpc.cpp
from .multipointconstraint import MultiPointConstraint
def apply_lifting(b: _PETSc.Vec, form: List[_fem.FormMetaClass], bcs: List[List[_fem.DirichletBCMetaClass]],
constraint: MultiPointConstraint, x0: List[_PETSc.Vec] = [], scale: float = 1.0):
"""
Apply lifting to vector b, i.e.
.. math::
b <- b - scale * K^T (A_j (g_j - x0_j))
Parameters
----------
b
PETSc vector to assemble into
form
The linear form
bcs
List of Dirichlet boundary conditions
constraint
The multi point constraint
x0
List of vectors
scale
Scaling for lifting
Returns
-------
PETSc.Vec
The assembled linear form
"""
t = Timer("~MPC: Apply lifting (C++)")
with contextlib.ExitStack() as stack:
x0 = [stack.enter_context(x.localForm()) for x in x0]
x0_r = [x.array_r for x in x0]
b_local = stack.enter_context(b.localForm())
dolfinx_mpc.cpp.mpc.apply_lifting(b_local.array_w, form,
bcs, x0_r, scale, constraint._cpp_object)
t.stop()
def assemble_vector(form: ufl.form.Form, constraint: MultiPointConstraint,
b: _PETSc.Vec = None) -> _PETSc.Vec:
"""
Assemble a linear form into vector b with corresponding multi point constraint
Parameters
----------
form
The linear form
constraint
The multi point constraint
b
PETSc vector to assemble into (optional)
Returns
-------
PETSc.Vec
The assembled linear form
"""
if b is None:
b = _cpp.la.petsc.create_vector(constraint.function_space.dofmap.index_map,
constraint.function_space.dofmap.index_map_bs)
t = Timer("~MPC: Assemble vector (C++)")
with b.localForm() as b_local:
b_local.set(0.0)
dolfinx_mpc.cpp.mpc.assemble_vector(b_local, form, constraint._cpp_object)
t.stop()
return b
def create_vector_nest(
L: Sequence[_fem.FormMetaClass],
constraints: Sequence[MultiPointConstraint]) -> _PETSc.Vec:
"""
Create a PETSc vector of type "nest" appropriate for the provided multi
point constraints
Parameters
----------
L
A sequence of linear forms
constraints
An ordered list of multi point constraints
Returns
-------
PETSc.Vec
A PETSc vector of type "nest"
"""
assert len(constraints) == len(L)
maps = [(constraint.function_space.dofmap.index_map,
constraint.function_space.dofmap.index_map_bs)
for constraint in constraints]
return _cpp.fem.petsc.create_vector_nest(maps)
def assemble_vector_nest(
b: _PETSc.Vec,
L: Sequence[_fem.FormMetaClass],
constraints: Sequence[MultiPointConstraint]):
"""
Assemble a linear form into a PETSc vector of type "nest"
Parameters
----------
b
A PETSc vector of type "nest"
L
A sequence of linear forms
constraints
An ordered list of multi point constraints
"""
assert len(constraints) == len(L)
assert b.getType() == "nest"
b_sub_vecs = b.getNestSubVecs()
for i, L_row in enumerate(L):
assemble_vector(L_row, constraints[i], b=b_sub_vecs[i])
|