Skip to content

Commit

Permalink
Rescale doping concentrations exceeding 1 by a small margin, else error
Browse files Browse the repository at this point in the history
  • Loading branch information
sivonxay committed Oct 27, 2023
1 parent 6140843 commit 90a0a13
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 9 deletions.
34 changes: 25 additions & 9 deletions src/NanoParticleTools/inputs/nanoparticle.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,9 @@ def sites_in_bounds(self,
if center is None:
center = [0, 0, 0]

distances_from_center = np.linalg.norm(np.subtract(site_coords, center), axis=1)
distances_from_center = np.linalg.norm(np.subtract(
site_coords, center),
axis=1)
return distances_from_center <= self.radius

def __str__(self) -> str:
Expand Down Expand Up @@ -333,7 +335,8 @@ def __init__(self,

# Check if there are zero constraints
if len(constraints) == 0:
raise ValueError('There are no constraints, this particle is empty')
raise ValueError(
'There are no constraints, this particle is empty')
self.constraints = constraints

self.seed = seed if seed is not None else 0
Expand All @@ -349,8 +352,7 @@ def __init__(self,
conc_by_layer_and_species = [{} for _ in self.constraints]
for i, dopant_conc, _, replace_el in dopant_specification:
if dopant_conc < 0:
raise ValueError(
'Dopant concentration cannot be negative')
raise ValueError('Dopant concentration cannot be negative')

Check warning on line 355 in src/NanoParticleTools/inputs/nanoparticle.py

View check run for this annotation

Codecov / codecov/patch

src/NanoParticleTools/inputs/nanoparticle.py#L355

Added line #L355 was not covered by tests
if dopant_conc > 1:
raise ValueError(
'Dopant concentration cannot be greater than 1')
Expand All @@ -369,13 +371,27 @@ def __init__(self,
if total_replaced_conc > 0:
dopants_present = True
if total_replaced_conc > 1:
raise ValueError(
f"Dopant concentration in constraint {layer_i}"
f" on {replaced_el} sites exceeds 100%")
if total_replaced_conc - 1 < 1e-4:
# within some tolerance, just rescale the concentrations
# This is most likely a numerical representation/rounding issue
scale_factor = 1 / (total_replaced_conc + 1e-7)
for i in range(len(dopant_specification)):
dopant_spec = dopant_specification[i]
if dopant_spec[0] == layer_i:
dopant_specification[i] = (layer_i,
dopant_spec[1] *
scale_factor,
dopant_spec[2],
dopant_spec[3])
else:
raise ValueError(
f"Dopant concentration in constraint {layer_i}"
f" on {replaced_el} sites exceeds 100%")

if not dopants_present:
raise ValueError('There are no dopants being placed, this is an empty particle.'
'The result will be zero intensity for everything')
raise ValueError(
'There are no dopants being placed, this is an empty particle.'
'The result will be zero intensity for everything')

self.prune_hosts = prune_hosts
if prune_hosts:
Expand Down
27 changes: 27 additions & 0 deletions tests/inputs/test_nanoparticle.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,33 @@ def test_doped_nanoparticle():
assert len(dnp.sites) == 56


def test_doped_near_one():
with pytest.raises(ValueError):
constraints = [SphericalConstraint(10)]
dopants = [(0, 0.1, 'Yb', 'Y'), (0, 1, 'Er', 'Y')]
dnp = DopedNanoparticle(constraints, dopants)

with pytest.raises(ValueError):
constraints = [SphericalConstraint(10)]
dopants = [(0, 2e-4, 'Yb', 'Y'), (0, 1, 'Er', 'Y')]
dnp = DopedNanoparticle(constraints, dopants)

constraints = [SphericalConstraint(10)]
dopants = [(0, 0.33334, 'Yb', 'Y'), (0, 0.666667, 'Er', 'Y')]
dnp = DopedNanoparticle(constraints, dopants)
assert dnp.dopant_specification[0][1] == pytest.approx(0.333337, abs=1e-6)
assert dnp.dopant_specification[1][1] == pytest.approx(0.666662, abs=1e-6)

constraints = [SphericalConstraint(10), SphericalConstraint(20)]
dopants = [(0, 0.33334, 'Yb', 'Y'), (0, 0.666667, 'Er', 'Y'),
(1, .20001, 'Yb', 'Y'), (1, 0.8, 'Er', 'Y')]
dnp = DopedNanoparticle(constraints, dopants)
assert dnp.dopant_specification[0][1] == pytest.approx(0.333337, abs=1e-6)
assert dnp.dopant_specification[1][1] == pytest.approx(0.666662, abs=1e-6)
assert dnp.dopant_specification[2][1] == pytest.approx(0.200007, abs=1e-6)
assert dnp.dopant_specification[3][1] == pytest.approx(0.799992, abs=1e-6)


def test_nanoparticle_with_empty():
constraints = [
SphericalConstraint(40),
Expand Down

0 comments on commit 90a0a13

Please sign in to comment.