Skip to content

Commit b309147

Browse files
demo BDDC mixed poisson
1 parent 8d8b489 commit b309147

File tree

1 file changed

+166
-0
lines changed

1 file changed

+166
-0
lines changed
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
# ---
2+
# jupyter:
3+
# jupytext:
4+
# text_representation:
5+
# extension: .py
6+
# format_name: light
7+
# format_version: '1.5'
8+
# jupytext_version: 1.14.1
9+
# ---
10+
11+
# # Mixed formulation of the Poisson equation solved with BDDC preconditioner # noqa
12+
#
13+
# This demo illustrates how to solve the Poisson equation using a mixed
14+
# (two-field) formulation and a monolithic Balancing Domain Decomposition by
15+
# Constraits (BDDC) preconditioner for the Krylov solver. For details, see
16+
# the [paper](https://doi.org/10.1137/16M1080653). For details on the
17+
# equations, see demo_mixed-poisson.py
18+
#
19+
# ```{admonition} Download sources
20+
# :class: download
21+
# * {download}`Python script <./demo_mixed-poisson-bddc.py>`
22+
# * {download}`Jupyter notebook <./demo_mixed-poisson-bddc.ipynb>`
23+
# ```
24+
25+
#
26+
# ## Implementation
27+
#
28+
# Import the required modules:
29+
30+
# +
31+
from mpi4py import MPI
32+
from petsc4py import PETSc
33+
34+
import numpy as np
35+
36+
import dolfinx
37+
import ufl
38+
from basix.ufl import element
39+
from dolfinx import fem, mesh
40+
from dolfinx.fem.petsc import discrete_gradient, interpolation_matrix
41+
from dolfinx.mesh import CellType, create_unit_square, GhostMode
42+
43+
# Solution scalar (e.g., float32, complex128) and geometry (float32/64)
44+
# types
45+
dtype = dolfinx.default_scalar_type
46+
xdtype = dolfinx.default_real_type
47+
# -
48+
49+
# Create a two-dimensional mesh. The iterative solver supports three-
50+
# dimensional meshes too. BDDC methods needs the linear operator
51+
# to be stored in unassembled format, i.e. assembled on each MPI process
52+
# associated with the subdomain part of the mesh, but not across processes
53+
# To this end, we require the mesh to not be distributed with overlap
54+
55+
# +
56+
msh = create_unit_square(MPI.COMM_WORLD, 96, 96, CellType.triangle, ghost_mode=GhostMode.none, dtype=xdtype)
57+
# -
58+
59+
# From now on, the script is the same as demo_mixed-poisson.py.
60+
61+
# +
62+
k = 1
63+
V = fem.functionspace(msh, element("RT", msh.basix_cell(), k, dtype=xdtype))
64+
W = fem.functionspace(msh, element("Discontinuous Lagrange", msh.basix_cell(), k - 1, dtype=xdtype))
65+
Q = ufl.MixedFunctionSpace(V, W)
66+
67+
sigma, u = ufl.TrialFunctions(Q)
68+
tau, v = ufl.TestFunctions(Q)
69+
70+
x = ufl.SpatialCoordinate(msh)
71+
f = 10 * ufl.exp(-((x[0] - 0.5) * (x[0] - 0.5) + (x[1] - 0.5) * (x[1] - 0.5)) / 0.02)
72+
73+
dx = ufl.Measure("dx", msh)
74+
75+
a = ufl.extract_blocks(
76+
ufl.inner(sigma, tau) * dx + ufl.inner(u, ufl.div(tau)) * dx + ufl.inner(ufl.div(sigma), v) * dx
77+
)
78+
L = [ufl.ZeroBaseForm((tau,)), -ufl.inner(f, v) * dx]
79+
80+
fdim = msh.topology.dim - 1
81+
facets_top = mesh.locate_entities_boundary(msh, fdim, lambda x: np.isclose(x[1], 1.0))
82+
facets_bottom = mesh.locate_entities_boundary(msh, fdim, lambda x: np.isclose(x[1], 0.0))
83+
dofs_top = fem.locate_dofs_topological(V, fdim, facets_top)
84+
dofs_bottom = fem.locate_dofs_topological(V, fdim, facets_bottom)
85+
86+
cells_top_ = mesh.compute_incident_entities(msh.topology, facets_top, fdim, fdim + 1)
87+
cells_bottom = mesh.compute_incident_entities(msh.topology, facets_bottom, fdim, fdim + 1)
88+
g = fem.Function(V, dtype=dtype)
89+
g.interpolate(lambda x: np.vstack((np.zeros_like(x[0]), np.sin(5 * x[0]))), cells0=cells_top_)
90+
g.interpolate(lambda x: np.vstack((np.zeros_like(x[0]), -np.sin(5 * x[0]))), cells0=cells_bottom)
91+
bcs = [fem.dirichletbc(g, dofs_top), fem.dirichletbc(g, dofs_bottom)]
92+
93+
sigma, u = fem.Function(V, name="sigma", dtype=dtype), fem.Function(W, name="u", dtype=dtype)
94+
# -
95+
96+
# We now create a linear problem solver for the mixed problem.
97+
# As we will use BDDC, we specify the matrix kind to be "is".
98+
# We also show a minimal customization for the method to be
99+
# applied monolithically on the symmetric indefinite linear
100+
# system arising from the mixed problem.
101+
# In particular, we need solvers for the subproblems that can
102+
# support the saddle point formulation.
103+
104+
# +
105+
if PETSc.Sys().hasExternalPackage("umfpack"):
106+
solver = "lu"
107+
solver_type = "umfpack"
108+
elif PETSc.Sys().hasExternalPackage("mumps"):
109+
solver = "cholesky"
110+
solver_type = "mumps"
111+
elif PETSc.Sys().hasExternalPackage("superlu"):
112+
solver = "lu"
113+
solver_type = "superlu"
114+
elif PETSc.Sys().hasExternalPackage("umfpack"):
115+
solver = "lu"
116+
solver_type = "umfpack"
117+
else:
118+
solver = "svd"
119+
solver_type = "dummy"
120+
121+
problem = fem.petsc.LinearProblem(
122+
a,
123+
L,
124+
u=[sigma, u],
125+
kind="is",
126+
bcs=bcs,
127+
petsc_options_prefix="demo_mixed_poisson_",
128+
petsc_options={
129+
"ksp_rtol": 1e-8,
130+
"ksp_view": None,
131+
"pc_type": "bddc",
132+
"pc_bddc_use_local_mat_graph" : False,
133+
"pc_bddc_benign_trick": None,
134+
"pc_bddc_nonetflux": None,
135+
"pc_bddc_detect_disconnected": None,
136+
"pc_bddc_dirichlet_pc_type": solver,
137+
"pc_bddc_dirichlet_pc_factor_mat_solver_type": solver_type,
138+
"pc_bddc_neumann_pc_factor_mat_solver_type": solver_type,
139+
"pc_bddc_neumann_pc_type": solver,
140+
"pc_bddc_coarse_redundant_pc_factor_mat_solver_type": solver_type,
141+
"pc_bddc_coarse_redundant_pc_type": solver,
142+
},
143+
)
144+
# -
145+
146+
# Solve and save the solution `u` in VTX format:
147+
148+
# +
149+
ksp = problem.solver
150+
ksp.setMonitor(
151+
lambda _, its, rnorm: PETSc.Sys.Print(f"Iteration: {its:>4d}, residual: {rnorm:.3e}")
152+
)
153+
154+
problem.solve()
155+
converged_reason = problem.solver.getConvergedReason()
156+
assert converged_reason > 0, f"Krylov solver has not converged, reason: {converged_reason}."
157+
158+
if dolfinx.has_adios2:
159+
from dolfinx.io import VTXWriter
160+
161+
u.name = "u"
162+
with VTXWriter(msh.comm, "output_mixed_poisson_bddc.bp", u, "bp4") as f:
163+
f.write(0.0)
164+
else:
165+
print("ADIOS2 required for VTX output.")
166+
# -

0 commit comments

Comments
 (0)