Wed, 07 Oct 2026 08:25:46 -0500
Disable differential test
| 12 | 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 | 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 | 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 | 11 | from dolfinx_access import cell_FunctionSpace_f64 |
| 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 | 33 | |
| 34 | # Basix element matching V, used to tabulate phi_h exactly at points | |
| 35 | # self._element = self._create_basix_element() | |
| 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 | 68 | # ------------------------------------------------------------------ |
| 69 | # Exact per-cell line integration | |
| 70 | # | |
| 71 | # A beam is split into the ordered sub-segments where it actually | |
| 72 | # crosses each element (via Cyrus-Beck clipping against the cell's | |
| 73 | # polygon), and each sub-segment is integrated exactly using the | |
| 74 | # 3-point Simpson rule (exact for phi_h of degree <= 2, since phi_h | |
| 75 | # pulled back along a straight line stays degree <= 2 in the | |
| 76 | # parameter t). This replaces the previous approach of sampling many | |
| 77 | # midpoints and splitting weight equally across a cell's dofs. | |
| 78 | # ------------------------------------------------------------------ | |
|
1
a4137aedcb3a
Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
79 | |
| 12 | 80 | def _cell_vertices_2d(self, cell_idx): |
| 81 | """Physical (x, y) vertices of a cell, ordered CCW around its centroid.""" | |
| 82 | x_geom = self.domain.geometry.x | |
| 83 | verts = self.domain.geometry.dofmap[cell_idx] | |
| 84 | pts = x_geom[verts, :2] | |
| 85 | centroid = pts.mean(axis=0) | |
| 86 | angles = np.arctan2(pts[:, 1] - centroid[1], pts[:, 0] - centroid[0]) | |
| 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 | 89 | def _clip_segment_to_cell(self, pts, x, y, eps=1e-12): |
| 90 | """ | |
| 91 | Cyrus-Beck clip of the segment x->y against the convex polygon `cell_idx`. | |
| 92 | Returns (t0, t1) in [0, 1] such that x + t*(y - x), t in [t0, t1], is the | |
| 93 | part of the segment inside the cell -- or None if there's no overlap. | |
| 94 | Works for any convex cell (triangle or quad); assumes straight-sided | |
| 95 | (affine, P1) geometry. | |
| 96 | """ | |
| 97 | n_verts = len(pts) | |
| 98 | d = y - x | |
| 99 | t_lo, t_hi = 0.0, 1.0 | |
| 100 | ||
| 101 | for i in range(n_verts): | |
| 102 | v0 = pts[i] | |
| 103 | v1 = pts[(i + 1) % n_verts] | |
| 104 | edge = v1 - v0 | |
| 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 | 107 | denom = normal @ d |
| 108 | numer = normal @ (v0 - x) | |
| 109 | ||
| 110 | if abs(denom) < eps: | |
| 111 | if numer < -eps: # segment parallel to edge, and entirely outside it | |
| 112 | return None | |
| 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 | 115 | t_edge = numer / denom |
| 116 | if denom > 0: | |
| 117 | t_hi = min(t_hi, t_edge) | |
| 118 | else: | |
| 119 | t_lo = max(t_lo, t_edge) | |
| 120 | ||
| 121 | if t_lo > t_hi + eps: | |
| 122 | return None | |
| 123 | ||
| 124 | if t_lo > t_hi: | |
| 125 | return None | |
| 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 | 128 | def matrix(self, beams): |
| 129 | """Combined: exact beam/cell intersection + exact per-cell line integration.""" | |
| 130 | n_dofs = self.V.dofmap.index_map.size_global | |
| 131 | # R = np.zeros((self.M, n_dofs)) | |
| 132 | rows, cols, data = [], [], [] | |
|
1
a4137aedcb3a
Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
133 | |
| 12 | 134 | for cell_idx in range(len(self.domain.geometry.dofmap)): |
| 135 | pts = self._cell_vertices_2d(cell_idx) | |
| 136 | for beam_idx, (start_pt, end_pt) in enumerate(beams): | |
| 137 | clip = self._clip_segment_to_cell(pts, start_pt, end_pt) | |
| 138 | if clip is not None: | |
| 139 | t0, t1 = clip | |
| 140 | if t1 - t0 > 1e-10: | |
| 141 | beam_v = end_pt - start_pt | |
| 142 | x0 = start_pt + t0 * beam_v | |
| 143 | x1 = start_pt + t1 * beam_v | |
| 144 | midpt = start_pt + (0.5 * (t1 + t0)) * beam_v | |
| 145 | """ | |
| 146 | Exact int_{x0}^{x1} phi_h ds for phi_h in V restricted to `cell_idx`, as a | |
| 147 | (global_dofs, row_values) pair such that row_values @ phi_h.x.array[global_dofs] | |
| 148 | equals the integral. Uses the 3-point Simpson rule (endpoints + midpoint), | |
| 149 | which is exact since phi_h has degree <= 2 along the line. | |
| 150 | """ | |
| 151 | x_geom = self.domain.geometry.x | |
| 152 | verts = self.domain.geometry.dofmap[cell_idx] | |
| 153 | v0, v1, v2 = ( | |
| 154 | x_geom[verts[0], :2], | |
| 155 | x_geom[verts[1], :2], | |
| 156 | x_geom[verts[2], :2], | |
| 157 | ) | |
| 158 | J = np.column_stack([v1 - v0, v2 - v0]) | |
| 159 | """Map a physical point p to reference coordinates on an affine triangle.""" | |
| 160 | pts_ref = np.array( | |
| 161 | [ | |
| 162 | np.linalg.solve(J, x0 - v0), | |
| 163 | np.linalg.solve(J, midpt - v0), | |
| 164 | np.linalg.solve(J, x1 - v0), | |
| 165 | ] | |
| 166 | ) | |
| 167 | tab = self._element.tabulate(0, pts_ref)[ | |
| 168 | 0 | |
| 169 | ] # (npoints, ndof_local, value_size) | |
| 170 | tab = tab[ | |
| 171 | ..., 0 | |
| 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 | 174 | length = (t1 - t0) * np.linalg.norm(beam_v) |
| 175 | weights = np.array([1.0, 4.0, 1.0]) * length / 6.0 | |
| 176 | local_dofs = self.V.dofmap.cell_dofs(cell_idx) | |
| 177 | # global_dofs = self.V.dofmap.index_map.local_to_global(local_dofs) | |
| 178 | # R[beam_idx, local_dofs] += weights @ tab | |
| 179 | rows.append(np.full(len(local_dofs), beam_idx, dtype=np.int64)) | |
| 180 | cols.append(np.asarray(local_dofs, dtype=np.int64)) | |
| 181 | data.append(weights @ tab) | |
| 182 | ||
| 183 | # return R | |
|
1
a4137aedcb3a
Initial working version for known convectivity and diffusivity
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
184 | |
| 12 | 185 | if rows: |
| 186 | rows = np.concatenate(rows) | |
| 187 | cols = np.concatenate(cols) | |
| 188 | data = np.concatenate(data) | |
| 189 | else: | |
| 190 | rows = np.array([], dtype=np.int64) | |
| 191 | cols = np.array([], dtype=np.int64) | |
| 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 | 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 | 213 | res = fem.Function(self.V) |
| 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 | 216 | self.solver.solve(tmp.x.petsc_vec, res.x.petsc_vec) |
| 217 | res.x.scatter_forward() | |
| 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 |