experiments/laser_and_mirrors_aux.py

changeset 3
c3a4f4bb87f7
parent 1
a4137aedcb3a
equal deleted inserted replaced
1:a4137aedcb3a 3:c3a4f4bb87f7
11 from pointsource_pde.compose import ( 11 from pointsource_pde.compose import (
12 ComposeFnWithOperator, 12 ComposeFnWithOperator,
13 SumOfSeparableFunctions, 13 SumOfSeparableFunctions,
14 ) 14 )
15 from pointsource_pde.convection_diffusion import ( 15 from pointsource_pde.convection_diffusion import (
16 BoxedQuadraticRegularisation,
16 ConvectionDiffusion, 17 ConvectionDiffusion,
17 PlotFactory, 18 PlotFactory,
18 QuadraticRegularisation,
19 XBound, 19 XBound,
20 ) 20 )
21 from pointsource_pde.laser_sampling import LaserSampling 21 from pointsource_pde.laser_sampling import LaserSampling
22 from pointsource_pde.quadratic_dataterm import QuadraticDataTerm 22 from pointsource_pde.quadratic_dataterm import QuadraticDataTerm
23 23
25 name = "laser_and_mirrors_aux" 25 name = "laser_and_mirrors_aux"
26 26
27 # Fine-tune algorithms 27 # Fine-tune algorithms
28 alg_finetune = { 28 alg_finetune = {
29 "tau0": 0.99, 29 "tau0": 0.99,
30 "theta0": 0.01, 30 "theta0": 100,
31 "inner_method": "PP", 31 "inner_method": "PP",
32 "inner_pdps_τσ0": (19.8, 0.05), 32 "inner_pdps_τσ0": (19.8, 0.05),
33 "inner_pp_τ": [1000.0, 1000.0], 33 "inner_pp_τ": [1000.0, 1000.0],
34 "merge": True, 34 "merge": True,
35 "fitness_merging": True, 35 "fitness_merging": True,
36 "merge_radius": 0.1,
37 "merge_interp": False,
36 } 38 }
37 39
38 algorithm_overrides = { 40 algorithm_overrides = {
39 "RadonFB": alg_finetune, 41 "RadonFB": alg_finetune,
40 "RadonSlidingFB": alg_finetune, 42 "RadonSlidingFB": alg_finetune,
42 "RadonSlidingPDPS": alg_finetune, 44 "RadonSlidingPDPS": alg_finetune,
43 } 45 }
44 46
45 47
46 # Setup shared between experiment with known/unknown conductivity and diffusivity 48 # Setup shared between experiment with known/unknown conductivity and diffusivity
47 def generic_setup(prefix, simple=True): 49 def generic_setup(
48 50 prefix,
49 # Create true source 51 simple=True,
50 μ_true = DiscreteMeasure_2_f64( 52 rng=None,
53 μ_true=DiscreteMeasure_2_f64(
51 [([0.1, 0.3], 0.08), ([0.4, 0.25], 0.05), ([0.25, 0.13], 0.06)] 54 [([0.1, 0.3], 0.08), ([0.4, 0.25], 0.05), ([0.25, 0.13], 0.06)]
52 ) 55 ),
56 k=0.01,
57 r=0.5,
58 θ=30 * np.pi / 180,
59 ):
53 60
54 # Create convection-diffusion PDE 61 # Create convection-diffusion PDE
55 pde = ConvectionDiffusion( 62 pde = ConvectionDiffusion(
56 u0=lambda x: 0.0 * x[1], 63 u0=lambda x: 0.0 * x[1],
57 g=lambda x: 0.0 * x[1], 64 g=lambda x: 0.0 * x[1],
58 domain_size=[0, 0.5, 0, 0.5], 65 domain_size=[0, 0.5, 0, 0.5],
59 num_steps=50, 66 num_steps=50,
67 # override_lipschitz=4.0,
68 # override_lipschitz_pair=(4.0, 40.0),
60 ) 69 )
61 70
62 # Set up lasers and mirrors 71 # Set up lasers and mirrors
63 lasers = [ 72 lasers = [
64 np.array([0.1, 0.1]), 73 np.array([0.1, 0.1]),
89 98
90 v0 = 1.0 99 v0 = 1.0
91 100
92 if simple: 101 if simple:
93 # Scalar convectivity and diffusivity 102 # Scalar convectivity and diffusivity
94 r = 0.5
95 θ = 30 * np.pi / 180
96 c1 = r * np.cos(θ) 103 c1 = r * np.cos(θ)
97 c2 = r * np.sin(θ) 104 c2 = r * np.sin(θ)
98 k = 0.01 # diffusive
99 # k = 0.001 # high wind 105 # k = 0.001 # high wind
106 print("True aux variables: k = %f, c1 = %f, c2 = %f" % (k, c1, c2))
100 else: 107 else:
101 # Convectivity and diffusivity fields 108 # Convectivity and diffusivity fields
102 def velocity_x(x): 109 def velocity_x(x):
103 r = np.sqrt(x[0] ** 2 + x[1] ** 2 + 1e-10) 110 r = np.sqrt(x[0] ** 2 + x[1] ** 2 + 1e-10)
104 return v0 * x[0] / r 111 return v0 * x[0] / r
118 auxtrue = (k, (c1, c2)) 125 auxtrue = (k, (c1, c2))
119 126
120 # Simulate measurements 127 # Simulate measurements
121 u_n_list = pde.apply((μ_true, (k, (c1, c2)))) 128 u_n_list = pde.apply((μ_true, (k, (c1, c2))))
122 b_true = [L_i.apply(u) for u in u_n_list] 129 b_true = [L_i.apply(u) for u in u_n_list]
123 b = [b_i + L_i.noise(0.01 * norm(b_i) / np.sqrt(np.size(b_i))) for b_i in b_true] 130 b = [
131 b_i + L_i.noise(0.01 * norm(b_i) / np.sqrt(np.size(b_i)), rng) for b_i in b_true
132 ]
124 133
125 # Estimate bounds on domains and values 134 # Estimate bounds on domains and values
126 dat_bound = 10 * max([norm(b_i) for b_i in b]) 135 dat_bound = 2 * max([norm(b_i) for b_i in b])
127 μ_bound = 1.3 * sum([alpha for _point, alpha in μ_true.iter_padded()]) 136 μ_bound = 1.3 * sum([alpha for _point, alpha in μ_true.iter_padded()])
128 xbound = XBound(mu_dual=μ_bound, k_min=k, k_max=k, c_Linf=r) 137 pde.xbound = XBound(mu_dual=μ_bound, k_min=k * 0.9, k_max=k * 1.1, c_Linf=r * 0.9)
129 138
130 # Create data term 139 # Create data term
131 dat = ComposeFnWithOperator( 140 dat = ComposeFnWithOperator(
132 SumOfSeparableFunctions( 141 SumOfSeparableFunctions(
133 [ 142 [
137 xbound=dat_bound, 146 xbound=dat_bound,
138 b_norm=norm(b), 147 b_norm=norm(b),
139 λ=pde.dt / len(beams), 148 λ=pde.dt / len(beams),
140 ) 149 )
141 for data in b 150 for data in b
142 ] 151 ],
143 ), 152 ),
144 pde, 153 pde,
145 xbound=[xbound], 154 )
146 xbound_pair=[xbound], 155
147 ) 156 # Save true and initial data
148
149 # Plot true and initial data
150 plot_factory = PlotFactory(pde) 157 plot_factory = PlotFactory(pde)
151 plotter = plot_factory.produce(prefix) 158 plotter = plot_factory.produce(prefix)
152 ω, _ = dat.diff((DiscreteMeasure_2_f64([]), auxtrue)) 159 ω, _ = dat.diff((DiscreteMeasure_2_f64([]), auxtrue))
153 ω_true, _ = dat.diff((μ_true, auxtrue)) 160 ω_true, _ = dat.diff((μ_true, auxtrue))
154 np.savez_compressed( 161 np.savez_compressed(
155 "%s/omega_0.npz" % prefix, 162 "%s/omega_0.npz" % prefix,
156 true_mu=[[point[0], point[1], alpha] for point, alpha in μ_true.iter_padded()], 163 true_mu=[[point[0], point[1], alpha] for point, alpha in μ_true.iter_padded()],
157 omega0=ω.x.array, 164 omega0=ω.x.array,
158 true_omega=ω_true.x.array, 165 true_omega=ω_true.x.array,
166 k=k,
167 c1=c1,
168 c2=c2,
159 true_u_n_list_array=[u_n_list[i].x.array for i in plotter.plot_frames], 169 true_u_n_list_array=[u_n_list[i].x.array for i in plotter.plot_frames],
160 ) 170 )
161 171
162 return dat, auxtrue, μ_bound, μ_true, plot_factory 172 return dat, auxtrue, μ_bound, μ_true, plot_factory, pde
163 173
164 174
175 def relnoise(v, σ, rng, level=None):
176 if level is None:
177 level = abs(v)
178 return float(rng.normal(v, σ * level))
179
180
181 # Setup the problem
165 def setup(prefix): 182 def setup(prefix):
166 dat, auxtrue, _μ_bound, μ_true, plot_factory = generic_setup(prefix) 183 rng = np.random.default_rng(seed=31337)
167 184
168 reg = RegTerm.NonnegRadon(10e-7) 185 dat, auxtrue, _μ_bound, μ_true, plot_factory, pde = generic_setup(prefix, rng=rng)
186
187 # Override Lipschitz parameter
188 pde.override_lipschitz = (4.0,)
189 pde.override_lipschitz_pair = (4.0, 4.0)
190 # print("diff_chain_lipschitz_factor (modified)", pde.diff_chain_lipschitz_factor())
191 # l1, l2 = pde.diff_chain_lipschitz_factor_pair()
192 # print("diff_chain_lipschitz_factor_pair (modified) ", l1, ", ", l2)
193
194 reg = RegTerm.NonnegRadon(1.5e-6)
169 195
170 μ0 = DiscreteMeasure_2_f64([]) 196 μ0 = DiscreteMeasure_2_f64([])
171 aux0 = auxtrue 197 (k, (c1, c2)) = auxtrue
172 aux = QuadraticRegularisation(0.001, aux0) 198 aux0 = (
199 max(0.001, relnoise(k, 0.02, rng)),
200 (
201 relnoise(c1, 0.2, rng),
202 relnoise(c2, 0.2, rng),
203 ),
204 )
205 print("aux init ", aux0)
206 aux = BoxedQuadraticRegularisation((0.001, -1.0), (1.0, 1.0), (3.0, 0.0005), aux0)
173 ax = aux.apply(aux0) 207 ax = aux.apply(aux0)
174 inival = dat.apply((μ0, aux0)) 208 inival = dat.apply((μ0, aux0))
175 print("Initial value:", inival + ax, ax) 209 print("Initial data term value:", inival + ax)
176 print("Value at true μ:", dat.apply((μ_true, auxtrue)) + ax) 210 print("Data term value at true μ:", dat.apply((μ_true, auxtrue)) + ax)
177 211
178 # auxinit = np.c_[ 212 # No curvature bound given: θ is aboslute.
179 # np.zeros_like(k), 213 dat.curvature_bound_components = lambda: (None, None)
180 # np.zeros_like(c1),
181 # np.zeros_like(c2),
182 # ]
183 # print(np.shape(auxinit))
184
185 # We need Θ² such that ⟨F'(μ+Δ, aux-F'(μ, aux)|Δ⟩ ≤ Θ²|γ|(c_2), where Δ=(π_♯^1-π_♯^0)γ.
186 # We have
187 #
188 # ⟨F'(μ+Δ, aux)-F'(μ, aux)|Δ⟩ ≤ ‖⟨F'(μ+Δ, aux)-F'(μ, aux)‖ ‖Δ‖
189 # ≤ L_{F'(·, aux)} ‖Δ‖²,
190 #
191 # so Θ² ≥ L_{F'(·, aux)} ‖Δ‖² / |γ|(c_2). Thsi doesn't give anything useful if the
192 # transport is very small in distance.
193
194 dat.curvature_bound_components = lambda: (None, None) # 1.0
195 214
196 return Problem(dat, reg, aux, aux0, μ0, plot_factory=plot_factory) 215 return Problem(dat, reg, aux, aux0, μ0, plot_factory=plot_factory)

mercurial