src/laser_sampling.py

Wed, 07 Oct 2026 08:25:46 -0500

author
Tuomo Valkonen <tuomov@iki.fi>
date
Wed, 07 Oct 2026 08:25:46 -0500
changeset 18
ddd24b5c2715
parent 12
a0d61ac3719e
permissions
-rw-r--r--

Disable differential test

12
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
1 import basix
1
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
2 import numpy as np
12
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
3 from dolfinx import fem
1
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
4 from mpi4py import MPI
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
5 from petsc4py import PETSc
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
6 from pointsource_pde.dolfinx_extras import get_mass_matrix
12
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
7 from scipy.sparse import coo_matrix
1
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
8 from scipy.sparse.linalg import svds
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
9 from slepc4py import SLEPc
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
10
12
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
11 from dolfinx_access import cell_FunctionSpace_f64
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
12
1
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
13
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
14 class LaserSampling:
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
15 """
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
16 A linear operator class for laser sampling of a concentration (fem.Function)
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
17 """
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
18
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
19 def __init__(
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
20 self,
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
21 V,
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
22 domain,
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
23 nx,
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
24 ny,
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
25 beams,
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
26 domain_size=[-2, 2, -2, 2],
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
27 ):
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
28 self.V = V
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
29 self.domain = domain
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
30 self.nx, self.ny = nx, ny
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
31 self.M = len(beams)
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
32 self.domain_size = domain_size
12
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
33
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
34 # Basix element matching V, used to tabulate phi_h exactly at points
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
35 # self._element = self._create_basix_element()
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
36 self._element = self.V.element.basix_element
1
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
37
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
38 # Build R matrix (single function does everything)
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
39 self.R = self.matrix(beams)
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
40
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
41 A = get_mass_matrix(V)
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
42 solver = PETSc.KSP().create(A.comm)
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
43 solver.setOperators(A)
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
44 solver.setType(PETSc.KSP.Type.PREONLY)
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
45 solver.getPC().setType(PETSc.PC.Type.LU)
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
46 self.solver = solver
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
47
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
48 # ‖x‖^2 = ‖Ax.array‖^2
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
49 # ‖Lx‖^2 = ‖Rx.array‖^2 = ‖RA^{-1}Ax.array‖^2 ≤ ‖RA^{-1}‖‖x‖^2 ≤ ‖R‖‖A^{-1}‖‖x‖^2,
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
50 # so we need the inverse of the minimal eigenvalue.
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
51 E = SLEPc.EPS().create(A.comm)
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
52 E.setOperators(A)
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
53 E.setProblemType(SLEPc.EPS.ProblemType.NHEP)
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
54 E.setWhichEigenpairs(SLEPc.EPS.Which.SMALLEST_MAGNITUDE)
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
55 # E.setWhichEigenpairs(SLEPc.EPS.Which.LARGEST_MAGNITUDE)
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
56 E.setFromOptions()
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
57 E.solve()
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
58
3
c3a4f4bb87f7 Dolfin update, fixes, additional experiment, build instructions.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
59 # sigma = abs(E.getEigenvalue(0))
1
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
60 # self._opnorm = 1.0 / sigma
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
61 # print("Full sampling opnorm = %f" % self._opnorm)
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
62
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
63 # SVD operator norm
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
64 _u, s, _v = svds(self.R, k=1)
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
65 self._opnorm = s[0] # / sigma
3
c3a4f4bb87f7 Dolfin update, fixes, additional experiment, build instructions.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
66 # print(f"Laser sampling opnorm = {self._opnorm:.6f}")
1
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
67
12
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
68 # ------------------------------------------------------------------
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
69 # Exact per-cell line integration
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
70 #
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
71 # A beam is split into the ordered sub-segments where it actually
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
72 # crosses each element (via Cyrus-Beck clipping against the cell's
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
73 # polygon), and each sub-segment is integrated exactly using the
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
74 # 3-point Simpson rule (exact for phi_h of degree <= 2, since phi_h
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
75 # pulled back along a straight line stays degree <= 2 in the
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
76 # parameter t). This replaces the previous approach of sampling many
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
77 # midpoints and splitting weight equally across a cell's dofs.
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
78 # ------------------------------------------------------------------
1
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
79
12
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
80 def _cell_vertices_2d(self, cell_idx):
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
81 """Physical (x, y) vertices of a cell, ordered CCW around its centroid."""
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
82 x_geom = self.domain.geometry.x
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
83 verts = self.domain.geometry.dofmap[cell_idx]
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
84 pts = x_geom[verts, :2]
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
85 centroid = pts.mean(axis=0)
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
86 angles = np.arctan2(pts[:, 1] - centroid[1], pts[:, 0] - centroid[0])
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
87 return pts[np.argsort(angles)]
1
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
88
12
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
89 def _clip_segment_to_cell(self, pts, x, y, eps=1e-12):
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
90 """
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
91 Cyrus-Beck clip of the segment x->y against the convex polygon `cell_idx`.
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
92 Returns (t0, t1) in [0, 1] such that x + t*(y - x), t in [t0, t1], is the
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
93 part of the segment inside the cell -- or None if there's no overlap.
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
94 Works for any convex cell (triangle or quad); assumes straight-sided
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
95 (affine, P1) geometry.
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
96 """
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
97 n_verts = len(pts)
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
98 d = y - x
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
99 t_lo, t_hi = 0.0, 1.0
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
100
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
101 for i in range(n_verts):
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
102 v0 = pts[i]
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
103 v1 = pts[(i + 1) % n_verts]
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
104 edge = v1 - v0
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
105 normal = np.array([edge[1], -edge[0]]) # outward normal (CCW polygon)
1
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
106
12
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
107 denom = normal @ d
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
108 numer = normal @ (v0 - x)
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
109
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
110 if abs(denom) < eps:
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
111 if numer < -eps: # segment parallel to edge, and entirely outside it
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
112 return None
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
113 continue # parallel and inside: this edge imposes no constraint
1
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
114
12
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
115 t_edge = numer / denom
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
116 if denom > 0:
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
117 t_hi = min(t_hi, t_edge)
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
118 else:
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
119 t_lo = max(t_lo, t_edge)
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
120
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
121 if t_lo > t_hi + eps:
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
122 return None
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
123
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
124 if t_lo > t_hi:
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
125 return None
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
126 return t_lo, t_hi
1
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
127
12
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
128 def matrix(self, beams):
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
129 """Combined: exact beam/cell intersection + exact per-cell line integration."""
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
130 n_dofs = self.V.dofmap.index_map.size_global
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
131 # R = np.zeros((self.M, n_dofs))
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
132 rows, cols, data = [], [], []
1
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
133
12
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
134 for cell_idx in range(len(self.domain.geometry.dofmap)):
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
135 pts = self._cell_vertices_2d(cell_idx)
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
136 for beam_idx, (start_pt, end_pt) in enumerate(beams):
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
137 clip = self._clip_segment_to_cell(pts, start_pt, end_pt)
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
138 if clip is not None:
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
139 t0, t1 = clip
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
140 if t1 - t0 > 1e-10:
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
141 beam_v = end_pt - start_pt
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
142 x0 = start_pt + t0 * beam_v
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
143 x1 = start_pt + t1 * beam_v
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
144 midpt = start_pt + (0.5 * (t1 + t0)) * beam_v
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
145 """
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
146 Exact int_{x0}^{x1} phi_h ds for phi_h in V restricted to `cell_idx`, as a
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
147 (global_dofs, row_values) pair such that row_values @ phi_h.x.array[global_dofs]
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
148 equals the integral. Uses the 3-point Simpson rule (endpoints + midpoint),
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
149 which is exact since phi_h has degree <= 2 along the line.
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
150 """
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
151 x_geom = self.domain.geometry.x
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
152 verts = self.domain.geometry.dofmap[cell_idx]
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
153 v0, v1, v2 = (
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
154 x_geom[verts[0], :2],
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
155 x_geom[verts[1], :2],
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
156 x_geom[verts[2], :2],
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
157 )
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
158 J = np.column_stack([v1 - v0, v2 - v0])
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
159 """Map a physical point p to reference coordinates on an affine triangle."""
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
160 pts_ref = np.array(
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
161 [
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
162 np.linalg.solve(J, x0 - v0),
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
163 np.linalg.solve(J, midpt - v0),
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
164 np.linalg.solve(J, x1 - v0),
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
165 ]
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
166 )
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
167 tab = self._element.tabulate(0, pts_ref)[
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
168 0
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
169 ] # (npoints, ndof_local, value_size)
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
170 tab = tab[
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
171 ..., 0
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
172 ] # scalar element -> drop trailing value_size=1 axis
1
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
173
12
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
174 length = (t1 - t0) * np.linalg.norm(beam_v)
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
175 weights = np.array([1.0, 4.0, 1.0]) * length / 6.0
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
176 local_dofs = self.V.dofmap.cell_dofs(cell_idx)
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
177 # global_dofs = self.V.dofmap.index_map.local_to_global(local_dofs)
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
178 # R[beam_idx, local_dofs] += weights @ tab
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
179 rows.append(np.full(len(local_dofs), beam_idx, dtype=np.int64))
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
180 cols.append(np.asarray(local_dofs, dtype=np.int64))
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
181 data.append(weights @ tab)
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
182
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
183 # return R
1
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
184
12
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
185 if rows:
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
186 rows = np.concatenate(rows)
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
187 cols = np.concatenate(cols)
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
188 data = np.concatenate(data)
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
189 else:
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
190 rows = np.array([], dtype=np.int64)
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
191 cols = np.array([], dtype=np.int64)
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
192 data = np.array([], dtype=np.float64)
1
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
193
12
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
194 return coo_matrix((data, (rows, cols)), shape=(self.M, n_dofs)).tocsr()
1
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
195
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
196 def apply(self, x):
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
197 """
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
198 This does not work with MPI
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
199 """
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
200 x.x.scatter_forward()
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
201 return self.R @ x.x.array
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
202
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
203 def diff_adjdir(self, j, _x):
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
204 """
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
205 This does not work with MPI
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
206 """
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
207 # We need ⟨Rx,v⟩_{ℝ^n} = ⟨x,R^*v⟩_V
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
208 # We have ⟨x,R^*v⟩_V = ⟨Ax.array,[R^*v].array⟩_{ℝ^m}
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
209 # But Rx = R₀ x.array, so we need
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
210 # ⟨x.array,R₀^* v⟩_{ℝ^n} = ⟨Ax.array,[R^*v].array⟩_{ℝ^m}
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
211 # Taking [R^*v].array=A^{-1}R₀^* v, the conjugate works correctly.
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
212 tmp = fem.Function(self.V)
12
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
213 res = fem.Function(self.V)
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
214 tmp.x.array[:] = self.R.T @ j
1
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
215 tmp.x.scatter_forward()
12
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
216 self.solver.solve(tmp.x.petsc_vec, res.x.petsc_vec)
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
217 res.x.scatter_forward()
a0d61ac3719e Various revisions:
Tuomo Valkonen <tuomov@iki.fi>
parents: 3
diff changeset
218 return res
1
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
219
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
220 def opnorm(self, *args):
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
221 # raise NotImplementedError("Need mesh weighting?")
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
222 return self._opnorm
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
223
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
224 def lipschitz_factor(self, *args):
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
225 return self.opnorm(*args)
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
226
3
c3a4f4bb87f7 Dolfin update, fixes, additional experiment, build instructions.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
227 def diff_chain_lipschitz_factor(self, *args):
1
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
228 return self.opnorm(*args)
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
229
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
230 def diff_bound(self, *args):
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
231 return self.opnorm(*args)
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
232
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
233 # Construct observation noise
3
c3a4f4bb87f7 Dolfin update, fixes, additional experiment, build instructions.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
234 def noise(self, noise_level, rng=None):
c3a4f4bb87f7 Dolfin update, fixes, additional experiment, build instructions.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
235 if rng is None:
c3a4f4bb87f7 Dolfin update, fixes, additional experiment, build instructions.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
236 rng = np.random.default_rng()
1
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
237 M = self.M
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
238 # Generate noise with shape (M, 1) using scalar standard deviation
3
c3a4f4bb87f7 Dolfin update, fixes, additional experiment, build instructions.
Tuomo Valkonen <tuomov@iki.fi>
parents: 1
diff changeset
239 noise = rng.normal(0, noise_level, size=(M,))
1
a4137aedcb3a Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
240 return noise

mercurial