Skip to content

scrape_off_layer

Module for calculating plasma scrape off layer physics

ScrapeOffLayer

Bases: Model

Model for calculating plasma scrape off layer physics.

Source code in process/models/physics/scrape_off_layer.py
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
class ScrapeOffLayer(Model):
    """Model for calculating plasma scrape off layer physics."""

    def __init__(self):
        self.outfile = constants.NOUT
        self.mfile = constants.MFILE

    def run(self):
        """Calculate the scrape off layer physics and update the physics variables."""
        self.data.physics.len_plasma_sol_eich13_power_decay = self.calculate_eich2013_sol_power_decay_length(  # noqa: E501
            p_plasma_separatrix_mw=self.data.physics.p_plasma_separatrix_mw,
            rmajor=self.data.physics.rmajor,
            b_plasma_surface_poloidal_average=self.data.physics.b_plasma_surface_poloidal_average,
            aspect=self.data.physics.aspect,
        )

        self.data.physics.len_plasma_sol_mast14_power_decay_1 = self.calculate_mast2014_sol_power_decay_length_1(  # noqa: E501
            p_plasma_separatrix_mw=self.data.physics.p_plasma_separatrix_mw,
            b_plasma_surface_poloidal_average=self.data.physics.b_plasma_surface_poloidal_average,
        )

        # NOTE: converting plasma_current from A to MA
        self.data.physics.len_plasma_sol_mast14_power_decay_2 = (
            self.calculate_mast2014_sol_power_decay_length_2(
                p_plasma_separatrix_mw=self.data.physics.p_plasma_separatrix_mw,
                cur_plasma_ma=self.data.physics.plasma_current / 1e6,
            )
        )

        self.data.physics.len_plasma_sol_eich11_jet_power_decay = (
            self.calculate_eich2011_jet_sol_power_decay_length(
                b_plasma_toroidal_on_axis=self.data.physics.b_plasma_toroidal_on_axis,
                q_cyl=self.data.physics.qstar,
                p_plasma_separatrix_mw=self.data.physics.p_plasma_separatrix_mw,
            )
        )

        self.data.physics.len_plasma_sol_eich11_jet_asdex_power_decay = (
            self.calculate_eich2011_jet_asdex_sol_power_decay_length(
                b_plasma_toroidal_on_axis=self.data.physics.b_plasma_toroidal_on_axis,
                q_cyl=self.data.physics.qstar,
                p_plasma_separatrix_mw=self.data.physics.p_plasma_separatrix_mw,
                rmajor=self.data.physics.rmajor,
            )
        )

        # Set to user input if OutbordSOLPowerDecayLengthModel = 1/USER_INUT
        match OutbordSOLPowerDecayLengthModel(
            self.data.physics.i_len_sol_outboard_power_decay
        ):
            case OutbordSOLPowerDecayLengthModel.EICH_2013:
                self.data.physics.len_sol_outboard_power_decay = (
                    self.data.physics.len_plasma_sol_eich13_power_decay
                )
            case OutbordSOLPowerDecayLengthModel.MAST_2014_1:
                self.data.physics.len_sol_outboard_power_decay = (
                    self.data.physics.len_plasma_sol_mast14_power_decay_1
                )
            case OutbordSOLPowerDecayLengthModel.MAST_2014_2:
                self.data.physics.len_sol_outboard_power_decay = (
                    self.data.physics.len_plasma_sol_mast14_power_decay_2
                )
            case OutbordSOLPowerDecayLengthModel.EICH_2011_JET:
                self.data.physics.len_sol_outboard_power_decay = (
                    self.data.physics.len_plasma_sol_eich11_jet_power_decay
                )
            case OutbordSOLPowerDecayLengthModel.EICH_2011_JET_ASDEX:
                self.data.physics.len_sol_outboard_power_decay = (
                    self.data.physics.len_plasma_sol_eich11_jet_asdex_power_decay
                )

        self.data.physics.len_sol_inboard_power_decay = (
            self.data.physics.f_len_sol_power_decay_inboard_outboard
            * self.data.physics.len_sol_outboard_power_decay
        )

        self.data.physics.a_plasma_outboard_sol_parallel = self.calculate_upstream_sol_outboard_parallel_area(  # noqa: E501
            rmajor=self.data.physics.rmajor,
            rminor=self.data.physics.rminor,
            len_plasma_sol_power_decay=self.data.physics.len_sol_outboard_power_decay,
            b_plasma_outboard_total=self.data.physics.b_plasma_outboard_total,
            b_plasma_surface_poloidal_average=self.data.physics.b_plasma_surface_poloidal_average,
        )

        self.data.physics.a_plasma_outboard_sol_eich13_parallel = self.calculate_upstream_sol_outboard_parallel_area(  # noqa: E501
            rmajor=self.data.physics.rmajor,
            rminor=self.data.physics.rminor,
            len_plasma_sol_power_decay=self.data.physics.len_plasma_sol_eich13_power_decay,
            b_plasma_outboard_total=self.data.physics.b_plasma_outboard_total,
            b_plasma_surface_poloidal_average=self.data.physics.b_plasma_surface_poloidal_average,
        )

        self.data.physics.pflux_plasma_outboard_sol_parallel_mw = (
            self.data.physics.p_plasma_separatrix_mw
            * self.data.physics.f_p_div_outboard_separatrix
            / self.data.physics.a_plasma_outboard_sol_parallel
        )

        self.data.physics.pflux_plasma_outboard_sol_eich13_parallel_mw = (
            self.data.physics.p_plasma_separatrix_mw
            / self.data.physics.a_plasma_outboard_sol_eich13_parallel
        )

        self.data.physics.len_div_outboard_lower_scarabosio15_power_spreading = self.calculate_scarabosio2015_power_spreading_factor(  # noqa: E501
            p_plasma_separatrix_mw=self.data.physics.p_plasma_separatrix_mw,
            b_plasma_surface_poloidal_average=self.data.physics.b_plasma_surface_poloidal_average,
            nd_plasma_separatrix_electron_19=self.data.physics.nd_plasma_separatrix_electron
            / 1e19,
            rmajor=self.data.physics.rmajor,
        )

        self.data.physics.len_div_outboard_lower_power_spreading = (
            self.data.physics.len_div_outboard_lower_scarabosio15_power_spreading
        )

    def output(self) -> None:
        """Output plasma scrape off layer physics information."""
        po.oheadr(self.outfile, "Plasma Scrape Off Layer")

        po.osubhd(self.outfile, "Power Decay Lengths (λ_q):")
        po.ovarre(
            self.outfile,
            "Outboard SOL power decay length model switch",
            "(i_len_sol_outboard_power_decay)",
            self.data.physics.i_len_sol_outboard_power_decay,
        )
        po.ocmmnt(
            self.outfile,
            "-> "
            + OutbordSOLPowerDecayLengthModel(
                self.data.physics.i_len_sol_outboard_power_decay
            ).description
            + " ",
        )
        po.ovarre(
            self.outfile,
            "Outboard SOL power decay length (λₒᵤₜ_q) [m]",
            "(len_sol_outboard_power_decay)",
            self.data.physics.len_sol_outboard_power_decay,
        )

        po.oblnkl(self.outfile)
        po.ovarre(
            self.outfile,
            "Inboard to outboard SOL power decay length ratio (λᵢₙ_q/λₒᵤₜ_q)",
            "(f_len_sol_power_decay_inboard_outboard)",
            self.data.physics.f_len_sol_power_decay_inboard_outboard,
        )
        po.ovarre(
            self.outfile,
            "Inboard SOL power decay length (λᵢₙ_q) [m]",
            "(len_sol_inboard_power_decay)",
            self.data.physics.len_sol_inboard_power_decay,
        )
        po.oblnkl(self.outfile)
        po.ovarre(
            self.outfile,
            "Eich 2013 SOL power decay length (λ_q) [m]",
            "(len_plasma_sol_eich13_power_decay)",
            self.data.physics.len_plasma_sol_eich13_power_decay,
        )
        po.ovarre(
            self.outfile,
            "MAST 2014 SOL power decay length 1 (λ_q) [m]",
            "(len_plasma_sol_mast14_power_decay_1)",
            self.data.physics.len_plasma_sol_mast14_power_decay_1,
        )
        po.ovarre(
            self.outfile,
            "MAST 2014 SOL power decay length 2 (λ_q) [m]",
            "(len_plasma_sol_mast14_power_decay_2)",
            self.data.physics.len_plasma_sol_mast14_power_decay_2,
        )
        po.ovarre(
            self.outfile,
            "Eich 2011 JET SOL power decay length (λ_q) [m]",
            "(len_plasma_sol_eich11_jet_power_decay)",
            self.data.physics.len_plasma_sol_eich11_jet_power_decay,
        )
        po.ovarre(
            self.outfile,
            "Eich 2011 JET + ASDEX Upgrade SOL power decay length (λ_q) [m]",
            "(len_plasma_sol_eich11_jet_asdex_power_decay)",
            self.data.physics.len_plasma_sol_eich11_jet_asdex_power_decay,
        )
        po.oblnkl(self.outfile)
        po.ocmmnt(self.outfile, "----------------------------")

        po.osubhd(self.outfile, "Upstream Outboard SOL Parallel Area and Power Flux:")

        po.ovarre(
            self.outfile,
            "Plasma outboard midplane SOL parallel area (Aₗₗ,ᵤ) [m²]",
            "(a_plasma_outboard_sol_parallel)",
            self.data.physics.a_plasma_outboard_sol_parallel,
        )
        po.oblnkl(self.outfile)

        po.ovarre(
            self.outfile,
            "Plasma outboard midplane Eich 2013 SOL parallel area (Aₗₗ,ᵤ) [m²]",
            "(a_plasma_outboard_sol_eich13_parallel)",
            self.data.physics.a_plasma_outboard_sol_eich13_parallel,
        )
        po.oblnkl(self.outfile)
        po.ovarre(
            self.outfile,
            "Plasma outboard midplane SOL parallel power flux (qₗₗ,ᵤ) [MW/m²]",
            "(pflux_plasma_outboard_sol_parallel_mw)",
            self.data.physics.pflux_plasma_outboard_sol_parallel_mw,
        )
        po.oblnkl(self.outfile)
        po.ovarre(
            self.outfile,
            "Plasma outboard midplane Eich 2013 SOL parallel power flux (qₗₗ,ᵤ) [MW/m²]",
            "(pflux_plasma_outboard_sol_eich13_parallel_mw)",
            self.data.physics.pflux_plasma_outboard_sol_eich13_parallel_mw,
        )
        po.oblnkl(self.outfile)
        po.ocmmnt(self.outfile, "----------------------------")
        po.osubhd(self.outfile, "Power Spreading Factors (S):")

        po.ovarre(
            self.outfile,
            "Outboard lower divertor power spreading factor (S) [m]",
            "(len_div_outboard_lower_power_spreading)",
            self.data.physics.len_div_outboard_lower_power_spreading,
        )
        po.ovarre(
            self.outfile,
            "Scarabosio 2015 H-mode power spreading factor (S) [m]",
            "(len_div_outboard_lower_scarabosio15_power_spreading)",
            self.data.physics.len_div_outboard_lower_scarabosio15_power_spreading,
        )
        po.oblnkl(self.outfile)
        po.ocmmnt(self.outfile, "----------------------------")
        po.oblnkl(self.outfile)
        po.ovarre(
            self.outfile,
            "Outboard lower divertor flux expansion factor for the divertor targets "
            "(fₓ)",
            "(f_b_div_outboard_lower_flux_expansion)",
            self.data.physics.f_b_div_outboard_lower_flux_expansion,
        )

    @staticmethod
    def calculate_eich2013_sol_power_decay_length(
        p_plasma_separatrix_mw: float,
        rmajor: float,
        b_plasma_surface_poloidal_average: float,
        aspect: float,
    ) -> float:
        """Calculate the Eich 2013 SOL power decay length (λ_q).

        Parameters
        ----------
        p_plasma_separatrix_mw : float
            Power crossing the separatrix (Pₛₑₚ) [MW]
        rmajor : float
            Major radius of the plasma (R₀) [m]
        b_plasma_surface_poloidal_average : float
            Poloidal magnetic field at the plasma surface (⟨Bₚₒₗ(a)⟩) [T]
        aspect : float
            Aspect ratio of the plasma (A)

        Returns
        -------
        float
            Eich 2013 SOL power decay length (λ_q) [m]

        Notes
        -----
        - The paper states that the poloidal field terms is for the outer midplane
        Bₚₒₗ(a), we are using the outer surface average

        References
        ----------
        [1] T. Eich et al., “Scaling of the tokamak near the scrape-off layer H-mode
        power width and implications for ITER,” Nuclear Fusion, vol. 53, no. 9,
        p. 093031, Aug. 2013, doi: 10.1088/0029-5515/53/9/093031.

        """
        return (
            1.35e-3
            * p_plasma_separatrix_mw**-0.02
            * rmajor**0.04
            * b_plasma_surface_poloidal_average**-0.92
            * aspect**-0.42
        )

    @staticmethod
    def calculate_mast2014_sol_power_decay_length_1(
        p_plasma_separatrix_mw: float,
        b_plasma_surface_poloidal_average: float,
    ) -> float:
        """Calculate the MAST 2014 SOL power decay length (λ_q).

        Parameters
        ----------
        p_plasma_separatrix_mw : float
            Power crossing the separatrix (Pₛₑₚ) [MW]
        b_plasma_surface_poloidal_average : float
            Poloidal magnetic field at the plasma surface (⟨Bₚₒₗ(a)⟩) [T]

        Returns
        -------
        float
            MAST 2014 SOL power decay length (λ_q) [m]

        Notes
        -----
        - The paper states that the poloidal field terms is for the outer midplane
        Bₚₒₗ(a), we are using the outer surface average

        References
        ----------
        [1] A. J. Thornton and A. Kirk, “Scaling of the scrape-off layer width during
        inter-ELM H modes on MAST as measured by infrared thermography,”
        Plasma Physics and Controlled Fusion, vol. 56, no. 5, p. 055008, Apr. 2014,
        doi: 10.1088/0741-3335/56/5/055008.

        """
        return (
            1.84e-3
            * p_plasma_separatrix_mw**0.18
            * b_plasma_surface_poloidal_average**-0.68
        )

    @staticmethod
    def calculate_mast2014_sol_power_decay_length_2(
        p_plasma_separatrix_mw: float,
        cur_plasma_ma: float,
    ) -> float:
        """Calculate the MAST 2014 SOL power decay length (λ_q).

        Parameters
        ----------
        p_plasma_separatrix_mw : float
            Power crossing the separatrix (Pₛₑₚ) [MW]
        cur_plasma_ma : float
            Plasma current (Iₚ) [MA]

        Returns
        -------
        float
            MAST 2014 SOL power decay length (λ_q) [m]


        References
        ----------
        [1] A. J. Thornton and A. Kirk, “Scaling of the scrape-off layer width during
        inter-ELM H modes on MAST as measured by infrared thermography,”
        Plasma Physics and Controlled Fusion, vol. 56, no. 5, p. 055008, Apr. 2014,
        doi: 10.1088/0741-3335/56/5/055008.

        """
        return 4.57e-3 * p_plasma_separatrix_mw**0.22 * cur_plasma_ma**-0.64

    @staticmethod
    def calculate_eich2011_jet_sol_power_decay_length(
        b_plasma_toroidal_on_axis: float,
        q_cyl: float,
        p_plasma_separatrix_mw: float,
    ) -> float:
        """Calculate the Eich 2011 JET SOL power decay length (λ_q).

        Parameters
        ----------
        b_plasma_toroidal_on_axis : float
            Toroidal magnetic field at the plasma axis (Bᴛ(R₀)) [T]
        q_cyl : float
            Cylindrical safety factor (q_cyl) [-]
        p_plasma_separatrix_mw : float
            Power crossing the separatrix (Pₛₑₚ) [MW]

        Returns
        -------
        float
            Eich 2011 JET SOL power decay length (λ_q) [m]

        Notes
        -----
        - The fit values can be found in Table 2 of [1].
        - The scaling is done for type-I ELMy H-mode plasmas

        References
        ----------
        [1] T. Eich, B. Sieglin, A. Scarabosio, W. Fundamenski, Robert James Goldston,
        and A. Herrmann, “Inter-ELM Power Decay Length for JET and ASDEX Upgrade:
        Measurement and Comparison with Heuristic Drift-Based Model,”
        Physical Review Letters, vol. 107, no. 21, Nov. 2011,
        doi: https://doi.org/10.1103/PhysRevLett.107.215001.

        """
        return (
            0.7e-3
            * b_plasma_toroidal_on_axis**-0.84
            * q_cyl**1.23
            * p_plasma_separatrix_mw**0.14
        )

    @staticmethod
    def calculate_eich2011_jet_asdex_sol_power_decay_length(
        b_plasma_toroidal_on_axis: float,
        q_cyl: float,
        p_plasma_separatrix_mw: float,
        rmajor: float,
    ) -> float:
        """Calculate the Eich 2011 JET + ASDEX Upgrade SOL power decay length (λ_q).

        Parameters
        ----------
        b_plasma_toroidal_on_axis : float
            Toroidal magnetic field at the plasma axis (Bᴛ(R₀)) [T]
        q_cyl : float
            Cylindrical safety factor (q_cyl) [-]
        p_plasma_separatrix_mw : float
            Power crossing the separatrix (Pₛₑₚ) [MW]
        rmajor : float
            Major radius of the plasma (R₀) [m]

        Returns
        -------
        float
            Eich 2011 JET + ASDEX Upgrade SOL power decay length (λ_q) [m]

        Notes
        -----
        - The fit values can be found in Table 2 of [1].
        - The scaling is done for type-I ELMy H-mode plasmas

        References
        ----------
        [1] T. Eich, B. Sieglin, A. Scarabosio, W. Fundamenski, Robert James Goldston,
        and A. Herrmann, “Inter-ELM Power Decay Length for JET and ASDEX Upgrade:
        Measurement and Comparison with Heuristic Drift-Based Model,”
        Physical Review Letters, vol. 107, no. 21, Nov. 2011,
        doi: https://doi.org/10.1103/PhysRevLett.107.215001.

        """
        return (
            0.73e-3
            * b_plasma_toroidal_on_axis**-0.78
            * q_cyl**1.2
            * p_plasma_separatrix_mw**0.1
            * rmajor**0.02
        )

    @staticmethod
    def calculate_upstream_sol_outboard_parallel_area(
        rmajor: float,
        rminor: float,
        len_plasma_sol_power_decay: float,
        b_plasma_outboard_total: float,
        b_plasma_surface_poloidal_average: float,
    ) -> float:
        """Calculate the outboard SOL upstream parallel area (Aₗₗ,ᵤ) [m²].

        Parameters
        ----------
        rmajor : float
            Major radius of the plasma (R₀) [m]
        rminor : float
            Minor radius of the plasma (a) [m]
        len_plasma_sol_power_decay : float
            Power decay length (λ_q) [m]
        b_plasma_outboard_total : float
            Total magnetic field at the plasma outboard (Bₜₒₜ(R₀+a)) [T]
        b_plasma_surface_poloidal_average : float
            Poloidal magnetic field at the plasma surface (⟨Bₚₒₗ(a)⟩) [T]

        Returns
        -------
        float
            Upstream outboard SOL parallel area (Aₗₗ,ᵤ) [m²]

        References
        ----------
        [1] P. C. Stangeby, “The Plasma Boundary of Magnetic Fusion Devices,” Jan. 2000,
        doi: 10.1201/9780367801489.

        [2] S. S. Henderson et al., “An overview of the STEP divertor design and the
        simple models driving the plasma exhaust scenario,” Nuclear Fusion, vol. 65,
        no. 1, pp. 016033-016033, Nov. 2024, doi: 10.1088/1741-4326/ad93e7.

        """
        return (
            (2 * np.pi * (rmajor + rminor))
            * len_plasma_sol_power_decay
            * (b_plasma_surface_poloidal_average / b_plasma_outboard_total)
        )

    @staticmethod
    def calculate_outboard_midplane_near_sol_radial_profile(
        rmajor: float,
        rminor: float,
        len_plasma_sol_power_decay: float,
        pflux_plasma_outboard_sol_parallel_mw: float,
        r: float | np.ndarray,
    ) -> float | np.ndarray:
        """Calculate the outboard midplane near SOL radial profile (qₗₗ(r)) [MW/m²].

        Parameters
        ----------
        rmajor : float
            Major radius of the plasma (R₀) [m]
        rminor : float
            Minor radius of the plasma (a) [m]
        len_plasma_sol_power_decay : float
            Power decay length (λ_q) [m]
        pflux_plasma_outboard_sol_parallel_mw : float
            Parallel power flux at the outboard midplane (qₗₗ,ᵤ) [MW/m²]
        r : float|np.ndarray
            Radial position(s) at which to calculate the SOL profile [m]

        Returns
        -------
        float|np.ndarray
            Outboard midplane SOL radial profile (qₗₗ(r)) [MW/m²]

        Raises
        ------
        ValueError
            If any radial position r is inside the plasma edge (r < rmajor + rminor)

        Notes
        -----
        - The exponential model is highly valid in the "near-SOL" (typically the first
        few millimeters to a centimeter outside the separatrix). In this region, parallel
        heat transport is dominated by classical electron heat conduction
        (Spitzer-Härm conductivity), which is vastly faster than perpendicular diffusion.
        This competition between fast parallel conduction and slow perpendicular
        diffusion naturally produces an exponential radial profile.

        - The midplane exponential assumes steady-state H-mode conditions without the
        massive, transient convective bursts caused by ELMs, which momentarily
        flatten the entire midplane profile.

        References
        ----------
        [1] T. Eich et al., “Scaling of the tokamak near the scrape-off layer H-mode
        power width and implications for ITER,” Nuclear Fusion, vol. 53, no. 9,
        p. 093031, Aug. 2013, doi: 10.1088/0029-5515/53/9/093031.

        """
        if np.any(r < (rmajor + rminor)):
            raise ValueError(
                f"Radial position {r=} must be greater than or equal to the plasma "
                f"edge {(rmajor + rminor)=}."
            )

        return pflux_plasma_outboard_sol_parallel_mw * np.exp(
            -(r - (rmajor + rminor)) / len_plasma_sol_power_decay
        )

    @staticmethod
    def calculate_eich_target_heat_flux_profile(
        rmajor: float,
        rminor: float,
        pflux_plasma_sol_parallel_mw: float,
        len_plasma_sol_power_decay: float,
        f_b_div_flux_expansion: float,
        len_plasma_sol_power_spreading: float,
        pflux_target_background_heat_flux_mw: float,
        r: float | np.ndarray,
    ) -> float | np.ndarray:
        """Calculate the Eich parallel target heat flux profile (qₗₗ,ₜ(r)) [MW/m²].

        Parameters
        ----------
        rmajor : float
            Major radius of the plasma (R₀) [m]
        rminor : float
            Minor radius of the plasma (a) [m]
        pflux_plasma_sol_parallel_mw : float
            Parallel power flux at the outboard midplane (qₗₗ,ᵤ) [MW/m²]
        len_plasma_sol_power_decay : float
            Power decay length (λ_q) [m]
        f_b_div_flux_expansion : float
            Divertor flux expansion factor (fₓ) [-]
        len_plasma_sol_power_spreading : float
            Power spreading length in the divertor (S) [m]
        pflux_target_background_heat_flux_mw : float
            Background heat flux at the divertor target [MW/m²]
        r : float|np.ndarray
            Radial position(s) at which to calculate the target heat flux profile [m]

        Returns
        -------
        float|np.ndarray
            Eich parallel target heat flux profile (qₗₗ,ₜ(r)) [MW/m²]

        Notes
        -----
        - The Eich parallel target heat flux profile is derived from the midplane
        exponential profile, taking into account the magnetic geometry and flux expansion
        between the midplane and the divertor target. The profile is typically
        characterized by a combination of an exponential decay and a Gaussian spreading
        due to cross-field transport in the divertor leg.

        References
        ----------
        [1] T. Eich, B. Sieglin, A. Scarabosio, W. Fundamenski, R. J. Goldston, and
        A. Herrmann, “Inter-ELM Power Decay Length for JET and ASDEX Upgrade: Measurement
        and Comparison with Heuristic Drift-Based Model,” Physical Review Letters,
        vol. 107, no. 21, Nov. 2011, doi: https://doi.org/10.1103/PhysRevLett.107.215001

        [2] T. Eich et al., “Scaling of the tokamak near the scrape-off layer H-mode
        power width and implications for ITER,” Nuclear Fusion, vol. 53, no. 9,
        p. 093031, Aug. 2013, doi: 10.1088/0029-5515/53/9/093031.

        """
        return (pflux_plasma_sol_parallel_mw / 2) * np.exp(
            (
                (len_plasma_sol_power_spreading)
                / (2 * len_plasma_sol_power_decay * f_b_div_flux_expansion)
            )
            ** 2
            - (
                (r - (rmajor + rminor))
                / (len_plasma_sol_power_decay * f_b_div_flux_expansion)
            )
        ) * scipy.special.erfc(
            (
                len_plasma_sol_power_spreading
                / (2 * len_plasma_sol_power_decay * f_b_div_flux_expansion)
            )
            - ((r - (rmajor + rminor)) / (len_plasma_sol_power_spreading))
        ) + pflux_target_background_heat_flux_mw

    @staticmethod
    def calculate_scarabosio2015_power_spreading_factor(
        p_plasma_separatrix_mw: float,
        b_plasma_surface_poloidal_average: float,
        nd_plasma_separatrix_electron_19: float,
        rmajor: float,
    ) -> float:
        """Calculate the Scarabosio 2015 H-mode power spreading factor (S).

        Parameters
        ----------
        p_plasma_separatrix_mw : float
            Power crossing the separatrix (Pₛₑₚ) [MW]
        b_plasma_surface_poloidal_average : float
            Poloidal magnetic field at the plasma surface (Bₚₒₗ(a))  [T]
        nd_plasma_separatrix_electron_19 : float
            Electron density at the separatrix (nₑ,ₛₑₚ) [10¹⁹ m⁻³]
        rmajor : float
            Major radius of the plasma (R₀) [m]

        Returns
        -------
        float
            Scarabosio 2015 H-mode power spreading factor (S) [m]

        Notes
        -----
        - The R² for the fit is 0.65

        References
        ----------
        [1] A. Scarabosio et al., “Scaling of the divertor power spreading (S-factor) in
        open and closed divertor operation in JET and ASDEX Upgrade,”
        Journal of Nuclear Materials, vol. 463, pp. 49-54, Aug. 2015,
        doi: 10.1016/j.jnucmat.2014.11.076.

        """
        return (
            0.12e-3
            * p_plasma_separatrix_mw**0.21
            * b_plasma_surface_poloidal_average**-0.82
            * nd_plasma_separatrix_electron_19**-0.02
            * rmajor**0.71
        )

outfile = constants.NOUT instance-attribute

mfile = constants.MFILE instance-attribute

run()

Calculate the scrape off layer physics and update the physics variables.

Source code in process/models/physics/scrape_off_layer.py
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
def run(self):
    """Calculate the scrape off layer physics and update the physics variables."""
    self.data.physics.len_plasma_sol_eich13_power_decay = self.calculate_eich2013_sol_power_decay_length(  # noqa: E501
        p_plasma_separatrix_mw=self.data.physics.p_plasma_separatrix_mw,
        rmajor=self.data.physics.rmajor,
        b_plasma_surface_poloidal_average=self.data.physics.b_plasma_surface_poloidal_average,
        aspect=self.data.physics.aspect,
    )

    self.data.physics.len_plasma_sol_mast14_power_decay_1 = self.calculate_mast2014_sol_power_decay_length_1(  # noqa: E501
        p_plasma_separatrix_mw=self.data.physics.p_plasma_separatrix_mw,
        b_plasma_surface_poloidal_average=self.data.physics.b_plasma_surface_poloidal_average,
    )

    # NOTE: converting plasma_current from A to MA
    self.data.physics.len_plasma_sol_mast14_power_decay_2 = (
        self.calculate_mast2014_sol_power_decay_length_2(
            p_plasma_separatrix_mw=self.data.physics.p_plasma_separatrix_mw,
            cur_plasma_ma=self.data.physics.plasma_current / 1e6,
        )
    )

    self.data.physics.len_plasma_sol_eich11_jet_power_decay = (
        self.calculate_eich2011_jet_sol_power_decay_length(
            b_plasma_toroidal_on_axis=self.data.physics.b_plasma_toroidal_on_axis,
            q_cyl=self.data.physics.qstar,
            p_plasma_separatrix_mw=self.data.physics.p_plasma_separatrix_mw,
        )
    )

    self.data.physics.len_plasma_sol_eich11_jet_asdex_power_decay = (
        self.calculate_eich2011_jet_asdex_sol_power_decay_length(
            b_plasma_toroidal_on_axis=self.data.physics.b_plasma_toroidal_on_axis,
            q_cyl=self.data.physics.qstar,
            p_plasma_separatrix_mw=self.data.physics.p_plasma_separatrix_mw,
            rmajor=self.data.physics.rmajor,
        )
    )

    # Set to user input if OutbordSOLPowerDecayLengthModel = 1/USER_INUT
    match OutbordSOLPowerDecayLengthModel(
        self.data.physics.i_len_sol_outboard_power_decay
    ):
        case OutbordSOLPowerDecayLengthModel.EICH_2013:
            self.data.physics.len_sol_outboard_power_decay = (
                self.data.physics.len_plasma_sol_eich13_power_decay
            )
        case OutbordSOLPowerDecayLengthModel.MAST_2014_1:
            self.data.physics.len_sol_outboard_power_decay = (
                self.data.physics.len_plasma_sol_mast14_power_decay_1
            )
        case OutbordSOLPowerDecayLengthModel.MAST_2014_2:
            self.data.physics.len_sol_outboard_power_decay = (
                self.data.physics.len_plasma_sol_mast14_power_decay_2
            )
        case OutbordSOLPowerDecayLengthModel.EICH_2011_JET:
            self.data.physics.len_sol_outboard_power_decay = (
                self.data.physics.len_plasma_sol_eich11_jet_power_decay
            )
        case OutbordSOLPowerDecayLengthModel.EICH_2011_JET_ASDEX:
            self.data.physics.len_sol_outboard_power_decay = (
                self.data.physics.len_plasma_sol_eich11_jet_asdex_power_decay
            )

    self.data.physics.len_sol_inboard_power_decay = (
        self.data.physics.f_len_sol_power_decay_inboard_outboard
        * self.data.physics.len_sol_outboard_power_decay
    )

    self.data.physics.a_plasma_outboard_sol_parallel = self.calculate_upstream_sol_outboard_parallel_area(  # noqa: E501
        rmajor=self.data.physics.rmajor,
        rminor=self.data.physics.rminor,
        len_plasma_sol_power_decay=self.data.physics.len_sol_outboard_power_decay,
        b_plasma_outboard_total=self.data.physics.b_plasma_outboard_total,
        b_plasma_surface_poloidal_average=self.data.physics.b_plasma_surface_poloidal_average,
    )

    self.data.physics.a_plasma_outboard_sol_eich13_parallel = self.calculate_upstream_sol_outboard_parallel_area(  # noqa: E501
        rmajor=self.data.physics.rmajor,
        rminor=self.data.physics.rminor,
        len_plasma_sol_power_decay=self.data.physics.len_plasma_sol_eich13_power_decay,
        b_plasma_outboard_total=self.data.physics.b_plasma_outboard_total,
        b_plasma_surface_poloidal_average=self.data.physics.b_plasma_surface_poloidal_average,
    )

    self.data.physics.pflux_plasma_outboard_sol_parallel_mw = (
        self.data.physics.p_plasma_separatrix_mw
        * self.data.physics.f_p_div_outboard_separatrix
        / self.data.physics.a_plasma_outboard_sol_parallel
    )

    self.data.physics.pflux_plasma_outboard_sol_eich13_parallel_mw = (
        self.data.physics.p_plasma_separatrix_mw
        / self.data.physics.a_plasma_outboard_sol_eich13_parallel
    )

    self.data.physics.len_div_outboard_lower_scarabosio15_power_spreading = self.calculate_scarabosio2015_power_spreading_factor(  # noqa: E501
        p_plasma_separatrix_mw=self.data.physics.p_plasma_separatrix_mw,
        b_plasma_surface_poloidal_average=self.data.physics.b_plasma_surface_poloidal_average,
        nd_plasma_separatrix_electron_19=self.data.physics.nd_plasma_separatrix_electron
        / 1e19,
        rmajor=self.data.physics.rmajor,
    )

    self.data.physics.len_div_outboard_lower_power_spreading = (
        self.data.physics.len_div_outboard_lower_scarabosio15_power_spreading
    )

output()

Output plasma scrape off layer physics information.

Source code in process/models/physics/scrape_off_layer.py
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
def output(self) -> None:
    """Output plasma scrape off layer physics information."""
    po.oheadr(self.outfile, "Plasma Scrape Off Layer")

    po.osubhd(self.outfile, "Power Decay Lengths (λ_q):")
    po.ovarre(
        self.outfile,
        "Outboard SOL power decay length model switch",
        "(i_len_sol_outboard_power_decay)",
        self.data.physics.i_len_sol_outboard_power_decay,
    )
    po.ocmmnt(
        self.outfile,
        "-> "
        + OutbordSOLPowerDecayLengthModel(
            self.data.physics.i_len_sol_outboard_power_decay
        ).description
        + " ",
    )
    po.ovarre(
        self.outfile,
        "Outboard SOL power decay length (λₒᵤₜ_q) [m]",
        "(len_sol_outboard_power_decay)",
        self.data.physics.len_sol_outboard_power_decay,
    )

    po.oblnkl(self.outfile)
    po.ovarre(
        self.outfile,
        "Inboard to outboard SOL power decay length ratio (λᵢₙ_q/λₒᵤₜ_q)",
        "(f_len_sol_power_decay_inboard_outboard)",
        self.data.physics.f_len_sol_power_decay_inboard_outboard,
    )
    po.ovarre(
        self.outfile,
        "Inboard SOL power decay length (λᵢₙ_q) [m]",
        "(len_sol_inboard_power_decay)",
        self.data.physics.len_sol_inboard_power_decay,
    )
    po.oblnkl(self.outfile)
    po.ovarre(
        self.outfile,
        "Eich 2013 SOL power decay length (λ_q) [m]",
        "(len_plasma_sol_eich13_power_decay)",
        self.data.physics.len_plasma_sol_eich13_power_decay,
    )
    po.ovarre(
        self.outfile,
        "MAST 2014 SOL power decay length 1 (λ_q) [m]",
        "(len_plasma_sol_mast14_power_decay_1)",
        self.data.physics.len_plasma_sol_mast14_power_decay_1,
    )
    po.ovarre(
        self.outfile,
        "MAST 2014 SOL power decay length 2 (λ_q) [m]",
        "(len_plasma_sol_mast14_power_decay_2)",
        self.data.physics.len_plasma_sol_mast14_power_decay_2,
    )
    po.ovarre(
        self.outfile,
        "Eich 2011 JET SOL power decay length (λ_q) [m]",
        "(len_plasma_sol_eich11_jet_power_decay)",
        self.data.physics.len_plasma_sol_eich11_jet_power_decay,
    )
    po.ovarre(
        self.outfile,
        "Eich 2011 JET + ASDEX Upgrade SOL power decay length (λ_q) [m]",
        "(len_plasma_sol_eich11_jet_asdex_power_decay)",
        self.data.physics.len_plasma_sol_eich11_jet_asdex_power_decay,
    )
    po.oblnkl(self.outfile)
    po.ocmmnt(self.outfile, "----------------------------")

    po.osubhd(self.outfile, "Upstream Outboard SOL Parallel Area and Power Flux:")

    po.ovarre(
        self.outfile,
        "Plasma outboard midplane SOL parallel area (Aₗₗ,ᵤ) [m²]",
        "(a_plasma_outboard_sol_parallel)",
        self.data.physics.a_plasma_outboard_sol_parallel,
    )
    po.oblnkl(self.outfile)

    po.ovarre(
        self.outfile,
        "Plasma outboard midplane Eich 2013 SOL parallel area (Aₗₗ,ᵤ) [m²]",
        "(a_plasma_outboard_sol_eich13_parallel)",
        self.data.physics.a_plasma_outboard_sol_eich13_parallel,
    )
    po.oblnkl(self.outfile)
    po.ovarre(
        self.outfile,
        "Plasma outboard midplane SOL parallel power flux (qₗₗ,ᵤ) [MW/m²]",
        "(pflux_plasma_outboard_sol_parallel_mw)",
        self.data.physics.pflux_plasma_outboard_sol_parallel_mw,
    )
    po.oblnkl(self.outfile)
    po.ovarre(
        self.outfile,
        "Plasma outboard midplane Eich 2013 SOL parallel power flux (qₗₗ,ᵤ) [MW/m²]",
        "(pflux_plasma_outboard_sol_eich13_parallel_mw)",
        self.data.physics.pflux_plasma_outboard_sol_eich13_parallel_mw,
    )
    po.oblnkl(self.outfile)
    po.ocmmnt(self.outfile, "----------------------------")
    po.osubhd(self.outfile, "Power Spreading Factors (S):")

    po.ovarre(
        self.outfile,
        "Outboard lower divertor power spreading factor (S) [m]",
        "(len_div_outboard_lower_power_spreading)",
        self.data.physics.len_div_outboard_lower_power_spreading,
    )
    po.ovarre(
        self.outfile,
        "Scarabosio 2015 H-mode power spreading factor (S) [m]",
        "(len_div_outboard_lower_scarabosio15_power_spreading)",
        self.data.physics.len_div_outboard_lower_scarabosio15_power_spreading,
    )
    po.oblnkl(self.outfile)
    po.ocmmnt(self.outfile, "----------------------------")
    po.oblnkl(self.outfile)
    po.ovarre(
        self.outfile,
        "Outboard lower divertor flux expansion factor for the divertor targets "
        "(fₓ)",
        "(f_b_div_outboard_lower_flux_expansion)",
        self.data.physics.f_b_div_outboard_lower_flux_expansion,
    )

calculate_eich2013_sol_power_decay_length(p_plasma_separatrix_mw, rmajor, b_plasma_surface_poloidal_average, aspect) staticmethod

Calculate the Eich 2013 SOL power decay length (λ_q).

Parameters:

Name Type Description Default
p_plasma_separatrix_mw float

Power crossing the separatrix (Pₛₑₚ) [MW]

required
rmajor float

Major radius of the plasma (R₀) [m]

required
b_plasma_surface_poloidal_average float

Poloidal magnetic field at the plasma surface (⟨Bₚₒₗ(a)⟩) [T]

required
aspect float

Aspect ratio of the plasma (A)

required

Returns:

Type Description
float

Eich 2013 SOL power decay length (λ_q) [m]

Notes
  • The paper states that the poloidal field terms is for the outer midplane Bₚₒₗ(a), we are using the outer surface average
References

[1] T. Eich et al., “Scaling of the tokamak near the scrape-off layer H-mode power width and implications for ITER,” Nuclear Fusion, vol. 53, no. 9, p. 093031, Aug. 2013, doi: 10.1088/0029-5515/53/9/093031.

Source code in process/models/physics/scrape_off_layer.py
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
@staticmethod
def calculate_eich2013_sol_power_decay_length(
    p_plasma_separatrix_mw: float,
    rmajor: float,
    b_plasma_surface_poloidal_average: float,
    aspect: float,
) -> float:
    """Calculate the Eich 2013 SOL power decay length (λ_q).

    Parameters
    ----------
    p_plasma_separatrix_mw : float
        Power crossing the separatrix (Pₛₑₚ) [MW]
    rmajor : float
        Major radius of the plasma (R₀) [m]
    b_plasma_surface_poloidal_average : float
        Poloidal magnetic field at the plasma surface (⟨Bₚₒₗ(a)⟩) [T]
    aspect : float
        Aspect ratio of the plasma (A)

    Returns
    -------
    float
        Eich 2013 SOL power decay length (λ_q) [m]

    Notes
    -----
    - The paper states that the poloidal field terms is for the outer midplane
    Bₚₒₗ(a), we are using the outer surface average

    References
    ----------
    [1] T. Eich et al., “Scaling of the tokamak near the scrape-off layer H-mode
    power width and implications for ITER,” Nuclear Fusion, vol. 53, no. 9,
    p. 093031, Aug. 2013, doi: 10.1088/0029-5515/53/9/093031.

    """
    return (
        1.35e-3
        * p_plasma_separatrix_mw**-0.02
        * rmajor**0.04
        * b_plasma_surface_poloidal_average**-0.92
        * aspect**-0.42
    )

calculate_mast2014_sol_power_decay_length_1(p_plasma_separatrix_mw, b_plasma_surface_poloidal_average) staticmethod

Calculate the MAST 2014 SOL power decay length (λ_q).

Parameters:

Name Type Description Default
p_plasma_separatrix_mw float

Power crossing the separatrix (Pₛₑₚ) [MW]

required
b_plasma_surface_poloidal_average float

Poloidal magnetic field at the plasma surface (⟨Bₚₒₗ(a)⟩) [T]

required

Returns:

Type Description
float

MAST 2014 SOL power decay length (λ_q) [m]

Notes
  • The paper states that the poloidal field terms is for the outer midplane Bₚₒₗ(a), we are using the outer surface average
References

[1] A. J. Thornton and A. Kirk, “Scaling of the scrape-off layer width during inter-ELM H modes on MAST as measured by infrared thermography,” Plasma Physics and Controlled Fusion, vol. 56, no. 5, p. 055008, Apr. 2014, doi: 10.1088/0741-3335/56/5/055008.

Source code in process/models/physics/scrape_off_layer.py
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
@staticmethod
def calculate_mast2014_sol_power_decay_length_1(
    p_plasma_separatrix_mw: float,
    b_plasma_surface_poloidal_average: float,
) -> float:
    """Calculate the MAST 2014 SOL power decay length (λ_q).

    Parameters
    ----------
    p_plasma_separatrix_mw : float
        Power crossing the separatrix (Pₛₑₚ) [MW]
    b_plasma_surface_poloidal_average : float
        Poloidal magnetic field at the plasma surface (⟨Bₚₒₗ(a)⟩) [T]

    Returns
    -------
    float
        MAST 2014 SOL power decay length (λ_q) [m]

    Notes
    -----
    - The paper states that the poloidal field terms is for the outer midplane
    Bₚₒₗ(a), we are using the outer surface average

    References
    ----------
    [1] A. J. Thornton and A. Kirk, “Scaling of the scrape-off layer width during
    inter-ELM H modes on MAST as measured by infrared thermography,”
    Plasma Physics and Controlled Fusion, vol. 56, no. 5, p. 055008, Apr. 2014,
    doi: 10.1088/0741-3335/56/5/055008.

    """
    return (
        1.84e-3
        * p_plasma_separatrix_mw**0.18
        * b_plasma_surface_poloidal_average**-0.68
    )

calculate_mast2014_sol_power_decay_length_2(p_plasma_separatrix_mw, cur_plasma_ma) staticmethod

Calculate the MAST 2014 SOL power decay length (λ_q).

Parameters:

Name Type Description Default
p_plasma_separatrix_mw float

Power crossing the separatrix (Pₛₑₚ) [MW]

required
cur_plasma_ma float

Plasma current (Iₚ) [MA]

required

Returns:

Type Description
float

MAST 2014 SOL power decay length (λ_q) [m]

References

[1] A. J. Thornton and A. Kirk, “Scaling of the scrape-off layer width during inter-ELM H modes on MAST as measured by infrared thermography,” Plasma Physics and Controlled Fusion, vol. 56, no. 5, p. 055008, Apr. 2014, doi: 10.1088/0741-3335/56/5/055008.

Source code in process/models/physics/scrape_off_layer.py
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
@staticmethod
def calculate_mast2014_sol_power_decay_length_2(
    p_plasma_separatrix_mw: float,
    cur_plasma_ma: float,
) -> float:
    """Calculate the MAST 2014 SOL power decay length (λ_q).

    Parameters
    ----------
    p_plasma_separatrix_mw : float
        Power crossing the separatrix (Pₛₑₚ) [MW]
    cur_plasma_ma : float
        Plasma current (Iₚ) [MA]

    Returns
    -------
    float
        MAST 2014 SOL power decay length (λ_q) [m]


    References
    ----------
    [1] A. J. Thornton and A. Kirk, “Scaling of the scrape-off layer width during
    inter-ELM H modes on MAST as measured by infrared thermography,”
    Plasma Physics and Controlled Fusion, vol. 56, no. 5, p. 055008, Apr. 2014,
    doi: 10.1088/0741-3335/56/5/055008.

    """
    return 4.57e-3 * p_plasma_separatrix_mw**0.22 * cur_plasma_ma**-0.64

calculate_eich2011_jet_sol_power_decay_length(b_plasma_toroidal_on_axis, q_cyl, p_plasma_separatrix_mw) staticmethod

Calculate the Eich 2011 JET SOL power decay length (λ_q).

Parameters:

Name Type Description Default
b_plasma_toroidal_on_axis float

Toroidal magnetic field at the plasma axis (Bᴛ(R₀)) [T]

required
q_cyl float

Cylindrical safety factor (q_cyl) [-]

required
p_plasma_separatrix_mw float

Power crossing the separatrix (Pₛₑₚ) [MW]

required

Returns:

Type Description
float

Eich 2011 JET SOL power decay length (λ_q) [m]

Notes
  • The fit values can be found in Table 2 of [1].
  • The scaling is done for type-I ELMy H-mode plasmas
References

[1] T. Eich, B. Sieglin, A. Scarabosio, W. Fundamenski, Robert James Goldston, and A. Herrmann, “Inter-ELM Power Decay Length for JET and ASDEX Upgrade: Measurement and Comparison with Heuristic Drift-Based Model,” Physical Review Letters, vol. 107, no. 21, Nov. 2011, doi: https://doi.org/10.1103/PhysRevLett.107.215001.

Source code in process/models/physics/scrape_off_layer.py
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
@staticmethod
def calculate_eich2011_jet_sol_power_decay_length(
    b_plasma_toroidal_on_axis: float,
    q_cyl: float,
    p_plasma_separatrix_mw: float,
) -> float:
    """Calculate the Eich 2011 JET SOL power decay length (λ_q).

    Parameters
    ----------
    b_plasma_toroidal_on_axis : float
        Toroidal magnetic field at the plasma axis (Bᴛ(R₀)) [T]
    q_cyl : float
        Cylindrical safety factor (q_cyl) [-]
    p_plasma_separatrix_mw : float
        Power crossing the separatrix (Pₛₑₚ) [MW]

    Returns
    -------
    float
        Eich 2011 JET SOL power decay length (λ_q) [m]

    Notes
    -----
    - The fit values can be found in Table 2 of [1].
    - The scaling is done for type-I ELMy H-mode plasmas

    References
    ----------
    [1] T. Eich, B. Sieglin, A. Scarabosio, W. Fundamenski, Robert James Goldston,
    and A. Herrmann, “Inter-ELM Power Decay Length for JET and ASDEX Upgrade:
    Measurement and Comparison with Heuristic Drift-Based Model,”
    Physical Review Letters, vol. 107, no. 21, Nov. 2011,
    doi: https://doi.org/10.1103/PhysRevLett.107.215001.

    """
    return (
        0.7e-3
        * b_plasma_toroidal_on_axis**-0.84
        * q_cyl**1.23
        * p_plasma_separatrix_mw**0.14
    )

calculate_eich2011_jet_asdex_sol_power_decay_length(b_plasma_toroidal_on_axis, q_cyl, p_plasma_separatrix_mw, rmajor) staticmethod

Calculate the Eich 2011 JET + ASDEX Upgrade SOL power decay length (λ_q).

Parameters:

Name Type Description Default
b_plasma_toroidal_on_axis float

Toroidal magnetic field at the plasma axis (Bᴛ(R₀)) [T]

required
q_cyl float

Cylindrical safety factor (q_cyl) [-]

required
p_plasma_separatrix_mw float

Power crossing the separatrix (Pₛₑₚ) [MW]

required
rmajor float

Major radius of the plasma (R₀) [m]

required

Returns:

Type Description
float

Eich 2011 JET + ASDEX Upgrade SOL power decay length (λ_q) [m]

Notes
  • The fit values can be found in Table 2 of [1].
  • The scaling is done for type-I ELMy H-mode plasmas
References

[1] T. Eich, B. Sieglin, A. Scarabosio, W. Fundamenski, Robert James Goldston, and A. Herrmann, “Inter-ELM Power Decay Length for JET and ASDEX Upgrade: Measurement and Comparison with Heuristic Drift-Based Model,” Physical Review Letters, vol. 107, no. 21, Nov. 2011, doi: https://doi.org/10.1103/PhysRevLett.107.215001.

Source code in process/models/physics/scrape_off_layer.py
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
@staticmethod
def calculate_eich2011_jet_asdex_sol_power_decay_length(
    b_plasma_toroidal_on_axis: float,
    q_cyl: float,
    p_plasma_separatrix_mw: float,
    rmajor: float,
) -> float:
    """Calculate the Eich 2011 JET + ASDEX Upgrade SOL power decay length (λ_q).

    Parameters
    ----------
    b_plasma_toroidal_on_axis : float
        Toroidal magnetic field at the plasma axis (Bᴛ(R₀)) [T]
    q_cyl : float
        Cylindrical safety factor (q_cyl) [-]
    p_plasma_separatrix_mw : float
        Power crossing the separatrix (Pₛₑₚ) [MW]
    rmajor : float
        Major radius of the plasma (R₀) [m]

    Returns
    -------
    float
        Eich 2011 JET + ASDEX Upgrade SOL power decay length (λ_q) [m]

    Notes
    -----
    - The fit values can be found in Table 2 of [1].
    - The scaling is done for type-I ELMy H-mode plasmas

    References
    ----------
    [1] T. Eich, B. Sieglin, A. Scarabosio, W. Fundamenski, Robert James Goldston,
    and A. Herrmann, “Inter-ELM Power Decay Length for JET and ASDEX Upgrade:
    Measurement and Comparison with Heuristic Drift-Based Model,”
    Physical Review Letters, vol. 107, no. 21, Nov. 2011,
    doi: https://doi.org/10.1103/PhysRevLett.107.215001.

    """
    return (
        0.73e-3
        * b_plasma_toroidal_on_axis**-0.78
        * q_cyl**1.2
        * p_plasma_separatrix_mw**0.1
        * rmajor**0.02
    )

calculate_upstream_sol_outboard_parallel_area(rmajor, rminor, len_plasma_sol_power_decay, b_plasma_outboard_total, b_plasma_surface_poloidal_average) staticmethod

Calculate the outboard SOL upstream parallel area (Aₗₗ,ᵤ) [m²].

Parameters:

Name Type Description Default
rmajor float

Major radius of the plasma (R₀) [m]

required
rminor float

Minor radius of the plasma (a) [m]

required
len_plasma_sol_power_decay float

Power decay length (λ_q) [m]

required
b_plasma_outboard_total float

Total magnetic field at the plasma outboard (Bₜₒₜ(R₀+a)) [T]

required
b_plasma_surface_poloidal_average float

Poloidal magnetic field at the plasma surface (⟨Bₚₒₗ(a)⟩) [T]

required

Returns:

Type Description
float

Upstream outboard SOL parallel area (Aₗₗ,ᵤ) [m²]

References

[1] P. C. Stangeby, “The Plasma Boundary of Magnetic Fusion Devices,” Jan. 2000, doi: 10.1201/9780367801489.

[2] S. S. Henderson et al., “An overview of the STEP divertor design and the simple models driving the plasma exhaust scenario,” Nuclear Fusion, vol. 65, no. 1, pp. 016033-016033, Nov. 2024, doi: 10.1088/1741-4326/ad93e7.

Source code in process/models/physics/scrape_off_layer.py
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
@staticmethod
def calculate_upstream_sol_outboard_parallel_area(
    rmajor: float,
    rminor: float,
    len_plasma_sol_power_decay: float,
    b_plasma_outboard_total: float,
    b_plasma_surface_poloidal_average: float,
) -> float:
    """Calculate the outboard SOL upstream parallel area (Aₗₗ,ᵤ) [m²].

    Parameters
    ----------
    rmajor : float
        Major radius of the plasma (R₀) [m]
    rminor : float
        Minor radius of the plasma (a) [m]
    len_plasma_sol_power_decay : float
        Power decay length (λ_q) [m]
    b_plasma_outboard_total : float
        Total magnetic field at the plasma outboard (Bₜₒₜ(R₀+a)) [T]
    b_plasma_surface_poloidal_average : float
        Poloidal magnetic field at the plasma surface (⟨Bₚₒₗ(a)⟩) [T]

    Returns
    -------
    float
        Upstream outboard SOL parallel area (Aₗₗ,ᵤ) [m²]

    References
    ----------
    [1] P. C. Stangeby, “The Plasma Boundary of Magnetic Fusion Devices,” Jan. 2000,
    doi: 10.1201/9780367801489.

    [2] S. S. Henderson et al., “An overview of the STEP divertor design and the
    simple models driving the plasma exhaust scenario,” Nuclear Fusion, vol. 65,
    no. 1, pp. 016033-016033, Nov. 2024, doi: 10.1088/1741-4326/ad93e7.

    """
    return (
        (2 * np.pi * (rmajor + rminor))
        * len_plasma_sol_power_decay
        * (b_plasma_surface_poloidal_average / b_plasma_outboard_total)
    )

calculate_outboard_midplane_near_sol_radial_profile(rmajor, rminor, len_plasma_sol_power_decay, pflux_plasma_outboard_sol_parallel_mw, r) staticmethod

Calculate the outboard midplane near SOL radial profile (qₗₗ®) [MW/m²].

Parameters:

Name Type Description Default
rmajor float

Major radius of the plasma (R₀) [m]

required
rminor float

Minor radius of the plasma (a) [m]

required
len_plasma_sol_power_decay float

Power decay length (λ_q) [m]

required
pflux_plasma_outboard_sol_parallel_mw float

Parallel power flux at the outboard midplane (qₗₗ,ᵤ) [MW/m²]

required
r float | ndarray

Radial position(s) at which to calculate the SOL profile [m]

required

Returns:

Type Description
float | ndarray

Outboard midplane SOL radial profile (qₗₗ®) [MW/m²]

Raises:

Type Description
ValueError

If any radial position r is inside the plasma edge (r < rmajor + rminor)

Notes
  • The exponential model is highly valid in the "near-SOL" (typically the first few millimeters to a centimeter outside the separatrix). In this region, parallel heat transport is dominated by classical electron heat conduction (Spitzer-Härm conductivity), which is vastly faster than perpendicular diffusion. This competition between fast parallel conduction and slow perpendicular diffusion naturally produces an exponential radial profile.

  • The midplane exponential assumes steady-state H-mode conditions without the massive, transient convective bursts caused by ELMs, which momentarily flatten the entire midplane profile.

References

[1] T. Eich et al., “Scaling of the tokamak near the scrape-off layer H-mode power width and implications for ITER,” Nuclear Fusion, vol. 53, no. 9, p. 093031, Aug. 2013, doi: 10.1088/0029-5515/53/9/093031.

Source code in process/models/physics/scrape_off_layer.py
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
@staticmethod
def calculate_outboard_midplane_near_sol_radial_profile(
    rmajor: float,
    rminor: float,
    len_plasma_sol_power_decay: float,
    pflux_plasma_outboard_sol_parallel_mw: float,
    r: float | np.ndarray,
) -> float | np.ndarray:
    """Calculate the outboard midplane near SOL radial profile (qₗₗ(r)) [MW/m²].

    Parameters
    ----------
    rmajor : float
        Major radius of the plasma (R₀) [m]
    rminor : float
        Minor radius of the plasma (a) [m]
    len_plasma_sol_power_decay : float
        Power decay length (λ_q) [m]
    pflux_plasma_outboard_sol_parallel_mw : float
        Parallel power flux at the outboard midplane (qₗₗ,ᵤ) [MW/m²]
    r : float|np.ndarray
        Radial position(s) at which to calculate the SOL profile [m]

    Returns
    -------
    float|np.ndarray
        Outboard midplane SOL radial profile (qₗₗ(r)) [MW/m²]

    Raises
    ------
    ValueError
        If any radial position r is inside the plasma edge (r < rmajor + rminor)

    Notes
    -----
    - The exponential model is highly valid in the "near-SOL" (typically the first
    few millimeters to a centimeter outside the separatrix). In this region, parallel
    heat transport is dominated by classical electron heat conduction
    (Spitzer-Härm conductivity), which is vastly faster than perpendicular diffusion.
    This competition between fast parallel conduction and slow perpendicular
    diffusion naturally produces an exponential radial profile.

    - The midplane exponential assumes steady-state H-mode conditions without the
    massive, transient convective bursts caused by ELMs, which momentarily
    flatten the entire midplane profile.

    References
    ----------
    [1] T. Eich et al., “Scaling of the tokamak near the scrape-off layer H-mode
    power width and implications for ITER,” Nuclear Fusion, vol. 53, no. 9,
    p. 093031, Aug. 2013, doi: 10.1088/0029-5515/53/9/093031.

    """
    if np.any(r < (rmajor + rminor)):
        raise ValueError(
            f"Radial position {r=} must be greater than or equal to the plasma "
            f"edge {(rmajor + rminor)=}."
        )

    return pflux_plasma_outboard_sol_parallel_mw * np.exp(
        -(r - (rmajor + rminor)) / len_plasma_sol_power_decay
    )

calculate_eich_target_heat_flux_profile(rmajor, rminor, pflux_plasma_sol_parallel_mw, len_plasma_sol_power_decay, f_b_div_flux_expansion, len_plasma_sol_power_spreading, pflux_target_background_heat_flux_mw, r) staticmethod

Calculate the Eich parallel target heat flux profile (qₗₗ,ₜ®) [MW/m²].

Parameters:

Name Type Description Default
rmajor float

Major radius of the plasma (R₀) [m]

required
rminor float

Minor radius of the plasma (a) [m]

required
pflux_plasma_sol_parallel_mw float

Parallel power flux at the outboard midplane (qₗₗ,ᵤ) [MW/m²]

required
len_plasma_sol_power_decay float

Power decay length (λ_q) [m]

required
f_b_div_flux_expansion float

Divertor flux expansion factor (fₓ) [-]

required
len_plasma_sol_power_spreading float

Power spreading length in the divertor (S) [m]

required
pflux_target_background_heat_flux_mw float

Background heat flux at the divertor target [MW/m²]

required
r float | ndarray

Radial position(s) at which to calculate the target heat flux profile [m]

required

Returns:

Type Description
float | ndarray

Eich parallel target heat flux profile (qₗₗ,ₜ®) [MW/m²]

Notes
  • The Eich parallel target heat flux profile is derived from the midplane exponential profile, taking into account the magnetic geometry and flux expansion between the midplane and the divertor target. The profile is typically characterized by a combination of an exponential decay and a Gaussian spreading due to cross-field transport in the divertor leg.
References

[1] T. Eich, B. Sieglin, A. Scarabosio, W. Fundamenski, R. J. Goldston, and A. Herrmann, “Inter-ELM Power Decay Length for JET and ASDEX Upgrade: Measurement and Comparison with Heuristic Drift-Based Model,” Physical Review Letters, vol. 107, no. 21, Nov. 2011, doi: https://doi.org/10.1103/PhysRevLett.107.215001

[2] T. Eich et al., “Scaling of the tokamak near the scrape-off layer H-mode power width and implications for ITER,” Nuclear Fusion, vol. 53, no. 9, p. 093031, Aug. 2013, doi: 10.1088/0029-5515/53/9/093031.

Source code in process/models/physics/scrape_off_layer.py
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
@staticmethod
def calculate_eich_target_heat_flux_profile(
    rmajor: float,
    rminor: float,
    pflux_plasma_sol_parallel_mw: float,
    len_plasma_sol_power_decay: float,
    f_b_div_flux_expansion: float,
    len_plasma_sol_power_spreading: float,
    pflux_target_background_heat_flux_mw: float,
    r: float | np.ndarray,
) -> float | np.ndarray:
    """Calculate the Eich parallel target heat flux profile (qₗₗ,ₜ(r)) [MW/m²].

    Parameters
    ----------
    rmajor : float
        Major radius of the plasma (R₀) [m]
    rminor : float
        Minor radius of the plasma (a) [m]
    pflux_plasma_sol_parallel_mw : float
        Parallel power flux at the outboard midplane (qₗₗ,ᵤ) [MW/m²]
    len_plasma_sol_power_decay : float
        Power decay length (λ_q) [m]
    f_b_div_flux_expansion : float
        Divertor flux expansion factor (fₓ) [-]
    len_plasma_sol_power_spreading : float
        Power spreading length in the divertor (S) [m]
    pflux_target_background_heat_flux_mw : float
        Background heat flux at the divertor target [MW/m²]
    r : float|np.ndarray
        Radial position(s) at which to calculate the target heat flux profile [m]

    Returns
    -------
    float|np.ndarray
        Eich parallel target heat flux profile (qₗₗ,ₜ(r)) [MW/m²]

    Notes
    -----
    - The Eich parallel target heat flux profile is derived from the midplane
    exponential profile, taking into account the magnetic geometry and flux expansion
    between the midplane and the divertor target. The profile is typically
    characterized by a combination of an exponential decay and a Gaussian spreading
    due to cross-field transport in the divertor leg.

    References
    ----------
    [1] T. Eich, B. Sieglin, A. Scarabosio, W. Fundamenski, R. J. Goldston, and
    A. Herrmann, “Inter-ELM Power Decay Length for JET and ASDEX Upgrade: Measurement
    and Comparison with Heuristic Drift-Based Model,” Physical Review Letters,
    vol. 107, no. 21, Nov. 2011, doi: https://doi.org/10.1103/PhysRevLett.107.215001

    [2] T. Eich et al., “Scaling of the tokamak near the scrape-off layer H-mode
    power width and implications for ITER,” Nuclear Fusion, vol. 53, no. 9,
    p. 093031, Aug. 2013, doi: 10.1088/0029-5515/53/9/093031.

    """
    return (pflux_plasma_sol_parallel_mw / 2) * np.exp(
        (
            (len_plasma_sol_power_spreading)
            / (2 * len_plasma_sol_power_decay * f_b_div_flux_expansion)
        )
        ** 2
        - (
            (r - (rmajor + rminor))
            / (len_plasma_sol_power_decay * f_b_div_flux_expansion)
        )
    ) * scipy.special.erfc(
        (
            len_plasma_sol_power_spreading
            / (2 * len_plasma_sol_power_decay * f_b_div_flux_expansion)
        )
        - ((r - (rmajor + rminor)) / (len_plasma_sol_power_spreading))
    ) + pflux_target_background_heat_flux_mw

calculate_scarabosio2015_power_spreading_factor(p_plasma_separatrix_mw, b_plasma_surface_poloidal_average, nd_plasma_separatrix_electron_19, rmajor) staticmethod

Calculate the Scarabosio 2015 H-mode power spreading factor (S).

Parameters:

Name Type Description Default
p_plasma_separatrix_mw float

Power crossing the separatrix (Pₛₑₚ) [MW]

required
b_plasma_surface_poloidal_average float

Poloidal magnetic field at the plasma surface (Bₚₒₗ(a)) [T]

required
nd_plasma_separatrix_electron_19 float

Electron density at the separatrix (nₑ,ₛₑₚ) [10¹⁹ m⁻³]

required
rmajor float

Major radius of the plasma (R₀) [m]

required

Returns:

Type Description
float

Scarabosio 2015 H-mode power spreading factor (S) [m]

Notes
  • The R² for the fit is 0.65
References

[1] A. Scarabosio et al., “Scaling of the divertor power spreading (S-factor) in open and closed divertor operation in JET and ASDEX Upgrade,” Journal of Nuclear Materials, vol. 463, pp. 49-54, Aug. 2015, doi: 10.1016/j.jnucmat.2014.11.076.

Source code in process/models/physics/scrape_off_layer.py
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
@staticmethod
def calculate_scarabosio2015_power_spreading_factor(
    p_plasma_separatrix_mw: float,
    b_plasma_surface_poloidal_average: float,
    nd_plasma_separatrix_electron_19: float,
    rmajor: float,
) -> float:
    """Calculate the Scarabosio 2015 H-mode power spreading factor (S).

    Parameters
    ----------
    p_plasma_separatrix_mw : float
        Power crossing the separatrix (Pₛₑₚ) [MW]
    b_plasma_surface_poloidal_average : float
        Poloidal magnetic field at the plasma surface (Bₚₒₗ(a))  [T]
    nd_plasma_separatrix_electron_19 : float
        Electron density at the separatrix (nₑ,ₛₑₚ) [10¹⁹ m⁻³]
    rmajor : float
        Major radius of the plasma (R₀) [m]

    Returns
    -------
    float
        Scarabosio 2015 H-mode power spreading factor (S) [m]

    Notes
    -----
    - The R² for the fit is 0.65

    References
    ----------
    [1] A. Scarabosio et al., “Scaling of the divertor power spreading (S-factor) in
    open and closed divertor operation in JET and ASDEX Upgrade,”
    Journal of Nuclear Materials, vol. 463, pp. 49-54, Aug. 2015,
    doi: 10.1016/j.jnucmat.2014.11.076.

    """
    return (
        0.12e-3
        * p_plasma_separatrix_mw**0.21
        * b_plasma_surface_poloidal_average**-0.82
        * nd_plasma_separatrix_electron_19**-0.02
        * rmajor**0.71
    )