llg3d 2.0.1__py3-none-any.whl → 3.0.0__py3-none-any.whl

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.
Files changed (46) hide show
  1. llg3d/__init__.py +2 -4
  2. llg3d/benchmarks/__init__.py +1 -0
  3. llg3d/benchmarks/compare_commits.py +321 -0
  4. llg3d/benchmarks/efficiency.py +451 -0
  5. llg3d/benchmarks/utils.py +25 -0
  6. llg3d/element.py +98 -17
  7. llg3d/grid.py +48 -58
  8. llg3d/io.py +395 -0
  9. llg3d/main.py +32 -35
  10. llg3d/parameters.py +159 -49
  11. llg3d/post/__init__.py +1 -1
  12. llg3d/post/extract.py +105 -0
  13. llg3d/post/info.py +178 -0
  14. llg3d/post/m1_vs_T.py +90 -0
  15. llg3d/post/m1_vs_time.py +56 -0
  16. llg3d/post/process.py +87 -85
  17. llg3d/post/utils.py +38 -0
  18. llg3d/post/x_profiles.py +141 -0
  19. llg3d/py.typed +1 -0
  20. llg3d/solvers/__init__.py +153 -0
  21. llg3d/solvers/base.py +345 -0
  22. llg3d/solvers/experimental/__init__.py +9 -0
  23. llg3d/{solver → solvers/experimental}/jax.py +117 -143
  24. llg3d/solvers/math_utils.py +41 -0
  25. llg3d/solvers/mpi.py +370 -0
  26. llg3d/solvers/numpy.py +126 -0
  27. llg3d/solvers/opencl.py +439 -0
  28. llg3d/solvers/profiling.py +38 -0
  29. {llg3d-2.0.1.dist-info → llg3d-3.0.0.dist-info}/METADATA +5 -2
  30. llg3d-3.0.0.dist-info/RECORD +36 -0
  31. {llg3d-2.0.1.dist-info → llg3d-3.0.0.dist-info}/WHEEL +1 -1
  32. llg3d-3.0.0.dist-info/entry_points.txt +9 -0
  33. llg3d/output.py +0 -107
  34. llg3d/post/plot_results.py +0 -61
  35. llg3d/post/temperature.py +0 -76
  36. llg3d/simulation.py +0 -95
  37. llg3d/solver/__init__.py +0 -45
  38. llg3d/solver/mpi.py +0 -450
  39. llg3d/solver/numpy.py +0 -207
  40. llg3d/solver/opencl.py +0 -330
  41. llg3d/solver/solver.py +0 -89
  42. llg3d-2.0.1.dist-info/RECORD +0 -25
  43. llg3d-2.0.1.dist-info/entry_points.txt +0 -4
  44. {llg3d-2.0.1.dist-info → llg3d-3.0.0.dist-info}/licenses/AUTHORS +0 -0
  45. {llg3d-2.0.1.dist-info → llg3d-3.0.0.dist-info}/licenses/LICENSE +0 -0
  46. {llg3d-2.0.1.dist-info → llg3d-3.0.0.dist-info}/top_level.txt +0 -0
@@ -1,61 +0,0 @@
1
- """
2
- Plot 1D curves from several files.
3
-
4
- Usage:
5
-
6
- python plot_results.py file1.txt
7
- or
8
- python plot_results.py file1.txt file2.txt file3.txt
9
-
10
- """
11
-
12
- import argparse
13
- from matplotlib import pyplot as plt
14
- import numpy as np
15
-
16
-
17
- DEFAULT_OUTPUT_FILE = "results.png"
18
-
19
-
20
- def plot(*files: tuple[str], output_file: str = DEFAULT_OUTPUT_FILE):
21
- """
22
- Plot the results from the given files.
23
-
24
- Args:
25
- files (tuple[str]): Paths to the result files.
26
- output_file (str): Path to the output image file.
27
- """
28
- fig, ax = plt.subplots()
29
- for file in files:
30
- if not file.endswith(".txt"):
31
- raise ValueError(f"File {file} does not end with .txt")
32
- data = np.loadtxt(file)
33
- ax.plot(data[:, 0], data[:, 1], label=file)
34
-
35
- ax.set_xlabel("time")
36
- ax.set_ylabel(r"$<m_1>$")
37
- ax.legend()
38
- ax.set_title(r"Space average of $m_1$ according to time")
39
- fig.savefig(output_file)
40
- print(f"Written to {output_file}")
41
- plt.show()
42
-
43
-
44
- def main():
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.")
48
- parser.add_argument(
49
- "--output",
50
- "-o",
51
- type=str,
52
- default=DEFAULT_OUTPUT_FILE,
53
- help=f"Path to the output image file (default: {DEFAULT_OUTPUT_FILE}).",
54
- )
55
- args = parser.parse_args()
56
-
57
- plot(*args.files, output_file=args.output)
58
-
59
-
60
- if __name__ == "__main__":
61
- main()
llg3d/post/temperature.py DELETED
@@ -1,76 +0,0 @@
1
- #!/usr/bin/env python3
2
- """Plot the magnetization vs temperature and determine the Curie temperature."""
3
-
4
- import argparse
5
- from pathlib import Path
6
-
7
- import matplotlib.pyplot as plt
8
-
9
- from .process import MagData
10
-
11
-
12
- def plot_m_vs_T(m: MagData, show: bool):
13
- """
14
- Plots the data (T, <m>).
15
-
16
- Interpolates the values, calculates the Curie temperature, exports to PNG.
17
-
18
- Args:
19
- m: Magnetization data object
20
- show: display the graph in a graphical window
21
- """
22
- print(f"T_Curie = {m.T_Curie:.0f} K")
23
-
24
- fig, ax = plt.subplots()
25
- fig.suptitle("Average magnetization vs Temperature")
26
- params = m.run["params"]
27
- ax.set_title(
28
- params["element"]
29
- + rf", ${params['Jx']}\times{params['Jy']}\times{params['Jz']}$"
30
- rf" ($dx = ${params['dx']})",
31
- fontdict={"size": 10},
32
- )
33
- ax.plot(m.temperature, m.m1_mean, "o", label="computed")
34
- ax.plot(m.T, m.interp(m.T), label="interpolated (cubic)")
35
- ax.annotate(
36
- "$T_{{Curie}} = {:.0f} K$".format(m.T_Curie),
37
- xy=(m.T_Curie, m.interp(m.T_Curie)),
38
- xytext=(m.T_Curie + 20, m.interp(m.T_Curie) + 0.01),
39
- )
40
- ax.axvline(x=m.T_Curie, color="k")
41
- ax.set_xlabel("Temperature [K]")
42
- ax.set_ylabel("Magnetization")
43
- ax.legend()
44
-
45
- if show:
46
- plt.show()
47
-
48
- image_filename = m.parentpath / "m1_mean.png"
49
- fig.savefig(image_filename)
50
- print(f"Image saved in {image_filename}")
51
-
52
-
53
- def main():
54
- """Parses the command line to execute processing functions."""
55
- parser = argparse.ArgumentParser(description=__doc__)
56
- parser.add_argument("--job_dir", type=Path, help="Slurm main job directory")
57
- parser.add_argument(
58
- "--run_file", type=Path, default="run.json", help="Path to the run.json file"
59
- )
60
- parser.add_argument(
61
- "-s",
62
- "--show",
63
- action="store_true",
64
- default=False,
65
- help="Display the graph in a graphical window",
66
- )
67
- args = parser.parse_args()
68
- if args.job_dir:
69
- m = MagData(job_dir=args.job_dir)
70
- else:
71
- m = MagData(run_file=args.run_file)
72
- plot_m_vs_T(m, args.show)
73
-
74
-
75
- if __name__ == "__main__":
76
- main()
llg3d/simulation.py DELETED
@@ -1,95 +0,0 @@
1
- """
2
- Define the Simulation class.
3
-
4
- Example usage:
5
-
6
- >>> from llg3d.main import Simulation
7
- >>> from llg3d.parameters import parameters
8
- >>> run_parameters = {name: value["default"] for name, value in parameters.items()}
9
- >>> sim = Simulation(run_parameters)
10
- >>> sim.run()
11
- >>> sim.save()
12
-
13
- """
14
-
15
- import inspect
16
-
17
- from . import rank, size
18
- from .element import get_element_class
19
- from .parameters import Parameter
20
- from .output import write_json
21
-
22
-
23
- class Simulation:
24
- """
25
- Class to encapsulate the simulation logic.
26
-
27
- Args:
28
- params: Dictionary of simulation parameters.
29
- """
30
-
31
- json_file = "run.json" #: JSON file to store the results
32
-
33
- def __init__(self, params: dict[str, Parameter]):
34
- self.params: dict[str, Parameter] = params.copy() #: simulation parameters
35
- self.simulate: callable = self._get_simulate_function_from_name(
36
- self.params["solver"]
37
- ) #: simulation function imported from the solver module
38
- self.total_time: None | float = None #: total simulation time
39
- self.filenames: list[str] = [] #: list of output filenames
40
- self.m1_mean: None | float = None #: space and time average of m1
41
- self.params["np"] = size # Add a parameter for the number of processes
42
- # Reference the element class from the element string
43
- self.params["element_class"] = get_element_class(params["element"])
44
-
45
- def run(self):
46
- """Runs the simulation and store the results."""
47
- self.total_time, self.filenames, self.m1_mean = self.simulate(**self.params)
48
-
49
- def _get_simulate_function_from_name(self, name: str) -> callable:
50
- """
51
- Retrieves the simulation function for a given solver name.
52
-
53
- Args:
54
- name: Name of the solver
55
-
56
- Returns:
57
- callable: The simulation function
58
-
59
- Example:
60
- >>> simulate = self.get_simulate_function_from_name("mpi")
61
-
62
- Will return the `simulate` function from the `llg3d.solver.mpi` module.
63
- """
64
- module = __import__(f"llg3d.solver.{name}", fromlist=["simulate"])
65
- return inspect.getattr_static(module, "simulate")
66
-
67
- def save(self):
68
- """Saves the results of the simulation to a JSON file."""
69
- params = self.params.copy() # save the parameters
70
- del params["element_class"] # remove class object before serialization
71
- if rank == 0:
72
- results = {"total_time": self.total_time}
73
- # Export the integral of m1
74
- if len(self.filenames) > 0:
75
- results["integral_file"] = self.filenames[0]
76
- print(f"Integral of m1 in {self.filenames[0]}")
77
- # Export the x-profiles of m1, m2 and m3
78
- for i, filename in enumerate(self.filenames[1:]):
79
- results[f"xprofile_m{i}"] = filename
80
- print(f"x-profile of m{i} in {filename}")
81
-
82
- print(
83
- f"""\
84
- N iterations = {params["N"]}
85
- total_time [s] = {self.total_time:.03f}
86
- time/ite [s/iter] = {self.total_time / params["N"]:.03e}\
87
- """
88
- )
89
- # Export the mean of m1
90
- if params["N"] > params["start_averaging"]:
91
- print(f"m1_mean = {self.m1_mean:e}")
92
- results["m1_mean"] = float(self.m1_mean)
93
-
94
- write_json(self.json_file, {"params": params, "results": results})
95
- print(f"Summary in {self.json_file}")
llg3d/solver/__init__.py DELETED
@@ -1,45 +0,0 @@
1
- """
2
- Solver module for LLG3D.
3
-
4
- This module contains different solver implementations.
5
- """
6
-
7
- import importlib.util
8
-
9
-
10
- __all__ = ["numpy", "solver", "rank", "size", "comm", "status"]
11
-
12
- LIB_AVAILABLE: dict[str, bool] = {}
13
-
14
- # Check for other solver availability
15
- for lib in "opencl", "jax", "mpi4py":
16
- if importlib.util.find_spec(lib, package=__package__) is not None:
17
- LIB_AVAILABLE[lib] = True
18
- __all__.append(lib)
19
- else:
20
- LIB_AVAILABLE[lib] = False
21
-
22
-
23
- # MPI utilities
24
- if LIB_AVAILABLE["mpi4py"]:
25
- from mpi4py import MPI
26
-
27
- comm = MPI.COMM_WORLD
28
- rank = comm.Get_rank()
29
- size = comm.Get_size()
30
- status = MPI.Status()
31
- else:
32
- # MPI library is not available: use dummy values
33
- class DummyComm:
34
- pass
35
-
36
- comm = DummyComm()
37
- rank = 0
38
- size = 1
39
-
40
- class DummyStatus:
41
- pass
42
-
43
- status = DummyStatus()
44
-
45
- from . import numpy, solver # noqa: E402