1from mpi4py import MPI
2from petsc4py import PETSc
3from dolfinx import mesh
4from dolfinx import fem
5
6
7domain = mesh.create_unit_square(MPI.COMM_WORLD,
8 nx = 4, ny = 4)
9
10
11
12import ufl
13from dolfinx import default_scalar_type
14from dolfinx.fem.petsc import LinearProblem, assemble_vector, create_vector
15
16
17for i in range(4):
18
19
20 V = fem.functionspace(domain, ('P', 1))
21
22
23 import numpy as np
24 uD = fem.Function(V)
25 uD.interpolate(lambda x: np.full(x.shape[1], 0.))
26
27 tdim = domain.topology.dim
28 fdim = tdim - 1
29 domain.topology.create_connectivity(fdim, tdim)
30 boundary_facets = mesh.exterior_facet_indices(domain.topology)
31 boundary_dofs = fem.locate_dofs_topological(V, fdim,
32 boundary_facets)
33 bc = fem.dirichletbc(uD, boundary_dofs)
34
35 u = ufl.TrialFunction(V)
36 v = ufl.TestFunction(V)
37
38
39 x = ufl.SpatialCoordinate(domain)
40
41 f = 100.0 * ufl.exp(-100 * ((x[0] - 0.5)**2 + (x[1] - 0.5)**2))
42
43
44 a = ufl.dot(ufl.grad(u), ufl.grad(v)) * ufl.dx
45
46
47 L = f * v * ufl.dx
48
49
50 problem = LinearProblem(a, L, bcs=[bc],
51 petsc_options_prefix="linear_problem_primal",
52 petsc_options={
53 "ksp_type": "cg",
54 "pc_type": "hypre",
55 "pc_hypre_type": "boomeramg",
56 "ksp_rtol": 1.0e-10,
57 },
58 )
59 uh = problem.solve()
60
61
62 import pyvista
63 from dolfinx import plot
64
65
66 topology, cell_types, geometry = plot.vtk_mesh(V)
67 grid_uh = pyvista.UnstructuredGrid(topology, cell_types, geometry)
68 grid_uh.point_data["uh"] = uh.x.array.real
69 grid_uh.set_active_scalars("uh")
70
71
72 p = pyvista.Plotter()
73 p.add_mesh(grid_uh, show_edges=True, scalars="uh", cmap="viridis", label="uh")
74 p.add_axes()
75 p.add_legend()
76 p.view_xy()
77 p.show()
78
79
80 V_dual = fem.functionspace(domain, ('P', 3))
81 z = ufl.TrialFunction(V_dual)
82 w = ufl.TestFunction(V_dual)
83
84
85 import numpy as np
86 uD = fem.Function(V_dual)
87 uD.interpolate(lambda x: np.full(x.shape[1], 0.))
88
89 tdim = domain.topology.dim
90 fdim = tdim - 1
91 domain.topology.create_connectivity(fdim, tdim)
92 boundary_facets = mesh.exterior_facet_indices(domain.topology)
93 boundary_dofs = fem.locate_dofs_topological(V_dual, fdim,
94 boundary_facets)
95 bc = fem.dirichletbc(uD, boundary_dofs)
96
97
98 a = ufl.dot(ufl.grad(w), ufl.grad(z)) * ufl.dx
99
100
101 M = w * ufl.dx
102
103
104 problem = LinearProblem(a, M, bcs=[bc],
105 petsc_options_prefix="linear_problem_dual",
106 petsc_options={
107 "ksp_type": "cg",
108 "pc_type": "hypre",
109 "pc_hypre_type": "boomeramg",
110 "ksp_rtol": 1.0e-10,
111 })
112 zh = problem.solve()
113
114
115 W0 = fem.functionspace(domain, ("DG", 0))
116 w0 = ufl.TestFunction(W0)
117
118
119 z_proj = fem.Function(V)
120 z_proj.interpolate(zh)
121 z_tilde = zh - z_proj
122
123
124 r = f + ufl.div(ufl.grad(uh))
125
126
127 n = ufl.FacetNormal(domain)
128 flux_jump = ufl.jump(ufl.dot(ufl.grad(uh), n))
129 eta_form = fem.form(
130 r * z_tilde * w0 * ufl.dx
131 + 0.5 * flux_jump * ufl.avg(z_tilde) * (w0('+') + w0('-')) * ufl.dS
132 )
133
134 eta_vec = create_vector(fem.extract_function_spaces(eta_form))
135 with eta_vec.localForm() as loc_eta:
136 loc_eta.set(0)
137 assemble_vector(eta_vec, eta_form)
138 eta_vec.ghostUpdate(addv=PETSc.InsertMode.ADD_VALUES,
139 mode=PETSc.ScatterMode.REVERSE)
140 eta_vec.ghostUpdate(addv=PETSc.InsertMode.INSERT_VALUES,
141 mode=PETSc.ScatterMode.FORWARD)
142
143 print(f"Refinement {i}: max |cell DWR indicator| = {np.abs(eta_vec.array).max()}")
144
145
146 topology, cell_types, geometry = plot.vtk_mesh(domain, domain.topology.dim)
147 grid_residual = pyvista.UnstructuredGrid(topology, cell_types, geometry)
148 grid_residual.cell_data["cell_eta"] = np.abs(eta_vec.array.real)
149 grid_residual.set_active_scalars("cell_eta")
150
151 pl = pyvista.Plotter()
152 pl.add_mesh(grid_residual, show_edges=True, scalars="cell_eta", cmap="inferno", label="cell_eta")
153 pl.add_axes()
154 pl.add_legend()
155 pl.view_xy()
156 pl.show()
157
158
159
160 tdim = domain.topology.dim
161 num_local_cells = domain.topology.index_map(tdim).size_local
162 local_cells = np.arange(num_local_cells, dtype=np.int32)
163 cell_eta = np.empty(num_local_cells, dtype=np.float64)
164 for c in local_cells:
165 dof = W0.dofmap.cell_dofs(c)[0]
166 cell_eta[c] = abs(eta_vec.array[dof].real)
167
168 local_max = cell_eta.max() if num_local_cells > 0 else 0.0
169 global_max = domain.comm.allreduce(local_max, op=MPI.MAX)
170 threshold = 0.5 * global_max
171 cells_to_refine = local_cells[cell_eta > threshold]
172 print(f"Refinement {i}: marking {len(cells_to_refine)} cells for refinement")
173
174
175
176
177
178
179
180 from dolfinx.mesh import refine
181 if len(cells_to_refine) > 0:
182 marker_entities = cells_to_refine
183 try:
184
185 marker_entities = mesh.compute_incident_entities(domain.topology,
186 cells_to_refine,
187 tdim, 1)
188 except Exception:
189 pass
190 refine_out = refine(domain, marker_entities)
191 domain = refine_out[0] if isinstance(refine_out, tuple) else refine_out
192
193p.screenshot("fig.png")
194
195
196import os
197os.system("convert fig.png -trim fig.png")
198from PIL import Image
199im = Image.open("fig.png")
200w, h = im.size
201dpi = im.info.get('dpi', (300, 300))
202print(f'w={w/dpi[0]:.3f}in, h={h/dpi[1]:.3f}in')