mbsolver 0.2.0__tar.gz → 0.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {mbsolver-0.2.0/src/mbsolver.egg-info → mbsolver-0.3.0}/PKG-INFO +26 -2
- {mbsolver-0.2.0 → mbsolver-0.3.0}/README.md +25 -1
- {mbsolver-0.2.0 → mbsolver-0.3.0}/pyproject.toml +1 -1
- {mbsolver-0.2.0 → mbsolver-0.3.0}/src/mbsolver/__init__.py +4 -2
- mbsolver-0.3.0/src/mbsolver/constants.py +18 -0
- mbsolver-0.3.0/src/mbsolver/sample.py +74 -0
- {mbsolver-0.2.0 → mbsolver-0.3.0/src/mbsolver.egg-info}/PKG-INFO +26 -2
- {mbsolver-0.2.0 → mbsolver-0.3.0}/src/mbsolver.egg-info/SOURCES.txt +3 -0
- mbsolver-0.3.0/tests/test_sample.py +61 -0
- {mbsolver-0.2.0 → mbsolver-0.3.0}/LICENSE +0 -0
- {mbsolver-0.2.0 → mbsolver-0.3.0}/setup.cfg +0 -0
- {mbsolver-0.2.0 → mbsolver-0.3.0}/src/mbsolver/grids.py +0 -0
- {mbsolver-0.2.0 → mbsolver-0.3.0}/src/mbsolver/profiles.py +0 -0
- {mbsolver-0.2.0 → mbsolver-0.3.0}/src/mbsolver/two_level/__init__.py +0 -0
- {mbsolver-0.2.0 → mbsolver-0.3.0}/src/mbsolver/two_level/_kernel_1d.py +0 -0
- {mbsolver-0.2.0 → mbsolver-0.3.0}/src/mbsolver.egg-info/dependency_links.txt +0 -0
- {mbsolver-0.2.0 → mbsolver-0.3.0}/src/mbsolver.egg-info/requires.txt +0 -0
- {mbsolver-0.2.0 → mbsolver-0.3.0}/src/mbsolver.egg-info/top_level.txt +0 -0
- {mbsolver-0.2.0 → mbsolver-0.3.0}/tests/test_profiles.py +0 -0
- {mbsolver-0.2.0 → mbsolver-0.3.0}/tests/test_two_level.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mbsolver
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Fast Maxwell-Bloch solvers for masers, superradiance and coherent pulse propagation
|
|
5
5
|
Author-email: Vahid Anari <vahid.anari8@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -92,6 +92,29 @@ plt.show()
|
|
|
92
92
|
`res.time`, `res.z` (positions of the stored planes), `res.intensity` and
|
|
93
93
|
`res.w` (shape `(n_planes, nt)`), `res.pump`, `res.field_in`, `res.t1`, `res.t2`.
|
|
94
94
|
|
|
95
|
+
## From physical values: `scaling`
|
|
96
|
+
|
|
97
|
+
The solvers take dimensionless parameters. `scaling` computes them from the
|
|
98
|
+
physical sample values (SI units): transition frequency `nu` (Hz), spontaneous
|
|
99
|
+
decay rate `gamma` (s⁻¹), time unit `t0` (s), length `l` (m) and inverted
|
|
100
|
+
population density `n0` (m⁻³).
|
|
101
|
+
|
|
102
|
+
```python
|
|
103
|
+
import math
|
|
104
|
+
import mbsolver
|
|
105
|
+
from mbsolver.two_level import solve_1d
|
|
106
|
+
|
|
107
|
+
s = mbsolver.scaling(nu=6.67e9, gamma=1.56e-9, t0=86400, l=7.5e12, n0=5.3e-7)
|
|
108
|
+
res = solve_1d(t_max=2000, nt=20001, nz=101, eta=s["eta"], theta0=s["theta0"],
|
|
109
|
+
t1=math.inf, t2=math.inf)
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Besides `eta` (η = T₀/T_R) and `theta0` (θ₀ = 2/√N), the result holds `t_r`,
|
|
113
|
+
`N`, `omega`, `lambda`, `k`, `lambda0` (Λ₀ = 1/T₀) and the field, polarization
|
|
114
|
+
and intensity scales for an electric dipole (`d`, `e0`, `p0`, `i0_electric`)
|
|
115
|
+
and a magnetic dipole (`mu`, `b0`, `m0`, `i0_magnetic`). Times in the solver
|
|
116
|
+
are in units of `t0`.
|
|
117
|
+
|
|
95
118
|
## Profiles
|
|
96
119
|
|
|
97
120
|
`Pulse(a, x0, w)` is a sum of sech² pulses, `a_i sech²((t − x0_i) / w_i)`.
|
|
@@ -113,7 +136,8 @@ pytest
|
|
|
113
136
|
|
|
114
137
|
The tests include a reference run that must match the solver of the Maxwell
|
|
115
138
|
Bloch app (version 8.13) exactly, and physics checks (Bloch rotation at the
|
|
116
|
-
entrance, relaxation balance, uncoupled propagation).
|
|
139
|
+
entrance, relaxation balance, uncoupled propagation). `scaling` is checked
|
|
140
|
+
against the values of Maxwell Bloch Studio.
|
|
117
141
|
|
|
118
142
|
## Earlier name
|
|
119
143
|
|
|
@@ -61,6 +61,29 @@ plt.show()
|
|
|
61
61
|
`res.time`, `res.z` (positions of the stored planes), `res.intensity` and
|
|
62
62
|
`res.w` (shape `(n_planes, nt)`), `res.pump`, `res.field_in`, `res.t1`, `res.t2`.
|
|
63
63
|
|
|
64
|
+
## From physical values: `scaling`
|
|
65
|
+
|
|
66
|
+
The solvers take dimensionless parameters. `scaling` computes them from the
|
|
67
|
+
physical sample values (SI units): transition frequency `nu` (Hz), spontaneous
|
|
68
|
+
decay rate `gamma` (s⁻¹), time unit `t0` (s), length `l` (m) and inverted
|
|
69
|
+
population density `n0` (m⁻³).
|
|
70
|
+
|
|
71
|
+
```python
|
|
72
|
+
import math
|
|
73
|
+
import mbsolver
|
|
74
|
+
from mbsolver.two_level import solve_1d
|
|
75
|
+
|
|
76
|
+
s = mbsolver.scaling(nu=6.67e9, gamma=1.56e-9, t0=86400, l=7.5e12, n0=5.3e-7)
|
|
77
|
+
res = solve_1d(t_max=2000, nt=20001, nz=101, eta=s["eta"], theta0=s["theta0"],
|
|
78
|
+
t1=math.inf, t2=math.inf)
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Besides `eta` (η = T₀/T_R) and `theta0` (θ₀ = 2/√N), the result holds `t_r`,
|
|
82
|
+
`N`, `omega`, `lambda`, `k`, `lambda0` (Λ₀ = 1/T₀) and the field, polarization
|
|
83
|
+
and intensity scales for an electric dipole (`d`, `e0`, `p0`, `i0_electric`)
|
|
84
|
+
and a magnetic dipole (`mu`, `b0`, `m0`, `i0_magnetic`). Times in the solver
|
|
85
|
+
are in units of `t0`.
|
|
86
|
+
|
|
64
87
|
## Profiles
|
|
65
88
|
|
|
66
89
|
`Pulse(a, x0, w)` is a sum of sech² pulses, `a_i sech²((t − x0_i) / w_i)`.
|
|
@@ -82,7 +105,8 @@ pytest
|
|
|
82
105
|
|
|
83
106
|
The tests include a reference run that must match the solver of the Maxwell
|
|
84
107
|
Bloch app (version 8.13) exactly, and physics checks (Bloch rotation at the
|
|
85
|
-
entrance, relaxation balance, uncoupled propagation).
|
|
108
|
+
entrance, relaxation balance, uncoupled propagation). `scaling` is checked
|
|
109
|
+
against the values of Maxwell Bloch Studio.
|
|
86
110
|
|
|
87
111
|
## Earlier name
|
|
88
112
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "mbsolver"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.3.0"
|
|
8
8
|
description = "Fast Maxwell-Bloch solvers for masers, superradiance and coherent pulse propagation"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -2,16 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
Profiles (pump pulses, boundary fields, relaxation-time schedules) are built
|
|
4
4
|
with :class:`Pulse` and :class:`Steps`; the solvers live in model subpackages,
|
|
5
|
-
e.g. ``mbsolver.two_level.solve_1d``.
|
|
5
|
+
e.g. ``mbsolver.two_level.solve_1d``. :func:`scaling` turns the physical
|
|
6
|
+
sample values into the solvers' ``eta`` and ``theta0``.
|
|
6
7
|
"""
|
|
7
8
|
|
|
8
9
|
from importlib.metadata import PackageNotFoundError, version
|
|
9
10
|
|
|
10
11
|
from mbsolver.profiles import Pulse, Steps
|
|
12
|
+
from mbsolver.sample import scaling
|
|
11
13
|
|
|
12
14
|
try:
|
|
13
15
|
__version__ = version("mbsolver")
|
|
14
16
|
except PackageNotFoundError: # running from a source tree without install
|
|
15
17
|
__version__ = "0+unknown"
|
|
16
18
|
|
|
17
|
-
__all__ = ["Pulse", "Steps", "__version__"]
|
|
19
|
+
__all__ = ["Pulse", "Steps", "scaling", "__version__"]
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"""Physical constants in SI units, used by :mod:`mbsolver.sample`."""
|
|
2
|
+
|
|
3
|
+
import math
|
|
4
|
+
|
|
5
|
+
PI: float = math.pi
|
|
6
|
+
"""Circle constant."""
|
|
7
|
+
|
|
8
|
+
H_BAR: float = 6.62607015e-34 / (2.0 * PI)
|
|
9
|
+
"""Reduced Planck constant in joule-seconds."""
|
|
10
|
+
|
|
11
|
+
C: float = 2.99792458e8
|
|
12
|
+
"""Speed of light in meters per second."""
|
|
13
|
+
|
|
14
|
+
MU_0: float = 4.0 * PI * 1e-7
|
|
15
|
+
"""Vacuum permeability in henries per meter."""
|
|
16
|
+
|
|
17
|
+
EPSILON_0: float = 1.0 / (MU_0 * C**2)
|
|
18
|
+
"""Vacuum permittivity in farads per meter."""
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"""From the physical sample to the solver's dimensionless parameters.
|
|
2
|
+
|
|
3
|
+
The solvers work in dimensionless units: time in units of ``T0``, the medium
|
|
4
|
+
from ``z = 0`` to ``z = 1``. :func:`scaling` turns the physical values of a
|
|
5
|
+
maser sample into the coupling ``eta`` and initial Bloch angle ``theta0`` the
|
|
6
|
+
solvers take, together with the other derived scales::
|
|
7
|
+
|
|
8
|
+
import math
|
|
9
|
+
import mbsolver
|
|
10
|
+
from mbsolver.two_level import solve_1d
|
|
11
|
+
|
|
12
|
+
s = mbsolver.scaling(nu=6.67e9, gamma=1.56e-9, t0=86400, l=7.5e12, n0=5.3e-7)
|
|
13
|
+
res = solve_1d(t_max=2000, nt=20001, nz=101, eta=s["eta"], theta0=s["theta0"],
|
|
14
|
+
t1=math.inf, t2=math.inf)
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
19
|
+
import math
|
|
20
|
+
from typing import Dict
|
|
21
|
+
|
|
22
|
+
from mbsolver.constants import C, EPSILON_0, H_BAR, MU_0, PI
|
|
23
|
+
|
|
24
|
+
__all__ = ["scaling"]
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def scaling(nu: float, gamma: float, t0: float, l: float, n0: float) -> Dict[str, float]:
|
|
28
|
+
"""Compute the solver parameters and derived scales from the sample values.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
nu: Transition frequency ν in Hz.
|
|
32
|
+
gamma: Spontaneous decay rate Γ in s⁻¹.
|
|
33
|
+
t0: Time scale T₀ in s (the solver's unit of time).
|
|
34
|
+
l: Length of the medium L in m.
|
|
35
|
+
n0: Inverted population density n₀ in m⁻³.
|
|
36
|
+
|
|
37
|
+
Returns:
|
|
38
|
+
Mapping, all in SI units:
|
|
39
|
+
|
|
40
|
+
- ``eta``: coupling coefficient η = T₀ / T_R (the solvers' ``eta``),
|
|
41
|
+
- ``theta0``: initial Bloch angle θ₀ = 2 / √N (the solvers' ``theta0``),
|
|
42
|
+
- ``t_r``: superradiance time scale T_R,
|
|
43
|
+
- ``N``: number of molecules in a column of one wavelength squared,
|
|
44
|
+
- ``omega``, ``lambda``, ``k``: angular frequency, wavelength, wave number,
|
|
45
|
+
- ``lambda0``: pump scale Λ₀ = 1 / T₀,
|
|
46
|
+
- electric dipole: ``d`` (dipole moment), ``e0`` (field scale),
|
|
47
|
+
``p0`` (polarization scale), ``i0_electric`` (intensity scale),
|
|
48
|
+
- magnetic dipole: ``mu``, ``b0``, ``m0``, ``i0_magnetic``.
|
|
49
|
+
"""
|
|
50
|
+
omega0 = 2 * PI * nu
|
|
51
|
+
k = omega0 / C
|
|
52
|
+
_lambda = C / nu
|
|
53
|
+
t_r = 2.0 * k**2 / (3.0 * PI * gamma * n0 * l)
|
|
54
|
+
N = n0 * _lambda * l**2
|
|
55
|
+
eta = t0 / t_r
|
|
56
|
+
theta0 = 2.0 / math.sqrt(N)
|
|
57
|
+
lambda0 = 1.0 / t0
|
|
58
|
+
|
|
59
|
+
d = math.sqrt(3 * PI * EPSILON_0 * H_BAR * gamma / k**3)
|
|
60
|
+
p0 = n0 * d
|
|
61
|
+
e0 = H_BAR / (t0 * d)
|
|
62
|
+
i0_electric = 0.5 * EPSILON_0 * C * e0**2
|
|
63
|
+
|
|
64
|
+
mu = math.sqrt(3 * PI * H_BAR * gamma / (MU_0 * k**3))
|
|
65
|
+
m0 = n0 * mu
|
|
66
|
+
b0 = H_BAR / (t0 * mu)
|
|
67
|
+
i0_magnetic = C / (2.0 * MU_0) * b0**2
|
|
68
|
+
|
|
69
|
+
return {
|
|
70
|
+
"omega": omega0, "lambda": _lambda, "k": k, "t_r": t_r, "eta": eta,
|
|
71
|
+
"N": N, "theta0": theta0, "lambda0": lambda0,
|
|
72
|
+
"d": d, "e0": e0, "p0": p0, "i0_electric": i0_electric,
|
|
73
|
+
"mu": mu, "b0": b0, "m0": m0, "i0_magnetic": i0_magnetic,
|
|
74
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mbsolver
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Fast Maxwell-Bloch solvers for masers, superradiance and coherent pulse propagation
|
|
5
5
|
Author-email: Vahid Anari <vahid.anari8@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -92,6 +92,29 @@ plt.show()
|
|
|
92
92
|
`res.time`, `res.z` (positions of the stored planes), `res.intensity` and
|
|
93
93
|
`res.w` (shape `(n_planes, nt)`), `res.pump`, `res.field_in`, `res.t1`, `res.t2`.
|
|
94
94
|
|
|
95
|
+
## From physical values: `scaling`
|
|
96
|
+
|
|
97
|
+
The solvers take dimensionless parameters. `scaling` computes them from the
|
|
98
|
+
physical sample values (SI units): transition frequency `nu` (Hz), spontaneous
|
|
99
|
+
decay rate `gamma` (s⁻¹), time unit `t0` (s), length `l` (m) and inverted
|
|
100
|
+
population density `n0` (m⁻³).
|
|
101
|
+
|
|
102
|
+
```python
|
|
103
|
+
import math
|
|
104
|
+
import mbsolver
|
|
105
|
+
from mbsolver.two_level import solve_1d
|
|
106
|
+
|
|
107
|
+
s = mbsolver.scaling(nu=6.67e9, gamma=1.56e-9, t0=86400, l=7.5e12, n0=5.3e-7)
|
|
108
|
+
res = solve_1d(t_max=2000, nt=20001, nz=101, eta=s["eta"], theta0=s["theta0"],
|
|
109
|
+
t1=math.inf, t2=math.inf)
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Besides `eta` (η = T₀/T_R) and `theta0` (θ₀ = 2/√N), the result holds `t_r`,
|
|
113
|
+
`N`, `omega`, `lambda`, `k`, `lambda0` (Λ₀ = 1/T₀) and the field, polarization
|
|
114
|
+
and intensity scales for an electric dipole (`d`, `e0`, `p0`, `i0_electric`)
|
|
115
|
+
and a magnetic dipole (`mu`, `b0`, `m0`, `i0_magnetic`). Times in the solver
|
|
116
|
+
are in units of `t0`.
|
|
117
|
+
|
|
95
118
|
## Profiles
|
|
96
119
|
|
|
97
120
|
`Pulse(a, x0, w)` is a sum of sech² pulses, `a_i sech²((t − x0_i) / w_i)`.
|
|
@@ -113,7 +136,8 @@ pytest
|
|
|
113
136
|
|
|
114
137
|
The tests include a reference run that must match the solver of the Maxwell
|
|
115
138
|
Bloch app (version 8.13) exactly, and physics checks (Bloch rotation at the
|
|
116
|
-
entrance, relaxation balance, uncoupled propagation).
|
|
139
|
+
entrance, relaxation balance, uncoupled propagation). `scaling` is checked
|
|
140
|
+
against the values of Maxwell Bloch Studio.
|
|
117
141
|
|
|
118
142
|
## Earlier name
|
|
119
143
|
|
|
@@ -2,8 +2,10 @@ LICENSE
|
|
|
2
2
|
README.md
|
|
3
3
|
pyproject.toml
|
|
4
4
|
src/mbsolver/__init__.py
|
|
5
|
+
src/mbsolver/constants.py
|
|
5
6
|
src/mbsolver/grids.py
|
|
6
7
|
src/mbsolver/profiles.py
|
|
8
|
+
src/mbsolver/sample.py
|
|
7
9
|
src/mbsolver.egg-info/PKG-INFO
|
|
8
10
|
src/mbsolver.egg-info/SOURCES.txt
|
|
9
11
|
src/mbsolver.egg-info/dependency_links.txt
|
|
@@ -12,4 +14,5 @@ src/mbsolver.egg-info/top_level.txt
|
|
|
12
14
|
src/mbsolver/two_level/__init__.py
|
|
13
15
|
src/mbsolver/two_level/_kernel_1d.py
|
|
14
16
|
tests/test_profiles.py
|
|
17
|
+
tests/test_sample.py
|
|
15
18
|
tests/test_two_level.py
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"""Tests for mbsolver.scaling (physical sample -> solver parameters)."""
|
|
2
|
+
|
|
3
|
+
import math
|
|
4
|
+
|
|
5
|
+
import pytest
|
|
6
|
+
|
|
7
|
+
import mbsolver
|
|
8
|
+
from mbsolver.constants import C, PI
|
|
9
|
+
|
|
10
|
+
SAMPLE = dict(nu=6668.519e6, gamma=1.56e-9, t0=86400.0, l=7.5e12, n0=5.3e-7)
|
|
11
|
+
|
|
12
|
+
# Values from Maxwell Bloch Studio 10.0.3 (mbstudio.scaling) for SAMPLE.
|
|
13
|
+
REFERENCE = {
|
|
14
|
+
"N": 1.340262006320294e+18,
|
|
15
|
+
"b0": 1.8155752119506778e-18,
|
|
16
|
+
"d": 2.2424742818774253e-30,
|
|
17
|
+
"e0": 5.442957554745647e-10,
|
|
18
|
+
"eta": 0.12925265980137085,
|
|
19
|
+
"i0_electric": 3.9319621867605606e-22,
|
|
20
|
+
"i0_magnetic": 3.9319621867605615e-22,
|
|
21
|
+
"k": 139.76182349940206,
|
|
22
|
+
"lambda": 0.04495637757049204,
|
|
23
|
+
"lambda0": 1.1574074074074073e-05,
|
|
24
|
+
"m0": 3.5630674479188363e-28,
|
|
25
|
+
"mu": 6.722768769658182e-22,
|
|
26
|
+
"omega": 41899540601.44791,
|
|
27
|
+
"p0": 1.1885113693950354e-36,
|
|
28
|
+
"t_r": 668458.1975548919,
|
|
29
|
+
"theta0": 1.7275679662364094e-09,
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def test_matches_studio():
|
|
34
|
+
s = mbsolver.scaling(**SAMPLE)
|
|
35
|
+
assert sorted(s) == sorted(REFERENCE)
|
|
36
|
+
for key, value in REFERENCE.items():
|
|
37
|
+
assert s[key] == pytest.approx(value, rel=1e-13), key
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def test_relations():
|
|
41
|
+
s = mbsolver.scaling(**SAMPLE)
|
|
42
|
+
assert s["eta"] == pytest.approx(SAMPLE["t0"] / s["t_r"], rel=1e-15)
|
|
43
|
+
assert s["theta0"] == pytest.approx(2.0 / math.sqrt(s["N"]), rel=1e-15)
|
|
44
|
+
assert s["lambda"] == pytest.approx(C / SAMPLE["nu"], rel=1e-15)
|
|
45
|
+
assert s["k"] == pytest.approx(2 * PI / s["lambda"], rel=1e-14)
|
|
46
|
+
# electric and magnetic dipole give the same intensity scale
|
|
47
|
+
assert s["i0_electric"] == pytest.approx(s["i0_magnetic"], rel=1e-12)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def test_eta_scales_with_length_and_density():
|
|
51
|
+
s1 = mbsolver.scaling(**SAMPLE)
|
|
52
|
+
s2 = mbsolver.scaling(**{**SAMPLE, "l": 2 * SAMPLE["l"], "n0": 3 * SAMPLE["n0"]})
|
|
53
|
+
assert s2["eta"] == pytest.approx(6 * s1["eta"], rel=1e-14)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def test_feeds_the_solver():
|
|
57
|
+
from mbsolver.two_level import solve_1d
|
|
58
|
+
|
|
59
|
+
s = mbsolver.scaling(**SAMPLE)
|
|
60
|
+
res = solve_1d(t_max=10, nt=101, nz=11, eta=s["eta"], theta0=s["theta0"], t1=math.inf, t2=math.inf)
|
|
61
|
+
assert res.intensity.shape == (2, 101)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|