llg3d 2.0.0__tar.gz → 2.0.1__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.
- {llg3d-2.0.0 → llg3d-2.0.1}/PKG-INFO +2 -2
- {llg3d-2.0.0 → llg3d-2.0.1}/pyproject.toml +34 -1
- {llg3d-2.0.0 → llg3d-2.0.1}/src/llg3d/__init__.py +3 -1
- llg3d-2.0.1/src/llg3d/__main__.py +6 -0
- {llg3d-2.0.0 → llg3d-2.0.1}/src/llg3d/element.py +22 -16
- {llg3d-2.0.0 → llg3d-2.0.1}/src/llg3d/grid.py +7 -10
- {llg3d-2.0.0 → llg3d-2.0.1}/src/llg3d/main.py +6 -5
- {llg3d-2.0.0 → llg3d-2.0.1}/src/llg3d/output.py +9 -10
- {llg3d-2.0.0 → llg3d-2.0.1}/src/llg3d/parameters.py +3 -3
- llg3d-2.0.1/src/llg3d/post/__init__.py +1 -0
- {llg3d-2.0.0 → llg3d-2.0.1}/src/llg3d/post/plot_results.py +4 -8
- {llg3d-2.0.0 → llg3d-2.0.1}/src/llg3d/post/process.py +18 -13
- {llg3d-2.0.0 → llg3d-2.0.1}/src/llg3d/post/temperature.py +6 -13
- {llg3d-2.0.0 → llg3d-2.0.1}/src/llg3d/simulation.py +5 -14
- {llg3d-2.0.0 → llg3d-2.0.1}/src/llg3d/solver/__init__.py +2 -2
- {llg3d-2.0.0 → llg3d-2.0.1}/src/llg3d/solver/jax.py +44 -40
- {llg3d-2.0.0 → llg3d-2.0.1}/src/llg3d/solver/mpi.py +25 -24
- {llg3d-2.0.0 → llg3d-2.0.1}/src/llg3d/solver/numpy.py +11 -14
- {llg3d-2.0.0 → llg3d-2.0.1}/src/llg3d/solver/opencl.py +31 -30
- {llg3d-2.0.0 → llg3d-2.0.1}/src/llg3d/solver/solver.py +7 -11
- {llg3d-2.0.0 → llg3d-2.0.1}/src/llg3d.egg-info/PKG-INFO +2 -2
- {llg3d-2.0.0 → llg3d-2.0.1}/tests/test_element.py +3 -5
- {llg3d-2.0.0 → llg3d-2.0.1}/tests/test_grid.py +4 -1
- {llg3d-2.0.0 → llg3d-2.0.1}/tests/test_main.py +4 -1
- llg3d-2.0.0/src/llg3d/__main__.py +0 -6
- llg3d-2.0.0/src/llg3d/post/__init__.py +0 -1
- {llg3d-2.0.0 → llg3d-2.0.1}/AUTHORS +0 -0
- {llg3d-2.0.0 → llg3d-2.0.1}/LICENSE +0 -0
- {llg3d-2.0.0 → llg3d-2.0.1}/README.md +0 -0
- {llg3d-2.0.0 → llg3d-2.0.1}/setup.cfg +0 -0
- {llg3d-2.0.0 → llg3d-2.0.1}/src/llg3d.egg-info/SOURCES.txt +0 -0
- {llg3d-2.0.0 → llg3d-2.0.1}/src/llg3d.egg-info/dependency_links.txt +0 -0
- {llg3d-2.0.0 → llg3d-2.0.1}/src/llg3d.egg-info/entry_points.txt +0 -0
- {llg3d-2.0.0 → llg3d-2.0.1}/src/llg3d.egg-info/requires.txt +0 -0
- {llg3d-2.0.0 → llg3d-2.0.1}/src/llg3d.egg-info/top_level.txt +0 -0
- {llg3d-2.0.0 → llg3d-2.0.1}/tests/test_parameters.py +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: llg3d
|
|
3
|
-
Version: 2.0.
|
|
4
|
-
Summary:
|
|
3
|
+
Version: 2.0.1
|
|
4
|
+
Summary: A solver for the stochastic Landau-Lifshitz-Gilbert equation in 3D
|
|
5
5
|
Author-email: Clémentine Courtès <clementine.courtes@math.unistra.fr>, Matthieu Boileau <matthieu.boileau@math.unistra.fr>
|
|
6
6
|
Project-URL: Homepage, https://gitlab.math.unistra.fr/llg3d/llg3d
|
|
7
7
|
Classifier: Programming Language :: Python :: 3
|
|
@@ -8,7 +8,7 @@ authors = [
|
|
|
8
8
|
{ name = "Clémentine Courtès", email = "clementine.courtes@math.unistra.fr" },
|
|
9
9
|
{ name = "Matthieu Boileau", email = "matthieu.boileau@math.unistra.fr" },
|
|
10
10
|
]
|
|
11
|
-
description = "
|
|
11
|
+
description = "A solver for the stochastic Landau-Lifshitz-Gilbert equation in 3D"
|
|
12
12
|
classifiers = [
|
|
13
13
|
"Programming Language :: Python :: 3",
|
|
14
14
|
"License :: OSI Approved :: MIT License",
|
|
@@ -78,3 +78,36 @@ doc = [
|
|
|
78
78
|
"sphinxcontrib-bibtex",
|
|
79
79
|
"ipython",
|
|
80
80
|
]
|
|
81
|
+
|
|
82
|
+
[tool.ruff]
|
|
83
|
+
# Set line length to 88 (compatible with Black)
|
|
84
|
+
line-length = 88
|
|
85
|
+
exclude = ["src/llg3d/process_tmp/"]
|
|
86
|
+
|
|
87
|
+
[tool.ruff.lint.per-file-ignores]
|
|
88
|
+
# Ignore all directories named `tests`.
|
|
89
|
+
"tests/**" = ["D"]
|
|
90
|
+
|
|
91
|
+
[tool.ruff.lint]
|
|
92
|
+
# Enable pydocstyle (D) rules along with existing rules
|
|
93
|
+
select = ["E", "F", "W", "D"]
|
|
94
|
+
extend-select = ["D213"]
|
|
95
|
+
ignore = [
|
|
96
|
+
"D107", # Missing docstring in __init__()
|
|
97
|
+
# Style preferences - ignore D212 to enable D213 (Google convention)
|
|
98
|
+
"D212", # Multi-line docstring summary should start at the first line (we prefer D213)
|
|
99
|
+
]
|
|
100
|
+
|
|
101
|
+
[tool.ruff.lint.pydocstyle]
|
|
102
|
+
# Use Google convention for docstrings
|
|
103
|
+
convention = "google"
|
|
104
|
+
|
|
105
|
+
[tool.ruff.format]
|
|
106
|
+
# Use double quotes for strings (compatible with Black)
|
|
107
|
+
quote-style = "double"
|
|
108
|
+
# Use 4 spaces for indentation (compatible with Black)
|
|
109
|
+
indent-style = "space"
|
|
110
|
+
# Respect magic trailing comma (compatible with Black)
|
|
111
|
+
skip-magic-trailing-comma = false
|
|
112
|
+
# Line length compatible with Black
|
|
113
|
+
line-ending = "auto"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
"""Module containing the definition of the chemical elements."""
|
|
2
|
+
|
|
3
|
+
from abc import ABC
|
|
4
4
|
|
|
5
5
|
import numpy as np
|
|
6
6
|
|
|
@@ -11,8 +11,16 @@ mu_0 = 4 * np.pi * 1.0e-7 #: Vacuum permeability :math:`[H.m^{-1}]`
|
|
|
11
11
|
gamma = 1.76e11 #: Gyromagnetic ratio :math:`[rad.s^{-1}.T^{-1}]`
|
|
12
12
|
|
|
13
13
|
|
|
14
|
-
class Element:
|
|
15
|
-
"""
|
|
14
|
+
class Element(ABC):
|
|
15
|
+
"""
|
|
16
|
+
Abstract class for chemical elements.
|
|
17
|
+
|
|
18
|
+
Args:
|
|
19
|
+
T: Temperature in Kelvin
|
|
20
|
+
H_ext: External magnetic field strength
|
|
21
|
+
g: Grid object representing the simulation grid
|
|
22
|
+
dt: Time step for the simulation
|
|
23
|
+
"""
|
|
16
24
|
|
|
17
25
|
A = 0.0
|
|
18
26
|
K = 0.0
|
|
@@ -22,14 +30,6 @@ class Element:
|
|
|
22
30
|
anisotropy: str = ""
|
|
23
31
|
|
|
24
32
|
def __init__(self, T: float, H_ext: float, g: Grid, dt: float) -> None:
|
|
25
|
-
"""Initializes the Element class with given parameters
|
|
26
|
-
|
|
27
|
-
Args:
|
|
28
|
-
T: Temperature in Kelvin
|
|
29
|
-
H_ext: External magnetic field strength
|
|
30
|
-
g: Grid object representing the simulation grid
|
|
31
|
-
dt: Time step for the simulation
|
|
32
|
-
"""
|
|
33
33
|
self.H_ext = H_ext
|
|
34
34
|
self.g = g
|
|
35
35
|
self.dt = dt
|
|
@@ -52,16 +52,16 @@ class Element:
|
|
|
52
52
|
|
|
53
53
|
def get_CFL(self) -> float:
|
|
54
54
|
"""
|
|
55
|
-
Returns the value of the CFL
|
|
55
|
+
Returns the value of the CFL.
|
|
56
56
|
|
|
57
57
|
Returns:
|
|
58
|
-
|
|
58
|
+
The CFL value
|
|
59
59
|
"""
|
|
60
60
|
return self.dt * self.coeff_1 / self.g.dx**2
|
|
61
61
|
|
|
62
62
|
def to_dict(self) -> dict:
|
|
63
63
|
"""
|
|
64
|
-
Export element parameters to a dictionary for JAX JIT compatibility
|
|
64
|
+
Export element parameters to a dictionary for JAX JIT compatibility.
|
|
65
65
|
|
|
66
66
|
Returns:
|
|
67
67
|
Dictionary containing element parameters needed for computations
|
|
@@ -81,6 +81,8 @@ class Element:
|
|
|
81
81
|
|
|
82
82
|
|
|
83
83
|
class Cobalt(Element):
|
|
84
|
+
"""Cobalt element."""
|
|
85
|
+
|
|
84
86
|
A = 30.0e-12 #: Exchange constant :math:`[J.m^{-1}]`
|
|
85
87
|
K = 520.0e3 #: Anisotropy constant :math:`[J.m^{-3}]`
|
|
86
88
|
lambda_G = 0.5 #: Damping parameter :math:`[1]`
|
|
@@ -90,6 +92,8 @@ class Cobalt(Element):
|
|
|
90
92
|
|
|
91
93
|
|
|
92
94
|
class Iron(Element):
|
|
95
|
+
"""Iron element."""
|
|
96
|
+
|
|
93
97
|
A = 21.0e-12 #: Exchange constant :math:`[J.m^{-1}]`
|
|
94
98
|
K = 48.0e3 #: Anisotropy constant :math:`[J.m^{-3}]`
|
|
95
99
|
lambda_G = 0.5 #: Damping parameter :math:`[1]`
|
|
@@ -99,6 +103,8 @@ class Iron(Element):
|
|
|
99
103
|
|
|
100
104
|
|
|
101
105
|
class Nickel(Element):
|
|
106
|
+
"""Nickel element."""
|
|
107
|
+
|
|
102
108
|
A = 9.0e-12 #: Exchange constant :math:`[J.m^{-1}]`
|
|
103
109
|
K = -5.7e3 #: Anisotropy constant :math:`[J.m^{-3}]`
|
|
104
110
|
lambda_G = 0.5 #: Damping parameter :math:`[1]`
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Module to define the grid for the simulation
|
|
3
|
-
"""
|
|
1
|
+
"""Module to define the grid for the simulation."""
|
|
4
2
|
|
|
5
3
|
from dataclasses import dataclass
|
|
6
4
|
import numpy as np
|
|
@@ -10,7 +8,7 @@ from .solver import rank, size
|
|
|
10
8
|
|
|
11
9
|
@dataclass
|
|
12
10
|
class Grid:
|
|
13
|
-
"""Stores grid data"""
|
|
11
|
+
"""Stores grid data."""
|
|
14
12
|
|
|
15
13
|
# Parameter values correspond to the global grid
|
|
16
14
|
Jx: int #: number of points in x direction
|
|
@@ -19,7 +17,7 @@ class Grid:
|
|
|
19
17
|
dx: float #: grid spacing in x direction
|
|
20
18
|
|
|
21
19
|
def __post_init__(self) -> None:
|
|
22
|
-
"""Compute grid characteristics"""
|
|
20
|
+
"""Compute grid characteristics."""
|
|
23
21
|
self.dy = self.dz = self.dx # Setting dx = dy = dz
|
|
24
22
|
self.Lx = (self.Jx - 1) * self.dx
|
|
25
23
|
self.Ly = (self.Jy - 1) * self.dy
|
|
@@ -35,8 +33,7 @@ class Grid:
|
|
|
35
33
|
self.ncell = (self.Jx - 1) * (self.Jy - 1) * (self.Jz - 1)
|
|
36
34
|
|
|
37
35
|
def __str__(self) -> str:
|
|
38
|
-
"""Print grid information"""
|
|
39
|
-
|
|
36
|
+
"""Print grid information."""
|
|
40
37
|
header = "\t\t".join(("x", "y", "z"))
|
|
41
38
|
s = f"""\
|
|
42
39
|
\t{header}
|
|
@@ -55,7 +52,7 @@ ncell = {self.ncell:d}
|
|
|
55
52
|
self, T: float, name: str = "m1_mean", extension: str = "txt"
|
|
56
53
|
) -> str:
|
|
57
54
|
"""
|
|
58
|
-
Returns the output file name for a given temperature
|
|
55
|
+
Returns the output file name for a given temperature.
|
|
59
56
|
|
|
60
57
|
Args:
|
|
61
58
|
T: temperature
|
|
@@ -97,7 +94,7 @@ ncell = {self.ncell:d}
|
|
|
97
94
|
|
|
98
95
|
def to_dict(self) -> dict:
|
|
99
96
|
"""
|
|
100
|
-
Export grid parameters to a dictionary for JAX JIT compatibility
|
|
97
|
+
Export grid parameters to a dictionary for JAX JIT compatibility.
|
|
101
98
|
|
|
102
99
|
Returns:
|
|
103
100
|
Dictionary containing grid parameters needed for computations
|
|
@@ -114,7 +111,7 @@ ncell = {self.ncell:d}
|
|
|
114
111
|
|
|
115
112
|
def get_laplacian_coeff(self) -> tuple[float, float, float, float]:
|
|
116
113
|
"""
|
|
117
|
-
Returns the coefficients for the laplacian computation
|
|
114
|
+
Returns the coefficients for the laplacian computation.
|
|
118
115
|
|
|
119
116
|
Returns:
|
|
120
117
|
Tuple of coefficients (dx2_inv, dy2_inv, dz2_inv, center_coeff)
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Define a CLI for the llg3d package.
|
|
3
|
-
"""
|
|
1
|
+
"""Define a CLI for the llg3d package."""
|
|
4
2
|
|
|
5
3
|
import argparse
|
|
6
4
|
|
|
@@ -20,6 +18,7 @@ else:
|
|
|
20
18
|
def parse_args(args: list[str] | None) -> argparse.Namespace:
|
|
21
19
|
"""
|
|
22
20
|
Argument parser for llg3d.
|
|
21
|
+
|
|
23
22
|
Automatically adds arguments from the parameter dictionary.
|
|
24
23
|
|
|
25
24
|
Returns:
|
|
@@ -44,9 +43,11 @@ def parse_args(args: list[str] | None) -> argparse.Namespace:
|
|
|
44
43
|
|
|
45
44
|
def main(arg_list: list[str] = None):
|
|
46
45
|
"""
|
|
47
|
-
Evaluates the command line and runs the simulation
|
|
48
|
-
"""
|
|
46
|
+
Evaluates the command line and runs the simulation.
|
|
49
47
|
|
|
48
|
+
Args:
|
|
49
|
+
arg_list: List of command line arguments
|
|
50
|
+
"""
|
|
50
51
|
args = parse_args(arg_list)
|
|
51
52
|
|
|
52
53
|
if size > 1 and args.solver != "mpi":
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Utility functions for LLG3D
|
|
3
|
-
"""
|
|
1
|
+
"""Utility functions for LLG3D."""
|
|
4
2
|
|
|
5
3
|
import json
|
|
6
4
|
import sys
|
|
@@ -10,9 +8,11 @@ from .solver import rank
|
|
|
10
8
|
from .grid import Grid
|
|
11
9
|
|
|
12
10
|
|
|
13
|
-
def progress_bar(
|
|
11
|
+
def progress_bar(
|
|
12
|
+
it: Iterable, prefix: str = "", size: int = 60, out: TextIO = sys.stdout
|
|
13
|
+
):
|
|
14
14
|
"""
|
|
15
|
-
Displays a progress bar
|
|
15
|
+
Displays a progress bar.
|
|
16
16
|
|
|
17
17
|
(Source: https://stackoverflow.com/a/34482761/16593179)
|
|
18
18
|
|
|
@@ -22,14 +22,13 @@ def progress_bar(it: Iterable, prefix: str = "", size: int = 60, out: TextIO = s
|
|
|
22
22
|
size: Size of the progress bar (number of characters)
|
|
23
23
|
out: Output stream (default is sys.stdout)
|
|
24
24
|
"""
|
|
25
|
-
|
|
26
25
|
count = len(it)
|
|
27
26
|
|
|
28
27
|
def show(j):
|
|
29
28
|
x = int(size * j / count)
|
|
30
29
|
if rank == 0:
|
|
31
30
|
print(
|
|
32
|
-
f"{prefix}[{
|
|
31
|
+
f"{prefix}[{'█' * x}{('.' * (size - x))}] {j}/{count}",
|
|
33
32
|
end="\r",
|
|
34
33
|
file=out,
|
|
35
34
|
flush=True,
|
|
@@ -48,7 +47,7 @@ def progress_bar(it: Iterable, prefix: str = "", size: int = 60, out: TextIO = s
|
|
|
48
47
|
|
|
49
48
|
def write_json(json_file: str, run: dict):
|
|
50
49
|
"""
|
|
51
|
-
Writes the run dictionary to a JSON file
|
|
50
|
+
Writes the run dictionary to a JSON file.
|
|
52
51
|
|
|
53
52
|
Args:
|
|
54
53
|
json_file: Name of the JSON file
|
|
@@ -60,7 +59,7 @@ def write_json(json_file: str, run: dict):
|
|
|
60
59
|
|
|
61
60
|
def get_output_files(g: Grid, T: float, n_mean: int, n_profile: int) -> tuple:
|
|
62
61
|
"""
|
|
63
|
-
Open files and list them
|
|
62
|
+
Open files and list them.
|
|
64
63
|
|
|
65
64
|
Args:
|
|
66
65
|
g: Grid object
|
|
@@ -95,7 +94,7 @@ def get_output_files(g: Grid, T: float, n_mean: int, n_profile: int) -> tuple:
|
|
|
95
94
|
|
|
96
95
|
def close_output_files(f_mean: TextIO, f_profiles: list[TextIO] = None):
|
|
97
96
|
"""
|
|
98
|
-
Close all output files
|
|
97
|
+
Close all output files.
|
|
99
98
|
|
|
100
99
|
Args:
|
|
101
100
|
f_mean: file handler for storing m space integral over time
|
|
@@ -58,13 +58,13 @@ parameters: dict[str, Parameter] = {
|
|
|
58
58
|
|
|
59
59
|
def get_parameter_list(parameters: dict) -> str:
|
|
60
60
|
"""
|
|
61
|
-
Returns parameter values as a string
|
|
61
|
+
Returns parameter values as a string.
|
|
62
62
|
|
|
63
63
|
Args:
|
|
64
|
-
|
|
64
|
+
parameters: Dictionary of parameters parsed by argparse
|
|
65
65
|
|
|
66
66
|
Returns:
|
|
67
|
-
|
|
67
|
+
Formatted string of parameters
|
|
68
68
|
"""
|
|
69
69
|
width = max([len(name) for name in parameters])
|
|
70
70
|
s = ""
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Post-processing tools for LLG3D."""
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"""
|
|
2
|
-
Plot 1D curves from several files
|
|
2
|
+
Plot 1D curves from several files.
|
|
3
3
|
|
|
4
4
|
Usage:
|
|
5
5
|
|
|
@@ -25,7 +25,6 @@ def plot(*files: tuple[str], output_file: str = DEFAULT_OUTPUT_FILE):
|
|
|
25
25
|
files (tuple[str]): Paths to the result files.
|
|
26
26
|
output_file (str): Path to the output image file.
|
|
27
27
|
"""
|
|
28
|
-
|
|
29
28
|
fig, ax = plt.subplots()
|
|
30
29
|
for file in files:
|
|
31
30
|
if not file.endswith(".txt"):
|
|
@@ -43,12 +42,9 @@ def plot(*files: tuple[str], output_file: str = DEFAULT_OUTPUT_FILE):
|
|
|
43
42
|
|
|
44
43
|
|
|
45
44
|
def main():
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
)
|
|
49
|
-
parser.add_argument(
|
|
50
|
-
"files", nargs="+", type=str, help="Path to the result files."
|
|
51
|
-
)
|
|
45
|
+
"""Main function to parse arguments and call the plot function."""
|
|
46
|
+
parser = argparse.ArgumentParser(description="Plot results from one or more files.")
|
|
47
|
+
parser.add_argument("files", nargs="+", type=str, help="Path to the result files.")
|
|
52
48
|
parser.add_argument(
|
|
53
49
|
"--output",
|
|
54
50
|
"-o",
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
2
|
"""
|
|
3
|
-
Post-processes a set of runs
|
|
4
|
-
|
|
3
|
+
Post-processes a set of runs.
|
|
4
|
+
|
|
5
|
+
Runs are grouped into a `run.json` file or into a set of SLURM job arrays:
|
|
5
6
|
|
|
6
7
|
1. Extracts result data,
|
|
7
8
|
2. Plots the computed average magnetization against temperature,
|
|
8
9
|
3. Interpolates the computed points using cubic splines,
|
|
9
|
-
4. Determines the Curie temperature as the value corresponding to the minimal (negative)
|
|
10
|
+
4. Determines the Curie temperature as the value corresponding to the minimal (negative)
|
|
11
|
+
slope of the interpolated curve.
|
|
10
12
|
"""
|
|
11
13
|
|
|
12
14
|
import json
|
|
@@ -17,14 +19,11 @@ from scipy.interpolate import interp1d
|
|
|
17
19
|
|
|
18
20
|
|
|
19
21
|
class MagData:
|
|
20
|
-
"""
|
|
21
|
-
Class to handle magnetization data and interpolation according to temperature
|
|
22
|
-
"""
|
|
22
|
+
"""Class to handle magnetization data and interpolation according to temperature."""
|
|
23
23
|
|
|
24
24
|
n_interp = 200
|
|
25
25
|
|
|
26
26
|
def __init__(self, job_dir: Path = None, run_file: Path = Path("run.json")) -> None:
|
|
27
|
-
|
|
28
27
|
if job_dir:
|
|
29
28
|
self.parentpath = job_dir
|
|
30
29
|
data, self.run = self.process_slurm_jobs()
|
|
@@ -65,16 +64,18 @@ class MagData:
|
|
|
65
64
|
run = json.load(f)
|
|
66
65
|
# Adding temperature and averaging value to the data list
|
|
67
66
|
data.extend(
|
|
68
|
-
[
|
|
67
|
+
[
|
|
68
|
+
[float(T), res["m1_mean"]]
|
|
69
|
+
for T, res in run["results"].items()
|
|
70
|
+
]
|
|
69
71
|
)
|
|
70
72
|
except FileNotFoundError:
|
|
71
|
-
print(f"Warning: {json_filename} file not found
|
|
73
|
+
print(f"Warning: {json_filename} file not found in {jobdir.as_posix()}")
|
|
72
74
|
|
|
73
75
|
data.sort() # Sorting by increasing temperatures
|
|
74
76
|
|
|
75
77
|
return np.array(data), run
|
|
76
78
|
|
|
77
|
-
|
|
78
79
|
def process_json(json_filepath: Path) -> tuple[np.array, dict]:
|
|
79
80
|
"""
|
|
80
81
|
Reads the run.json file and extracts result data.
|
|
@@ -98,8 +99,12 @@ class MagData:
|
|
|
98
99
|
@property
|
|
99
100
|
def T_Curie(self) -> float:
|
|
100
101
|
"""
|
|
101
|
-
Return the Curie temperature
|
|
102
|
-
|
|
102
|
+
Return the Curie temperature.
|
|
103
|
+
|
|
104
|
+
It is defined as the temperature at which the magnetization is below 0.1.
|
|
105
|
+
|
|
106
|
+
Returns:
|
|
107
|
+
float: Curie temperature
|
|
103
108
|
"""
|
|
104
109
|
i_max = np.where(0.1 - self.interp(self.T) > 0)[0].min()
|
|
105
|
-
return self.T[i_max]
|
|
110
|
+
return self.T[i_max]
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
-
"""
|
|
3
|
-
Plot the magnetization vs temperature and determine the Curie temperature.
|
|
4
|
-
"""
|
|
2
|
+
"""Plot the magnetization vs temperature and determine the Curie temperature."""
|
|
5
3
|
|
|
6
4
|
import argparse
|
|
7
5
|
from pathlib import Path
|
|
@@ -13,17 +11,14 @@ from .process import MagData
|
|
|
13
11
|
|
|
14
12
|
def plot_m_vs_T(m: MagData, show: bool):
|
|
15
13
|
"""
|
|
16
|
-
Plots the data (T, <m>)
|
|
17
|
-
|
|
18
|
-
|
|
14
|
+
Plots the data (T, <m>).
|
|
15
|
+
|
|
16
|
+
Interpolates the values, calculates the Curie temperature, exports to PNG.
|
|
19
17
|
|
|
20
18
|
Args:
|
|
21
|
-
|
|
22
|
-
parentdir: path to the directory containing the runs
|
|
23
|
-
run: descriptive dictionary of the run
|
|
19
|
+
m: Magnetization data object
|
|
24
20
|
show: display the graph in a graphical window
|
|
25
21
|
"""
|
|
26
|
-
|
|
27
22
|
print(f"T_Curie = {m.T_Curie:.0f} K")
|
|
28
23
|
|
|
29
24
|
fig, ax = plt.subplots()
|
|
@@ -56,9 +51,7 @@ def plot_m_vs_T(m: MagData, show: bool):
|
|
|
56
51
|
|
|
57
52
|
|
|
58
53
|
def main():
|
|
59
|
-
"""
|
|
60
|
-
Parses the command line to execute processing functions
|
|
61
|
-
"""
|
|
54
|
+
"""Parses the command line to execute processing functions."""
|
|
62
55
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
63
56
|
parser.add_argument("--job_dir", type=Path, help="Slurm main job directory")
|
|
64
57
|
parser.add_argument(
|
|
@@ -23,17 +23,14 @@ from .output import write_json
|
|
|
23
23
|
class Simulation:
|
|
24
24
|
"""
|
|
25
25
|
Class to encapsulate the simulation logic.
|
|
26
|
+
|
|
27
|
+
Args:
|
|
28
|
+
params: Dictionary of simulation parameters.
|
|
26
29
|
"""
|
|
27
30
|
|
|
28
31
|
json_file = "run.json" #: JSON file to store the results
|
|
29
32
|
|
|
30
33
|
def __init__(self, params: dict[str, Parameter]):
|
|
31
|
-
"""
|
|
32
|
-
Initializes the simulation with parameters.
|
|
33
|
-
|
|
34
|
-
Args:
|
|
35
|
-
params: Dictionary of simulation parameters.
|
|
36
|
-
"""
|
|
37
34
|
self.params: dict[str, Parameter] = params.copy() #: simulation parameters
|
|
38
35
|
self.simulate: callable = self._get_simulate_function_from_name(
|
|
39
36
|
self.params["solver"]
|
|
@@ -46,9 +43,7 @@ class Simulation:
|
|
|
46
43
|
self.params["element_class"] = get_element_class(params["element"])
|
|
47
44
|
|
|
48
45
|
def run(self):
|
|
49
|
-
"""
|
|
50
|
-
Runs the simulation and store the results.
|
|
51
|
-
"""
|
|
46
|
+
"""Runs the simulation and store the results."""
|
|
52
47
|
self.total_time, self.filenames, self.m1_mean = self.simulate(**self.params)
|
|
53
48
|
|
|
54
49
|
def _get_simulate_function_from_name(self, name: str) -> callable:
|
|
@@ -62,19 +57,15 @@ class Simulation:
|
|
|
62
57
|
callable: The simulation function
|
|
63
58
|
|
|
64
59
|
Example:
|
|
65
|
-
|
|
66
60
|
>>> simulate = self.get_simulate_function_from_name("mpi")
|
|
67
61
|
|
|
68
62
|
Will return the `simulate` function from the `llg3d.solver.mpi` module.
|
|
69
63
|
"""
|
|
70
|
-
|
|
71
64
|
module = __import__(f"llg3d.solver.{name}", fromlist=["simulate"])
|
|
72
65
|
return inspect.getattr_static(module, "simulate")
|
|
73
66
|
|
|
74
67
|
def save(self):
|
|
75
|
-
"""
|
|
76
|
-
Saves the results of the simulation to a JSON file.
|
|
77
|
-
"""
|
|
68
|
+
"""Saves the results of the simulation to a JSON file."""
|
|
78
69
|
params = self.params.copy() # save the parameters
|
|
79
70
|
del params["element_class"] # remove class object before serialization
|
|
80
71
|
if rank == 0:
|