Skip to content

Commit 5136672

Browse files
committed
fix phase fn calc for small x
1 parent 33ae5d1 commit 5136672

6 files changed

Lines changed: 37 additions & 29 deletions

File tree

CHANGELOG.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
Changelog
22
=========
33

4+
v2.5.0 (8/4/2023)
5+
-------------------
6+
* fix scattering function for very small spheres
7+
48
v2.4.0 (6/10/2023)
59
-------------------
610
* add mie_phase_matrix() to calculate scattering (Mueller) matrix

miepython/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
miepython.mie_phase_matrix(m, x, mu)
4343
4444
"""
45-
__version__ = '2.4.0'
45+
__version__ = '2.5.0'
4646
__author__ = 'Scott Prahl'
4747
__email__ = 'scott.prahl@oit.edu'
4848
__copyright__ = 'Copyright 2017-23, Scott Prahl'

miepython/miepython.py

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -476,8 +476,8 @@ def _small_mie_S1_S2(m, x, mu):
476476
return [S1, S2]
477477

478478

479-
@njit((complex128[:], complex128[:], float64, int32), cache=True)
480-
def normalization_factor(a, b, x, norm_int):
479+
@njit((complex128, float64, int32), cache=True)
480+
def normalization_factor(m, x, norm_int):
481481
"""
482482
Figure out scattering function normalization.
483483
@@ -492,7 +492,7 @@ def normalization_factor(a, b, x, norm_int):
492492
"""
493493
# Qsca normalization
494494
if norm_int == 3:
495-
return np.sqrt(np.pi * x**2)
495+
return x * np.sqrt(np.pi)
496496

497497
# Bohren Normalization
498498
if norm_int == 5:
@@ -503,26 +503,23 @@ def normalization_factor(a, b, x, norm_int):
503503
return 1
504504

505505
# calculate qsca and qext
506-
n = np.arange(1, len(a) + 1)
507-
cn = 2.0 * n + 1.0
508-
qext = 2 * np.sum(cn * (a.real + b.real)) / x**2
509-
qsca = 2 * np.sum(cn * (np.abs(a)**2 + np.abs(b)**2)) / x**2
506+
qext, qsca, _, _ = _mie_scalar(m, x)
510507

511508
# albedo Normalization
512509
if norm_int == 0:
513-
return np.sqrt(np.pi * x**2 * qext)
510+
return x * np.sqrt(np.pi * qext)
514511

515512
# Unity normalization
516513
if norm_int == 1:
517-
return np.sqrt(qsca * np.pi * x**2)
514+
return x * np.sqrt(qsca * np.pi)
518515

519516
# 4pi Normalization
520517
if norm_int == 2:
521-
return np.sqrt(qsca * x**2 / 4)
518+
return x * np.sqrt(qsca / 4)
522519

523520
# Qext Normalization
524521
if norm_int == 4: # 4pi
525-
return np.sqrt(qsca * np.pi * x**2 / qext)
522+
return x * np.sqrt(qsca * np.pi / qext)
526523

527524
raise ValueError("norm-int must be in the range 0..6")
528525

@@ -609,7 +606,7 @@ def _mie_S1_S2(m, x, mu, norm_int):
609606
pi_nm1 = ((2 * n + 1) * mu[k] * pi_nm1 - (n + 1) * pi_nm2) / n
610607
pi_nm2 = temp
611608

612-
normalization = normalization_factor(a, b, x, norm_int)
609+
normalization = normalization_factor(m, x, norm_int)
613610

614611
S1 /= normalization
615612
S2 /= normalization

miepython/miepython_nojit.py

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -465,13 +465,12 @@ def _small_mie_S1_S2(m, x, mu):
465465
return [S1, S2]
466466

467467

468-
def normalization_factor(a, b, x, norm_str):
468+
def normalization_factor(m, x, norm_str):
469469
"""
470470
Figure out scattering function normalization.
471471
472472
Args:
473-
a: complex array of An coefficients
474-
b: complex array of Bn coefficients
473+
m: complex index of refraction of sphere
475474
x: dimensionless sphere size
476475
norm_str: string describing type of normalization
477476
@@ -486,26 +485,22 @@ def normalization_factor(a, b, x, norm_str):
486485
if norm in ['wiscombe']:
487486
return 1
488487

489-
n = np.arange(1, len(a) + 1)
490-
cn = 2.0 * n + 1.0
491-
qext = 2 * np.sum(cn * (a.real + b.real)) / x**2
488+
if norm in ['qsca', 'scattering_efficiency']:
489+
return x * np.sqrt(np.pi)
492490

493-
if norm in ['a', 'albedo']:
494-
return np.sqrt(np.pi * x**2 * qext)
491+
qext, qsca, _, _ = _mie_scalar(m, x)
495492

496-
qsca = 2 * np.sum(cn * (np.abs(a)**2 + np.abs(b)**2)) / x**2
493+
if norm in ['a', 'albedo']:
494+
return x * np.sqrt(np.pi * qext)
497495

498496
if norm in ['1', 'one', 'unity']:
499-
return np.sqrt(qsca * np.pi * x**2)
497+
return x * np.sqrt(qsca * np.pi)
500498

501499
if norm in ['four_pi', '4pi']:
502-
return np.sqrt(qsca * x**2 / 4)
503-
504-
if norm in ['qsca', 'scattering_efficiency']:
505-
return np.sqrt(np.pi * x**2)
500+
return x * np.sqrt(qsca / 4)
506501

507502
if norm in ['qext', 'extinction_efficiency']:
508-
return np.sqrt(qsca * np.pi * x**2 / qext)
503+
return x * np.sqrt(qsca * np.pi / qext)
509504

510505
raise ValueError("normalization must be one of 'albedo' (default), 'one'"
511506
"'4pi', 'qext', 'qsca', 'bohren', or 'wiscombe'")
@@ -549,7 +544,7 @@ def mie_S1_S2(m, x, mu, norm='albedo'):
549544
pi_nm1 = ((2 * n + 1) * mu[k] * pi_nm1 - (n + 1) * pi_nm2) / n
550545
pi_nm2 = temp
551546

552-
normalization = normalization_factor(a, b, x, norm)
547+
normalization = normalization_factor(m, x, norm)
553548

554549
S1 /= normalization
555550
S2 /= normalization

tests/test_jit.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,12 @@ def test_i_par_i_per_01(self):
467467
total = (total1 + total2) / 2
468468
self.assertAlmostEqual(total / expected[i], 1, delta=1e-3)
469469

470+
def test_molecular_hydrogen(self):
471+
m = 1.00013626
472+
x = 0.0006403246172921872
473+
mu = np.linspace(-1, 1, 100)
474+
ph = miepython.i_unpolarized(m, x, mu)
475+
self.assertAlmostEqual(ph[1], 0.1169791, delta=1e-5)
470476

471477
class MiePhaseMatrix(unittest.TestCase):
472478
def test_mie_phase_matrix_basic(self):

tests/test_nojit.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,12 @@ def test_i_par_i_per_01(self):
467467
total = (total1 + total2) / 2
468468
self.assertAlmostEqual(total / expected[i], 1, delta=1e-3)
469469

470+
def test_molecular_hydrogen(self):
471+
m = 1.00013626
472+
x = 0.0006403246172921872
473+
mu = np.linspace(-1, 1, 100)
474+
ph = miepython.i_unpolarized(m, x, mu)
475+
self.assertAlmostEqual(ph[1], 0.1169791, delta=1e-5)
470476

471477
class MiePhaseMatrix(unittest.TestCase):
472478
def test_mie_phase_matrix_basic(self):

0 commit comments

Comments
 (0)