nmag-python-3 0.0.3__tar.gz → 0.0.5__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.
Files changed (161) hide show
  1. {nmag_python_3-0.0.3/src/nmag_python_3.egg-info → nmag_python_3-0.0.5}/PKG-INFO +4 -4
  2. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/pyproject.toml +15 -3
  3. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmag/__init__.py +16 -0
  4. nmag_python_3-0.0.5/src/nmag/cli/__init__.py +1 -0
  5. nmag_python_3-0.0.5/src/nmag/cli/nmagpp.py +43 -0
  6. nmag_python_3-0.0.5/src/nmag/vtk_export.py +125 -0
  7. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5/src/nmag_python_3.egg-info}/PKG-INFO +4 -4
  8. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmag_python_3.egg-info/SOURCES.txt +7 -0
  9. nmag_python_3-0.0.5/src/nmag_python_3.egg-info/entry_points.txt +3 -0
  10. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmag_python_3.egg-info/requires.txt +3 -3
  11. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmesh/__init__.py +8 -0
  12. nmag_python_3-0.0.5/src/nmesh/cli/__init__.py +1 -0
  13. nmag_python_3-0.0.5/src/nmesh/cli/nmeshimport.py +39 -0
  14. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmesh/io/__init__.py +9 -0
  15. nmag_python_3-0.0.5/src/nmesh/io/netgen.py +122 -0
  16. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/LICENSE +0 -0
  17. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/README.md +0 -0
  18. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/setup.cfg +0 -0
  19. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/anisotropy/__init__.py +0 -0
  20. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/anisotropy/anisotropy.py +0 -0
  21. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/anisotropy/evaluation.py +0 -0
  22. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/anisotropy/model.py +0 -0
  23. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/anisotropy/predefined.py +0 -0
  24. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/anisotropy/py.typed +0 -0
  25. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/anisotropy/values.py +0 -0
  26. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/mag_material/__init__.py +0 -0
  27. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/mag_material/mag_material.py +0 -0
  28. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/mag_material/parameters.py +0 -0
  29. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/mag_material/py.typed +0 -0
  30. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmag/backends.py +0 -0
  31. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmag/checkpoint.py +0 -0
  32. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmag/config.py +0 -0
  33. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmag/demag/__init__.py +0 -0
  34. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmag/demag/bem_operator.py +0 -0
  35. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmag/demag/geometry.py +0 -0
  36. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmag/demag/lindholm.py +0 -0
  37. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmag/demag/lindholm_fast.py +0 -0
  38. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmag/demag/linear.py +0 -0
  39. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmag/dynamics/__init__.py +0 -0
  40. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmag/output.py +0 -0
  41. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmag/parallel.py +0 -0
  42. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmag/py.typed +0 -0
  43. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmag/resources.py +0 -0
  44. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmag/simulation/__init__.py +0 -0
  45. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmag/simulation/anisotropy/__init__.py +0 -0
  46. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmag/simulation/anisotropy/fields.py +0 -0
  47. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmag/simulation/anisotropy/materials.py +0 -0
  48. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmag/simulation/demag/__init__.py +0 -0
  49. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmag/simulation/demag/bem/__init__.py +0 -0
  50. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmag/simulation/demag/bem/diagnostics.py +0 -0
  51. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmag/simulation/demag/bem/dirichlet.py +0 -0
  52. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmag/simulation/demag/bem/hierarchical.py +0 -0
  53. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmag/simulation/demag/bem/operator.py +0 -0
  54. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmag/simulation/demag/fem/__init__.py +0 -0
  55. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmag/simulation/demag/fem/assembly.py +0 -0
  56. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmag/simulation/demag/fem/charges.py +0 -0
  57. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmag/simulation/demag/fem/geometry.py +0 -0
  58. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmag/simulation/demag/fields/__init__.py +0 -0
  59. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmag/simulation/demag/fields/auxiliary.py +0 -0
  60. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmag/simulation/demag/fields/probe.py +0 -0
  61. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmag/simulation/demag/fields/recovery.py +0 -0
  62. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmag/simulation/demag/solver.py +0 -0
  63. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmag/simulation/dynamics/__init__.py +0 -0
  64. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmag/simulation/dynamics/advance.py +0 -0
  65. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmag/simulation/dynamics/integrator.py +0 -0
  66. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmag/simulation/exchange/__init__.py +0 -0
  67. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmag/simulation/exchange/coefficients.py +0 -0
  68. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmag/simulation/exchange/fields.py +0 -0
  69. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmag/simulation/exchange/llg_rhs.py +0 -0
  70. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmag/simulation/fields/__init__.py +0 -0
  71. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmag/simulation/fields/arrays.py +0 -0
  72. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmag/simulation/fields/availability.py +0 -0
  73. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmag/simulation/fields/averages.py +0 -0
  74. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmag/simulation/fields/derived.py +0 -0
  75. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmag/simulation/fields/maxangle.py +0 -0
  76. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmag/simulation/fields/probes.py +0 -0
  77. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmag/simulation/implicit_dynamics.py +0 -0
  78. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmag/simulation/mesh/__init__.py +0 -0
  79. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmag/simulation/mesh/geometry.py +0 -0
  80. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmag/simulation/mesh/materials.py +0 -0
  81. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmag/simulation/mesh/probe.py +0 -0
  82. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmag/simulation/restart.py +0 -0
  83. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmag/simulation/support.py +0 -0
  84. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmag_python_3.egg-info/dependency_links.txt +0 -0
  85. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmag_python_3.egg-info/top_level.txt +0 -0
  86. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmesh/backend.py +0 -0
  87. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmesh/geometry/__init__.py +0 -0
  88. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmesh/geometry/boolean_operations.py +0 -0
  89. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmesh/geometry/primitives.py +0 -0
  90. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmesh/geometry/transform.py +0 -0
  91. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmesh/io/ascii.py +0 -0
  92. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmesh/io/legacy_nmesh_hdf5.py +0 -0
  93. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmesh/io/meshio_support.py +0 -0
  94. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmesh/mesh_generation.py +0 -0
  95. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmesh/mesh_io.py +0 -0
  96. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmesh/mesh_model.py +0 -0
  97. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmesh/mesh_utilities.py +0 -0
  98. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmesh/mesher/__init__.py +0 -0
  99. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmesh/mesher/driver.py +0 -0
  100. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmesh/mesher/meshing_defaults.py +0 -0
  101. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmesh/mesher/meshing_parameters.py +0 -0
  102. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmesh/mesher/parity.py +0 -0
  103. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmesh/mesher/parity_canonical.py +0 -0
  104. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmesh/mesher/parity_comparison.py +0 -0
  105. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmesh/mesher/parity_metrics.py +0 -0
  106. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmesh/mesher/periodic.py +0 -0
  107. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmesh/mesher/relaxation/__init__.py +0 -0
  108. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmesh/mesher/relaxation/_constants.py +0 -0
  109. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmesh/mesher/relaxation/_types.py +0 -0
  110. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmesh/mesher/relaxation/density.py +0 -0
  111. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmesh/mesher/relaxation/engine/__init__.py +0 -0
  112. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmesh/mesher/relaxation/engine/state.py +0 -0
  113. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmesh/mesher/relaxation/engine/steps.py +0 -0
  114. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmesh/mesher/relaxation/engine/topology.py +0 -0
  115. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmesh/mesher/relaxation/forces/__init__.py +0 -0
  116. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmesh/mesher/relaxation/forces/jit.py +0 -0
  117. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmesh/mesher/relaxation/forces/neighbors.py +0 -0
  118. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmesh/mesher/relaxation/forces/simplex.py +0 -0
  119. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmesh/mesher/relaxation/forces/summary.py +0 -0
  120. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmesh/mesher/relaxation/forces/types.py +0 -0
  121. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmesh/mesher/relaxation/geometry/__init__.py +0 -0
  122. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmesh/mesher/relaxation/geometry/builder.py +0 -0
  123. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmesh/mesher/relaxation/geometry/model.py +0 -0
  124. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmesh/mesher/relaxation/seeding/__init__.py +0 -0
  125. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmesh/mesher/relaxation/seeding/periodic.py +0 -0
  126. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmesh/mesher/relaxation/seeding/points.py +0 -0
  127. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmesh/mesher/relaxation/seeding/sampling.py +0 -0
  128. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmesh/mesher/relaxation/topology/__init__.py +0 -0
  129. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmesh/mesher/relaxation/topology/finalize.py +0 -0
  130. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmesh/mesher/relaxation/topology/recovery.py +0 -0
  131. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmesh/mesher/sectioned_config.py +0 -0
  132. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmesh/nmesh.py +0 -0
  133. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmesh/py.typed +0 -0
  134. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmesh/utils/__init__.py +0 -0
  135. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmesh/utils/array_list_utils.py +0 -0
  136. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmesh/utils/constants.py +0 -0
  137. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmesh/utils/timing_memory_utils.py +0 -0
  138. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/nmesh/utils/types.py +0 -0
  139. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/si/constants.py +0 -0
  140. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/si/physical.py +0 -0
  141. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/si/py.typed +0 -0
  142. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/simulation/__init__.py +0 -0
  143. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/simulation/clock.py +0 -0
  144. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/simulation/data_writer.py +0 -0
  145. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/simulation/data_writer_collection.py +0 -0
  146. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/simulation/hysteresis.py +0 -0
  147. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/simulation/hysteresis_runner.py +0 -0
  148. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/simulation/hysteresis_schedule.py +0 -0
  149. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/simulation/inference/__init__.py +0 -0
  150. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/simulation/inference/inference.py +0 -0
  151. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/simulation/py.typed +0 -0
  152. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/simulation/quantity.py +0 -0
  153. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/simulation/simulation_core.py +0 -0
  154. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/throttler/__init__.py +0 -0
  155. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/throttler/py.typed +0 -0
  156. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/throttler/throttler.py +0 -0
  157. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/when/__init__.py +0 -0
  158. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/when/py.typed +0 -0
  159. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/src/when/when.py +0 -0
  160. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/tests/test_docs_examples.py +0 -0
  161. {nmag_python_3-0.0.3 → nmag_python_3-0.0.5}/tests/test_packaging_hygiene.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nmag-python-3
3
- Version: 0.0.3
3
+ Version: 0.0.5
4
4
  Summary: Standalone Python 3 implementation of the Nmag micromagnetic simulation interface
5
5
  Author-email: TriMagnetix <info@trimagnetix.com>
6
6
  Classifier: Programming Language :: Python :: 3
@@ -9,9 +9,9 @@ Requires-Python: >=3.10
9
9
  Description-Content-Type: text/markdown
10
10
  License-File: LICENSE
11
11
  Requires-Dist: pint
12
- Requires-Dist: numpy
12
+ Requires-Dist: numpy<2.6,>=1.22
13
13
  Requires-Dist: scipy
14
- Requires-Dist: numba
14
+ Requires-Dist: numba>=0.67
15
15
  Requires-Dist: tabulate
16
16
  Requires-Dist: meshio
17
17
  Requires-Dist: h5py
@@ -25,7 +25,7 @@ Provides-Extra: docs
25
25
  Requires-Dist: mkdocs==1.6.1; extra == "docs"
26
26
  Requires-Dist: mkdocs-material==9.7.7; extra == "docs"
27
27
  Requires-Dist: mkdocstrings==1.0.6; extra == "docs"
28
- Requires-Dist: mkdocstrings-python==2.0.5; extra == "docs"
28
+ Requires-Dist: mkdocstrings-python==2.0.8; extra == "docs"
29
29
  Provides-Extra: dev
30
30
  Requires-Dist: maturin<2,>=1.14; extra == "dev"
31
31
  Requires-Dist: h5py-stubs<0.2,>=0.1.2; extra == "dev"
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "nmag-python-3"
7
- version = "0.0.3"
7
+ version = "0.0.5"
8
8
  authors = [{ name = "TriMagnetix", email = "info@trimagnetix.com" }]
9
9
  description = "Standalone Python 3 implementation of the Nmag micromagnetic simulation interface"
10
10
  readme = "README.md"
@@ -12,7 +12,19 @@ requires-python = ">=3.10"
12
12
  classifiers = [
13
13
  "Programming Language :: Python :: 3",
14
14
  "Operating System :: OS Independent" ]
15
- dependencies = ["pint", "numpy", "scipy", "numba", "tabulate", "meshio", "h5py"]
15
+ dependencies = [
16
+ "pint",
17
+ "numpy>=1.22,<2.6",
18
+ "scipy",
19
+ "numba>=0.67",
20
+ "tabulate",
21
+ "meshio",
22
+ "h5py",
23
+ ]
24
+
25
+ [project.scripts]
26
+ nmeshimport = "nmesh.cli.nmeshimport:main"
27
+ nmagpp = "nmag.cli.nmagpp:main"
16
28
 
17
29
  [project.optional-dependencies]
18
30
  test = ["pytest", "pytest-cov", "pytest-watch"]
@@ -21,7 +33,7 @@ docs = [
21
33
  "mkdocs==1.6.1",
22
34
  "mkdocs-material==9.7.7",
23
35
  "mkdocstrings==1.0.6",
24
- "mkdocstrings-python==2.0.5",
36
+ "mkdocstrings-python==2.0.8",
25
37
  ]
26
38
  dev = [
27
39
  "maturin>=1.14,<2",
@@ -1,5 +1,7 @@
1
1
  """Public Python 3 entrypoint for the nmag rewrite."""
2
2
 
3
+ from typing import Any
4
+
3
5
  from anisotropy import (
4
6
  PredefinedAnisotropy,
5
7
  cubic_anisotropy,
@@ -15,6 +17,8 @@ from .dynamics import IntegratorConfig, IntegratorStats
15
17
  from .parallel import ParallelRuntimeInfo, parallel_runtime_info
16
18
  from .simulation import Simulation
17
19
 
20
+ _OUTPUT_EXPORTS = {"export_vtk", "resolve_snapshot"}
21
+
18
22
  __all__ = [
19
23
  "MagMaterial",
20
24
  "NmagConfig",
@@ -33,4 +37,16 @@ __all__ = [
33
37
  "parallel_runtime_info",
34
38
  "uniaxial_anisotropy",
35
39
  "want_anisotropy",
40
+ "export_vtk",
41
+ "resolve_snapshot",
36
42
  ]
43
+
44
+
45
+ def __getattr__(name: str) -> Any:
46
+ if name in _OUTPUT_EXPORTS:
47
+ from . import vtk_export
48
+
49
+ value = getattr(vtk_export, name)
50
+ globals()[name] = value
51
+ return value
52
+ raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
@@ -0,0 +1 @@
1
+ """Command-line entry points for Nmag utilities."""
@@ -0,0 +1,43 @@
1
+ """Export modern Nmag snapshots to VTK-compatible files."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import argparse
6
+ from collections.abc import Sequence
7
+ from pathlib import Path
8
+
9
+ import h5py
10
+
11
+ from ..vtk_export import export_vtk, resolve_snapshot
12
+
13
+
14
+ def _parser() -> argparse.ArgumentParser:
15
+ parser = argparse.ArgumentParser(
16
+ prog="nmagpp",
17
+ description="Export a modern Nmag HDF5 snapshot to VTK.",
18
+ )
19
+ parser.add_argument("--vtk", dest="output", required=True, type=Path)
20
+ parser.add_argument("input", type=Path, help="snapshot path or simulation base name")
21
+ parser.add_argument("--mesh", type=Path, help="mesh file supplying cell topology")
22
+ parser.add_argument("--field", action="append", dest="fields", metavar="NAME")
23
+ parser.add_argument("--all-fields", action="store_true")
24
+ return parser
25
+
26
+
27
+ def main(argv: Sequence[str] | None = None) -> int:
28
+ args = _parser().parse_args(argv)
29
+ snapshot = resolve_snapshot(args.input)
30
+ if args.all_fields:
31
+ with h5py.File(str(snapshot), "r") as handle:
32
+ group = handle.get("fields")
33
+ if not isinstance(group, h5py.Group):
34
+ raise ValueError("Snapshot is missing the /fields group.")
35
+ fields = tuple(str(name) for name in group.keys())
36
+ else:
37
+ fields = tuple(args.fields or ("m",))
38
+ export_vtk(snapshot, args.output, mesh_path=args.mesh, fields=fields)
39
+ return 0
40
+
41
+
42
+ if __name__ == "__main__":
43
+ raise SystemExit(main())
@@ -0,0 +1,125 @@
1
+ """Export modern Nmag spatial snapshots to VTK-compatible mesh files."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from collections.abc import Iterable
6
+ from pathlib import Path
7
+
8
+ import h5py
9
+ import meshio
10
+ import numpy as np
11
+ from numpy.typing import ArrayLike
12
+
13
+ import nmesh
14
+
15
+
16
+ def _dataset_names(handle: h5py.File) -> list[str]:
17
+ fields = handle.get("fields")
18
+ if not isinstance(fields, h5py.Group):
19
+ raise ValueError("Snapshot is missing the /fields group.")
20
+ return sorted(str(name) for name in fields.keys())
21
+
22
+
23
+ def _read_points(handle: h5py.File) -> np.ndarray:
24
+ try:
25
+ points = np.asarray(handle["mesh/points"], dtype=float)
26
+ except KeyError as exc:
27
+ raise ValueError("Snapshot is missing /mesh/points.") from exc
28
+ if points.ndim != 2 or points.shape[1] != 3:
29
+ raise ValueError(f"Snapshot points must have shape (N, 3), got {points.shape}.")
30
+ return points
31
+
32
+
33
+ def _read_topology(
34
+ handle: h5py.File,
35
+ mesh_path: str | Path | None,
36
+ ) -> tuple[np.ndarray, np.ndarray | None, np.ndarray]:
37
+ if "mesh/simplices" in handle:
38
+ simplices = np.asarray(handle["mesh/simplices"], dtype=np.int64)
39
+ regions = (
40
+ np.asarray(handle["mesh/simplicesregions"], dtype=np.int64)
41
+ if "mesh/simplicesregions" in handle
42
+ else None
43
+ )
44
+ elif mesh_path is not None:
45
+ source_mesh = nmesh.load(mesh_path)
46
+ simplices = np.asarray(source_mesh.simplices, dtype=np.int64)
47
+ regions = np.asarray(source_mesh.regions, dtype=np.int64)
48
+ else:
49
+ raise ValueError(
50
+ "Snapshot contains point coordinates but no cell topology; provide --mesh."
51
+ )
52
+
53
+ if simplices.ndim != 2 or simplices.shape[1] != 4:
54
+ raise ValueError(f"VTK export requires tetrahedral cells, got {simplices.shape}.")
55
+ if regions is not None and len(regions) != len(simplices):
56
+ raise ValueError("Mesh region data does not match the number of cells.")
57
+ return simplices, regions, _read_points(handle)
58
+
59
+
60
+ def export_vtk(
61
+ snapshot_path: str | Path,
62
+ output_path: str | Path,
63
+ *,
64
+ mesh_path: str | Path | None = None,
65
+ fields: Iterable[str] = ("m",),
66
+ ) -> Path:
67
+ """Export selected point fields from a modern Nmag HDF5 snapshot."""
68
+
69
+ snapshot = Path(snapshot_path)
70
+ output = Path(output_path)
71
+ selected_fields = tuple(dict.fromkeys(fields))
72
+ if not selected_fields:
73
+ raise ValueError("At least one point field must be selected.")
74
+
75
+ with h5py.File(str(snapshot), "r") as handle:
76
+ points = _read_points(handle)
77
+ simplices, regions, _ = _read_topology(handle, mesh_path)
78
+ if np.any(simplices < 0) or np.any(simplices >= len(points)):
79
+ raise ValueError("Mesh cell indices are outside the snapshot point range.")
80
+
81
+ point_data: dict[str, ArrayLike] = {}
82
+ field_group = handle.get("fields")
83
+ if not isinstance(field_group, h5py.Group):
84
+ raise ValueError("Snapshot is missing the /fields group.")
85
+ for field_name in selected_fields:
86
+ if field_name not in field_group:
87
+ available = ", ".join(_dataset_names(handle))
88
+ raise KeyError(f"Field {field_name!r} is not present; available fields: {available}")
89
+ values = np.asarray(field_group[field_name])
90
+ if values.ndim not in (1, 2) or values.shape[0] != len(points):
91
+ raise ValueError(
92
+ f"Field {field_name!r} must have one value per point, got {values.shape}."
93
+ )
94
+ if values.ndim == 2 and values.shape[1] not in (1, 3):
95
+ raise ValueError(
96
+ f"Field {field_name!r} must be scalar or three-component vector, "
97
+ f"got {values.shape}."
98
+ )
99
+ point_data[field_name] = np.asarray(values, dtype=float)
100
+
101
+ cell_data: dict[str, list[ArrayLike]] = {}
102
+ if regions is not None:
103
+ cell_data["region"] = [regions]
104
+ mesh = meshio.Mesh(
105
+ points=points,
106
+ cells=[("tetra", simplices)],
107
+ point_data=point_data,
108
+ cell_data=cell_data or None,
109
+ )
110
+ output.parent.mkdir(parents=True, exist_ok=True)
111
+ meshio.write(output, mesh)
112
+ return output
113
+
114
+
115
+ def resolve_snapshot(path: str | Path) -> Path:
116
+ """Resolve a snapshot path or a simulation base name."""
117
+
118
+ candidate = Path(path)
119
+ if candidate.is_file():
120
+ return candidate
121
+ if candidate.suffix == "":
122
+ suffixed = candidate.with_name(f"{candidate.name}_dat.h5")
123
+ if suffixed.is_file():
124
+ return suffixed
125
+ raise FileNotFoundError(f"Nmag snapshot does not exist: {candidate}")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nmag-python-3
3
- Version: 0.0.3
3
+ Version: 0.0.5
4
4
  Summary: Standalone Python 3 implementation of the Nmag micromagnetic simulation interface
5
5
  Author-email: TriMagnetix <info@trimagnetix.com>
6
6
  Classifier: Programming Language :: Python :: 3
@@ -9,9 +9,9 @@ Requires-Python: >=3.10
9
9
  Description-Content-Type: text/markdown
10
10
  License-File: LICENSE
11
11
  Requires-Dist: pint
12
- Requires-Dist: numpy
12
+ Requires-Dist: numpy<2.6,>=1.22
13
13
  Requires-Dist: scipy
14
- Requires-Dist: numba
14
+ Requires-Dist: numba>=0.67
15
15
  Requires-Dist: tabulate
16
16
  Requires-Dist: meshio
17
17
  Requires-Dist: h5py
@@ -25,7 +25,7 @@ Provides-Extra: docs
25
25
  Requires-Dist: mkdocs==1.6.1; extra == "docs"
26
26
  Requires-Dist: mkdocs-material==9.7.7; extra == "docs"
27
27
  Requires-Dist: mkdocstrings==1.0.6; extra == "docs"
28
- Requires-Dist: mkdocstrings-python==2.0.5; extra == "docs"
28
+ Requires-Dist: mkdocstrings-python==2.0.8; extra == "docs"
29
29
  Provides-Extra: dev
30
30
  Requires-Dist: maturin<2,>=1.14; extra == "dev"
31
31
  Requires-Dist: h5py-stubs<0.2,>=0.1.2; extra == "dev"
@@ -20,6 +20,9 @@ src/nmag/output.py
20
20
  src/nmag/parallel.py
21
21
  src/nmag/py.typed
22
22
  src/nmag/resources.py
23
+ src/nmag/vtk_export.py
24
+ src/nmag/cli/__init__.py
25
+ src/nmag/cli/nmagpp.py
23
26
  src/nmag/demag/__init__.py
24
27
  src/nmag/demag/bem_operator.py
25
28
  src/nmag/demag/geometry.py
@@ -70,6 +73,7 @@ src/nmag/simulation/mesh/probe.py
70
73
  src/nmag_python_3.egg-info/PKG-INFO
71
74
  src/nmag_python_3.egg-info/SOURCES.txt
72
75
  src/nmag_python_3.egg-info/dependency_links.txt
76
+ src/nmag_python_3.egg-info/entry_points.txt
73
77
  src/nmag_python_3.egg-info/requires.txt
74
78
  src/nmag_python_3.egg-info/top_level.txt
75
79
  src/nmesh/__init__.py
@@ -80,6 +84,8 @@ src/nmesh/mesh_model.py
80
84
  src/nmesh/mesh_utilities.py
81
85
  src/nmesh/nmesh.py
82
86
  src/nmesh/py.typed
87
+ src/nmesh/cli/__init__.py
88
+ src/nmesh/cli/nmeshimport.py
83
89
  src/nmesh/geometry/__init__.py
84
90
  src/nmesh/geometry/boolean_operations.py
85
91
  src/nmesh/geometry/primitives.py
@@ -88,6 +94,7 @@ src/nmesh/io/__init__.py
88
94
  src/nmesh/io/ascii.py
89
95
  src/nmesh/io/legacy_nmesh_hdf5.py
90
96
  src/nmesh/io/meshio_support.py
97
+ src/nmesh/io/netgen.py
91
98
  src/nmesh/mesher/__init__.py
92
99
  src/nmesh/mesher/driver.py
93
100
  src/nmesh/mesher/meshing_defaults.py
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ nmagpp = nmag.cli.nmagpp:main
3
+ nmeshimport = nmesh.cli.nmeshimport:main
@@ -1,7 +1,7 @@
1
1
  pint
2
- numpy
2
+ numpy<2.6,>=1.22
3
3
  scipy
4
- numba
4
+ numba>=0.67
5
5
  tabulate
6
6
  meshio
7
7
  h5py
@@ -19,7 +19,7 @@ ruff<1,>=0.12
19
19
  mkdocs==1.6.1
20
20
  mkdocs-material==9.7.7
21
21
  mkdocstrings==1.0.6
22
- mkdocstrings-python==2.0.5
22
+ mkdocstrings-python==2.0.8
23
23
 
24
24
  [rust]
25
25
  maturin<2,>=1.14
@@ -52,6 +52,7 @@ _MESHER_EXPORTS = {
52
52
  "do_every_n_steps_driver",
53
53
  "make_mg_gendriver",
54
54
  }
55
+ _NETGEN_EXPORTS = {"read_netgen_neutral"}
55
56
 
56
57
  __all__ = [
57
58
  "Mesh",
@@ -96,10 +97,17 @@ __all__ = [
96
97
  "inverse_shift",
97
98
  "make_mg_gendriver",
98
99
  "union",
100
+ "read_netgen_neutral",
99
101
  ]
100
102
 
101
103
 
102
104
  def __getattr__(name: str) -> Any:
105
+ if name in _NETGEN_EXPORTS:
106
+ from .io.netgen import read_netgen_neutral
107
+
108
+ globals()[name] = read_netgen_neutral
109
+ return read_netgen_neutral
110
+
103
111
  if name in _GEOMETRY_EXPORTS:
104
112
  from . import geometry
105
113
 
@@ -0,0 +1 @@
1
+ """Command-line entry points for mesh utilities."""
@@ -0,0 +1,39 @@
1
+ """Convert Netgen Neutral meshes to legacy Nmesh HDF5."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import argparse
6
+ from collections.abc import Sequence
7
+ from pathlib import Path
8
+
9
+ from ..io import save_raw_mesh_as_legacy_nmesh_hdf5
10
+ from ..io.netgen import read_netgen_neutral
11
+
12
+
13
+ def _parser() -> argparse.ArgumentParser:
14
+ parser = argparse.ArgumentParser(
15
+ prog="nmeshimport",
16
+ description="Convert a Netgen Neutral tetrahedral mesh to Nmesh HDF5.",
17
+ )
18
+ parser.add_argument(
19
+ "--netgen",
20
+ action="store_true",
21
+ help="read Netgen Neutral input (the supported conversion mode)",
22
+ )
23
+ parser.add_argument("input", type=Path)
24
+ parser.add_argument("output", type=Path)
25
+ return parser
26
+
27
+
28
+ def main(argv: Sequence[str] | None = None) -> int:
29
+ args = _parser().parse_args(argv)
30
+ if not args.netgen:
31
+ raise SystemExit("nmeshimport currently requires --netgen.")
32
+ mesh = read_netgen_neutral(args.input)
33
+ args.output.parent.mkdir(parents=True, exist_ok=True)
34
+ save_raw_mesh_as_legacy_nmesh_hdf5(args.output, mesh)
35
+ return 0
36
+
37
+
38
+ if __name__ == "__main__":
39
+ raise SystemExit(main())
@@ -23,12 +23,15 @@ _MESHIO_EXPORTS = {
23
23
  "save_raw_mesh_with_meshio",
24
24
  }
25
25
 
26
+ _NETGEN_EXPORTS = {"read_netgen_neutral"}
27
+
26
28
  __all__ = [
27
29
  "is_legacy_nmesh_hdf5",
28
30
  "load_raw_mesh_from_legacy_nmesh_hdf5",
29
31
  "load_raw_mesh_with_meshio",
30
32
  "save_raw_mesh_as_legacy_nmesh_hdf5",
31
33
  "save_raw_mesh_with_meshio",
34
+ "read_netgen_neutral",
32
35
  ]
33
36
 
34
37
 
@@ -47,4 +50,10 @@ def __getattr__(name: str) -> Any:
47
50
  globals()[name] = value
48
51
  return value
49
52
 
53
+ if name in _NETGEN_EXPORTS:
54
+ from .netgen import read_netgen_neutral
55
+
56
+ globals()[name] = read_netgen_neutral
57
+ return read_netgen_neutral
58
+
50
59
  raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
@@ -0,0 +1,122 @@
1
+ """Readers for Netgen Neutral tetrahedral meshes."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import gzip
6
+ from pathlib import Path
7
+ from typing import TextIO
8
+
9
+ from ..backend import RawMesh
10
+
11
+
12
+ def _open_text(path: Path) -> TextIO:
13
+ if path.suffix == ".gz":
14
+ return gzip.open(path, "rt", encoding="utf-8")
15
+ return path.open("r", encoding="utf-8")
16
+
17
+
18
+ class _LineReader:
19
+ def __init__(self, stream: TextIO, path: Path) -> None:
20
+ self.stream = stream
21
+ self.path = path
22
+ self.line_number = 0
23
+
24
+ def next(self, description: str) -> tuple[int, str]:
25
+ for line in self.stream:
26
+ self.line_number += 1
27
+ stripped = line.strip()
28
+ if stripped:
29
+ return self.line_number, stripped
30
+ raise ValueError(f"{self.path} ended while reading {description}.")
31
+
32
+
33
+ def _parse_count(line: str, path: Path, line_number: int, description: str) -> int:
34
+ try:
35
+ count = int(line)
36
+ except ValueError as exc:
37
+ raise ValueError(
38
+ f"{path}:{line_number} has an invalid {description} count: {line!r}."
39
+ ) from exc
40
+ if count < 0:
41
+ raise ValueError(f"{path}:{line_number} has a negative {description} count.")
42
+ return count
43
+
44
+
45
+ def read_netgen_neutral(path: str | Path) -> RawMesh:
46
+ """Read a Netgen Neutral tetrahedral mesh into a :class:`RawMesh`.
47
+
48
+ Netgen Neutral element indices are one-based. They are converted to the
49
+ zero-based indexing used by ``nmesh`` while region IDs are preserved.
50
+ Gzip-compressed files are accepted when the filename ends in ``.gz``.
51
+ """
52
+
53
+ mesh_path = Path(path)
54
+ if not mesh_path.is_file():
55
+ raise FileNotFoundError(f"Netgen mesh does not exist: {mesh_path}")
56
+
57
+ try:
58
+ with _open_text(mesh_path) as stream:
59
+ reader = _LineReader(stream, mesh_path)
60
+ point_count_line, point_count_text = reader.next("point")
61
+ point_count = _parse_count(
62
+ point_count_text, mesh_path, point_count_line, "point"
63
+ )
64
+ if point_count == 0:
65
+ raise ValueError(f"{mesh_path} contains no points.")
66
+
67
+ points: list[list[float]] = []
68
+ for index in range(point_count):
69
+ line_number, line = reader.next(f"point {index + 1}")
70
+ values = line.split()
71
+ if len(values) != 3:
72
+ raise ValueError(
73
+ f"{mesh_path}:{line_number} point {index + 1} must have three coordinates."
74
+ )
75
+ try:
76
+ points.append([float(value) for value in values])
77
+ except ValueError as exc:
78
+ raise ValueError(
79
+ f"{mesh_path}:{line_number} contains a non-numeric point coordinate."
80
+ ) from exc
81
+
82
+ simplex_count_line, simplex_count_text = reader.next("tetrahedron")
83
+ simplex_count = _parse_count(
84
+ simplex_count_text,
85
+ mesh_path,
86
+ simplex_count_line,
87
+ "tetrahedron",
88
+ )
89
+ if simplex_count == 0:
90
+ raise ValueError(f"{mesh_path} contains no tetrahedra.")
91
+
92
+ simplices: list[list[int]] = []
93
+ regions: list[int] = []
94
+ for index in range(simplex_count):
95
+ line_number, line = reader.next(f"tetrahedron {index + 1}")
96
+ values = line.split()
97
+ if len(values) != 5:
98
+ raise ValueError(
99
+ f"{mesh_path}:{line_number} tetrahedron {index + 1} must contain "
100
+ "one region ID and four point indices."
101
+ )
102
+ try:
103
+ region = int(values[0])
104
+ indices = [int(value) - 1 for value in values[1:]]
105
+ except ValueError as exc:
106
+ raise ValueError(
107
+ f"{mesh_path}:{line_number} contains a non-integer tetrahedron value."
108
+ ) from exc
109
+ if region <= 0:
110
+ raise ValueError(
111
+ f"{mesh_path}:{line_number} has invalid region ID {region}; expected > 0."
112
+ )
113
+ if any(point < 0 or point >= point_count for point in indices):
114
+ raise ValueError(
115
+ f"{mesh_path}:{line_number} contains a point index outside 1..{point_count}."
116
+ )
117
+ simplices.append(indices)
118
+ regions.append(region)
119
+ except (OSError, UnicodeError) as exc:
120
+ raise ValueError(f"Unable to read Netgen mesh {mesh_path}: {exc}") from exc
121
+
122
+ return RawMesh(points=points, simplices=simplices, regions=regions, dim=3)
File without changes
File without changes
File without changes