@@ -153,24 +153,22 @@ namespace impactx {
153153 }
154154
155155 amrex::ParticleReal
156- evaluate_lattice (ImpactX * sim, amrex::ParticleReal const & q1_k) // , amrex::ParticleReal q2_k)
156+ evaluate_lattice (ImpactX * sim, amrex::ParticleReal const & q1_k, amrex::ParticleReal const & q2_k)
157157 {
158- amrex::ParticleReal q2_k = 3.5 ;
158+ // Example from:
159+ // https://impactx.readthedocs.io/en/latest/usage/examples/fodo_space_charge/README.html
159160
160- // ns = 10 // TODO: number of slices per ds in the element
161+ int nslice = 50 ;
161162
162- auto dr1 = elements::Drift{2.7 };
163- auto q1 = elements::Quad{0.1 , q1_k};
164- auto dr2 = elements::Drift{1.4 };
165- auto q2 = elements::Quad{0.2 , q2_k};
166- auto dr3 = elements::Drift{1.4 };
167- auto q3 = elements::Quad{0.1 , q1_k};
168- auto dr4 = elements::Drift{2.7 };
163+ auto dr1 = elements::Drift{7.44e-2 };
164+ auto q1 = elements::Quad{6.10e-2 , q1_k};
165+ auto dr2 = elements::Drift{14.88e-2 };
166+ auto q2 = elements::Quad{6.10e-2 , q2_k};
169167
170168 /*
171169 // quadrupole triplet
172170 // https://impactx.readthedocs.io/en/latest/usage/examples/optimize_triplet/README.html
173- active_sim ->m_lattice = {
171+ sim ->m_lattice = {
174172 elements::Drift{2.7},
175173 elements::Quad{0.1, q1_k},
176174 elements::Drift{1.4},
@@ -191,41 +189,50 @@ namespace impactx {
191189
192190 // envelope mode
193191 // std::cout << "before ref\n";
194- auto ref = sim->amr_data ->track_envelope .m_ref .value ();
192+ RefPart & ref = sim->amr_data ->track_envelope .m_ref .value ();
195193 // std::cout << "before env\n";
196194 auto env = sim->amr_data ->track_envelope .m_env .value ();
197195 // std::cout << "before cm\n";
198196 auto cm = env.m_env ;
199197
200198 auto & intensity = env.m_beam_intensity ;
201- intensity = 1.0e-6 ; // a big value
199+ intensity = 0.5 ; // Ampere
202200
203- // push reference particle in global coordinates
204- dr1 (ref);
205- // push Covariance Matrix in external fields
206- dr1 (cm, ref);
207-
208- q1 (ref);
209- q1 (cm, ref);
210-
211- dr2 (ref);
212- dr2 (cm, ref);
213-
214- q2 (ref);
215- q2 (cm, ref);
216-
217- envelope::spacecharge::space_charge2D_push (ref, cm, intensity, q2.ds ());
201+ // sub-steps for space charge within the element
202+ for (int slice_step = 0 ; slice_step < nslice; ++slice_step)
203+ {
204+ envelope::spacecharge::space_charge2D_push (ref, cm, intensity, dr1.ds () / nslice);
205+ dr1 (ref);
206+ dr1 (cm, ref);
207+ }
218208
219- dr3 (ref);
220- dr3 (cm, ref);
209+ for (int slice_step = 0 ; slice_step < nslice; ++slice_step)
210+ {
211+ envelope::spacecharge::space_charge2D_push (ref, cm, intensity, q1.ds () / nslice);
212+ q1 (ref);
213+ q1 (cm, ref);
214+ }
221215
222- envelope::spacecharge::space_charge3D_push (ref, cm, intensity, dr3.ds ());
216+ for (int slice_step = 0 ; slice_step < nslice; ++slice_step)
217+ {
218+ envelope::spacecharge::space_charge2D_push (ref, cm, intensity, dr2.ds () / nslice);
219+ dr2 (ref);
220+ dr2 (cm, ref);
221+ }
223222
224- q3 (ref);
225- q3 (cm, ref);
223+ for (int slice_step = 0 ; slice_step < nslice; ++slice_step)
224+ {
225+ envelope::spacecharge::space_charge2D_push (ref, cm, intensity, q2.ds () / nslice);
226+ q2 (ref);
227+ q2 (cm, ref);
228+ }
226229
227- dr4 (ref);
228- dr4 (cm, ref);
230+ for (int slice_step = 0 ; slice_step < nslice; ++slice_step)
231+ {
232+ envelope::spacecharge::space_charge2D_push (ref, cm, intensity, dr1.ds () / nslice);
233+ dr1 (ref);
234+ dr1 (cm, ref);
235+ }
229236
230237 /*
231238 // particles
@@ -258,46 +265,58 @@ namespace impactx {
258265
259266 sim.init_grids ();
260267
261- // TODO: replace with beam params from https://impactx.readthedocs.io/en/latest/usage/examples/optimize_triplet /README.html
268+ // TODO: replace with beam params from https://impactx.readthedocs.io/en/latest/usage/examples/fodo_space_charge /README.html
262269 sim.initBeamDistributionFromInputs ();
263270
264271 // design the accelerator lattice
265272 // sim.initLatticeElementsFromInputs();
266273
267274 // initial quad strengths
268- amrex::ParticleReal q1_k = -3.0 ;
269- // amrex::ParticleReal q2_k = 3.0;
270- amrex::Print () << " q1_k = " << q1_k << std::endl;
275+ amrex::ParticleReal q1_k = -80.0 ;
276+ amrex::ParticleReal q2_k = 120.0 ;
277+ amrex::Print () << " q1_k = " << q1_k << " \n "
278+ << " q2_k = " << q2_k
279+ << std::endl;
271280
272281#define MYMODE 2
273282
274283#if MYMODE == 0
275284 // non-differentiable run:
276- amrex::ParticleReal ddx = std::numeric_limits<amrex::ParticleReal>::quiet_NaN ();
277- amrex::ParticleReal const alpha_x = evaluate_lattice (&sim, q1_k);
285+ amrex::ParticleReal dq1_k = std::numeric_limits<amrex::ParticleReal>::quiet_NaN ();
286+ amrex::ParticleReal dq2_k = std::numeric_limits<amrex::ParticleReal>::quiet_NaN ();
287+ amrex::ParticleReal const alpha_x = evaluate_lattice (&sim, q1_k, q2_k);
278288 amrex::Print () << " final alpha_x = " << alpha_x << std::endl;
279289
280290#elif MYMODE == 1
281291 // forward differentiable run
282292 // note: seeded direction, this is AD and NOT a finite difference
283293 amrex::ParticleReal dq1_k = 1.0 ;
294+ amrex::ParticleReal dq2_k = 1.0 ;
284295 amrex::ParticleReal ddx = __enzyme_fwddiff (
285296 &evaluate_lattice,
286297 enzyme_const, &sim,
287- enzyme_dup, &q1_k, &dq1_k
298+ enzyme_dup,
299+ &q1_k, &dq1_k,
300+ &q2_k, &dq2_k
288301 );
289302
290303#elif MYMODE == 2
291304 // reverse differentiable run:
292- amrex::ParticleReal ddx = 0.0 ; // accumulator, zero-init!
305+ amrex::ParticleReal dq1_k = 0.0 ; // accumulator, zero-init!
306+ amrex::ParticleReal dq2_k = 0.0 ; // accumulator, zero-init!
293307 __enzyme_autodiff (
294308 &evaluate_lattice,
295309 enzyme_const, &sim,
296- enzyme_dup, &q1_k, &ddx
310+ enzyme_dup,
311+ &q1_k, &dq1_k,
312+ &q2_k, &dq2_k
297313 );
298314#endif
299315
300- amrex::Print () << " ddx = " << ddx << std::endl;
316+ amrex::Print () << " final alpha_x = " << alpha_x << std::endl;
317+ amrex::Print () << " dq1_k = " << dq1_k << " \n "
318+ << " dq2_k = " << dq2_k
319+ << std::endl;
301320
302321 sim.finalize ();
303322 }
0 commit comments