From 7878cfda09f2f4a495bffceaa8826f94e53cb58e Mon Sep 17 00:00:00 2001 From: Gideon Date: Fri, 11 Jan 2019 17:25:23 +0100 Subject: [PATCH 1/6] Docs: added autogeneration of Python API docs. --- conf.py | 46 ++++++++++++++++++++++++++++++++++++++++++- docs/index.rst | 11 +++++++++++ docs/requirements.txt | 4 +++- 3 files changed, 59 insertions(+), 2 deletions(-) diff --git a/conf.py b/conf.py index 500996371..7fe17148e 100644 --- a/conf.py +++ b/conf.py @@ -19,6 +19,9 @@ # import os # import sys # sys.path.insert(0, os.path.abspath('.')) +import sys, os +sys.path.insert( 0, os.path.join( os.path.dirname( __file__ ), "core", "python", "spirit" ) ) +sys.path.insert( 0, os.path.join( os.path.dirname( __file__ ), "core", "python" ) ) # At top on conf.py (with other import statements) @@ -44,7 +47,7 @@ # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = ['sphinx_markdown_tables', 'sphinx.ext.intersphinx', - 'sphinx.ext.coverage'] + 'sphinx.ext.coverage', 'sphinx.ext.autodoc'] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] @@ -210,3 +213,44 @@ # Example configuration for intersphinx: refer to the Python standard library. intersphinx_mapping = {'https://docs.python.org/': None} + + + +def run_apidoc(_): + """Runs sphinx-apidoc when building the documentation. + Needs to be done in conf.py in order to include the APIdoc in the + build on readthedocs. + See also https://github.com/rtfd/readthedocs.org/issues/1139 + """ + source_dir = os.path.abspath(os.path.dirname(__file__)) + apidoc_dir = os.path.join(source_dir, 'docs', 'pyapidoc') + package_dir = os.path.join(source_dir, 'core', 'python', 'spirit') + + import subprocess + cmd_path = 'sphinx-apidoc' + if hasattr(sys, 'real_prefix'): # Check to see if we are in a virtualenv + # If we are, assemble the path manually + cmd_path = os.path.abspath(os.path.join(sys.prefix, 'bin', 'sphinx-apidoc')) + + options = [ + '-o', apidoc_dir, package_dir, + '--force', + '--no-headings', + '--module-first', + '--no-toc', + '--maxdepth', '4', + ] + + builddir = os.path.join(source_dir, 'build') + if not os.path.exists(builddir): + os.mkdir(builddir) + subprocess.check_call(['cmake', '..', '-DSPIRIT_BUILD_FOR_CXX=OFF'], cwd=builddir) + subprocess.check_call(['make'], cwd=builddir) + + # See https://stackoverflow.com/a/30144019 + env = os.environ.copy() + env["SPHINX_APIDOC_OPTIONS"] = 'members,special-members,private-members,undoc-members,show-inheritance' + subprocess.check_call([cmd_path] + options, env=env) + +def setup(app): + app.connect('builder-inited', run_apidoc) \ No newline at end of file diff --git a/docs/index.rst b/docs/index.rst index 7e1333726..87642b260 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -30,6 +30,17 @@ Spirit - Spin Simulation Framework C API Reference <../core/docs/API> Python API Reference <../core/docs/API_Python> + +.. c:autodoc:: core/include/Spirit/Chain.h + + +.. toctree:: + :maxdepth: 1 + :caption: Python API Reference + + pyapidoc/spirit + pyapidoc/spirit.parameters + .. toctree:: :maxdepth: 1 :caption: Further Information: diff --git a/docs/requirements.txt b/docs/requirements.txt index fe94e86f3..15b3b6864 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,2 +1,4 @@ pandoc -sphinx-markdown-tables \ No newline at end of file +sphinx-markdown-tables +cmake +gcc7 \ No newline at end of file From 39be2d2f961adcd1e0252887a3ac280385bc437a Mon Sep 17 00:00:00 2001 From: Gideon Date: Fri, 11 Jan 2019 17:28:14 +0100 Subject: [PATCH 2/6] Docs: added docstrings to Python API, improved autodocs. --- conf.py | 3 +- core/CMake/__init__.py.in | 5 ++ core/python/spirit/chain.py | 8 +++ core/python/spirit/configuration.py | 7 +++ core/python/spirit/constants.py | 23 ++++--- core/python/spirit/geometry.py | 8 +++ core/python/spirit/hamiltonian.py | 7 +++ core/python/spirit/io.py | 74 ++++++++++++++++++++--- core/python/spirit/log.py | 5 ++ core/python/spirit/parameters/__init__.py | 7 +++ core/python/spirit/quantities.py | 5 ++ core/python/spirit/simulation.py | 5 ++ core/python/spirit/state.py | 5 ++ core/python/spirit/system.py | 5 ++ core/python/spirit/transition.py | 5 ++ docs/index.rst | 63 ++++++++++--------- docs/requirements.txt | 1 + 17 files changed, 187 insertions(+), 49 deletions(-) diff --git a/conf.py b/conf.py index 7fe17148e..58ec8f959 100644 --- a/conf.py +++ b/conf.py @@ -109,7 +109,7 @@ # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This patterns also effect to html_static_path and html_extra_path -exclude_patterns = ['.github', '_build', 'Thumbs.db', '.DS_Store'] +exclude_patterns = ['.github', '_build', 'pyapidoc/spirit.rst', 'Thumbs.db', '.DS_Store'] # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' @@ -237,6 +237,7 @@ def run_apidoc(_): '--force', '--no-headings', '--module-first', + '--separate', '--no-toc', '--maxdepth', '4', ] diff --git a/core/CMake/__init__.py.in b/core/CMake/__init__.py.in index 8c77fec44..59771a0c0 100644 --- a/core/CMake/__init__.py.in +++ b/core/CMake/__init__.py.in @@ -1,3 +1,8 @@ +""" +Spirit +================================================== +""" + __version__ = "${META_VERSION}" __revision__ = "${META_VERSION_REVISION}" __title__ = "${META_PROJECT_NAME}" diff --git a/core/python/spirit/chain.py b/core/python/spirit/chain.py index 515b39d21..7984a081d 100644 --- a/core/python/spirit/chain.py +++ b/core/python/spirit/chain.py @@ -1,3 +1,11 @@ +""" +Chain +-------------------- + +Manipulate the chain of spin systems (images), e.g. add, remove or change active image. +Get information, such as number of images or energies and reaction coordinates. +""" + import spirit.spiritlib as spiritlib import spirit.parameters as parameters import spirit.system as system diff --git a/core/python/spirit/configuration.py b/core/python/spirit/configuration.py index 469f3d81e..326926786 100644 --- a/core/python/spirit/configuration.py +++ b/core/python/spirit/configuration.py @@ -1,3 +1,10 @@ +""" +Configuration +-------------------- + +Set various spin configurations, such as homogeneous domains, spirals or skyrmions. +""" + import spirit.spiritlib as spiritlib import ctypes diff --git a/core/python/spirit/constants.py b/core/python/spirit/constants.py index 2aeaaffb6..1862e9a7b 100644 --- a/core/python/spirit/constants.py +++ b/core/python/spirit/constants.py @@ -1,3 +1,8 @@ +""" +Constants +-------------------- +""" + import spirit.spiritlib as spiritlib import ctypes @@ -6,50 +11,50 @@ # Load Library _spirit = spiritlib.load_spirit_library() -# The Bohr Magneton [meV / T] _mu_B = _spirit.Constants_mu_B _mu_B.argtypes = None _mu_B.restype = scalar mu_B = _mu_B() +"""The Bohr Magneton [meV / T]""" -# The vacuum permeability [T^2 m^3 / meV] _mu_0 = _spirit.Constants_mu_0 _mu_0.argtypes = None _mu_0.restype = scalar mu_0 = _mu_0() +"""The vacuum permeability [T^2 m^3 / meV]""" -# The Boltzmann constant [meV / K] _k_B = _spirit.Constants_k_B _k_B.argtypes = None _k_B.restype = scalar k_B = _k_B() +"""The Boltzmann constant [meV / K]""" -# Planck's constant [meV*ps / rad] _hbar = _spirit.Constants_hbar _hbar.argtypes = None _hbar.restype = scalar hbar = _hbar() +"""Planck's constant [meV*ps / rad]""" -# Millirydberg [mRy / meV] _mRy = _spirit.Constants_mRy _mRy.argtypes = None _mRy.restype = scalar mRy = _mRy() +"""Millirydberg [mRy / meV]""" -# Gyromagnetic ratio of electron [rad / (ps*T)] _gamma = _spirit.Constants_gamma _gamma.argtypes = None _gamma.restype = scalar gamma = _gamma() +"""Gyromagnetic ratio of electron [rad / (ps*T)]""" -# Electron g-factor [unitless] _g_e = _spirit.Constants_g_e _g_e.argtypes = None _g_e.restype = scalar g_e = _g_e() +"""Electron g-factor [unitless]""" -# Pi [rad] _Pi = _spirit.Constants_Pi _Pi.argtypes = None _Pi.restype = scalar -pi = _Pi() \ No newline at end of file +pi = _Pi() +"""Pi [rad]""" \ No newline at end of file diff --git a/core/python/spirit/geometry.py b/core/python/spirit/geometry.py index 90c2fef85..ef43a9a95 100644 --- a/core/python/spirit/geometry.py +++ b/core/python/spirit/geometry.py @@ -1,3 +1,11 @@ +""" +Geometry +-------------------- + +Change or get info on the current geometrical configuration, e.g. +number of cells in the three crystal translation directions. +""" + import spirit.spiritlib as spiritlib import ctypes diff --git a/core/python/spirit/hamiltonian.py b/core/python/spirit/hamiltonian.py index 44c2fd4c0..28acdfe8c 100644 --- a/core/python/spirit/hamiltonian.py +++ b/core/python/spirit/hamiltonian.py @@ -1,3 +1,10 @@ +""" +Hamiltonian +-------------------- + +Set the parameters of the Heisenberg Hamiltonian, such as external field or exchange interaction. +""" + import spirit.spiritlib as spiritlib import ctypes diff --git a/core/python/spirit/io.py b/core/python/spirit/io.py index 7afe78431..8c51c20f1 100644 --- a/core/python/spirit/io.py +++ b/core/python/spirit/io.py @@ -1,3 +1,10 @@ +""" +I/O +-------------------- + +Read and write spin configurations, chains or eigenmodes. +""" + import spirit.spiritlib as spiritlib import ctypes @@ -6,16 +13,32 @@ ### Output file formats FILEFORMAT_OVF_BIN = 0 +"""OVF binary format corresponding to the precision with which the code was compiled""" + FILEFORMAT_OVF_BIN4 = 1 +"""OVF binary format with precision 4""" + FILEFORMAT_OVF_BIN8 = 2 +"""OVF binary format with precision 8""" + FILEFORMAT_OVF_TEXT = 3 +"""OVF text format""" + FILEFORMAT_OVF_CSV = 4 +"""OVF text format with comma-separated columns""" ### Get the number of images in a file _N_Images_In_File = _spirit.IO_N_Images_In_File _N_Images_In_File.argtypes = [ctypes.c_void_p, ctypes.c_char_p, ctypes.c_int, ctypes.c_int] _N_Images_In_File.restype = ctypes.c_int +"""test docstring above n_images_in_file""" def n_images_in_file(p_state, filename, idx_image_inchain=-1, idx_chain=-1): + """Returns the number of segments or images in a given file. + + Arguments: + p_state -- state pointer + filename -- the name of the file to check + """ return int(_N_Images_In_File(ctypes.c_void_p(p_state), ctypes.c_char_p(filename.encode('utf-8')), ctypes.c_int(idx_image_inchain), ctypes.c_int(idx_chain))) @@ -24,7 +47,18 @@ def n_images_in_file(p_state, filename, idx_image_inchain=-1, idx_chain=-1): _Image_Read.argtypes = [ctypes.c_void_p, ctypes.c_char_p, ctypes.c_int, ctypes.c_int, ctypes.c_int] _Image_Read.restype = None +"""test docstring above image_read""" def image_read(p_state, filename, idx_image_infile=0, idx_image_inchain=-1, idx_chain=-1): + """Attempts to read a spin configuration from a file into an image of the chain. + + Arguments: + p_state -- state pointer + filename -- the name of the file to read + + Keyword arguments: + idx_image_infile -- the index of the image in the file which should be read in + idx_image_inchain -- the index of the image in the chain into which the data should be read + """ _Image_Read(ctypes.c_void_p(p_state), ctypes.c_char_p(filename.encode('utf-8')), ctypes.c_int(idx_image_infile), ctypes.c_int(idx_image_inchain), ctypes.c_int(idx_chain)) @@ -34,7 +68,18 @@ def image_read(p_state, filename, idx_image_infile=0, idx_image_inchain=-1, idx_ _Image_Write.argtypes = [ctypes.c_void_p, ctypes.c_char_p, ctypes.c_int, ctypes.c_char_p, ctypes.c_int, ctypes.c_int] _Image_Write.restype = None -def image_write(p_state, filename, fileformat=FILEFORMAT_OVF_TEXT, comment=" ", idx_image=-1, idx_chain=-1): +def image_write(p_state, filename, fileformat=FILEFORMAT_OVF_TEXT, comment="", idx_image=-1, idx_chain=-1): + """Write an image of the chain to a file. + + Arguments: + p_state -- state pointer + filename -- the name of the file to write + + Keyword arguments: + fileformat -- the format in which to write the data (default: OVF text) + comment -- a comment string to be inserted in the header (default: empty) + idx_image -- the index of the image to be written to the file + """ _Image_Write(ctypes.c_void_p(p_state), ctypes.c_char_p(filename.encode('utf-8')), ctypes.c_int(fileformat), ctypes.c_char_p(comment.encode('utf-8')), ctypes.c_int(idx_image), ctypes.c_int(idx_chain)) @@ -44,7 +89,20 @@ def image_write(p_state, filename, fileformat=FILEFORMAT_OVF_TEXT, comment=" ", _Image_Append.argtypes = [ctypes.c_void_p, ctypes.c_char_p, ctypes.c_int, ctypes.c_char_p, ctypes.c_int, ctypes.c_int] _Image_Append.restype = None -def image_append(p_state, filename, fileformat=FILEFORMAT_OVF_TEXT, comment=" ", idx_image=-1, idx_chain=-1): +def image_append(p_state, filename, fileformat=FILEFORMAT_OVF_TEXT, comment="", idx_image=-1, idx_chain=-1): + """Append an image of the chain to a file, incrementing the segment count. + + If the file does not exist, it is created. + + Arguments: + p_state -- state pointer + filename -- the name of the file to append to + + Keyword arguments: + fileformat -- the format in which to write the data (default: OVF text) + comment -- a comment string to be inserted in the header (default: empty) + idx_image -- the index of the image to be written to the file + """ _Image_Append(ctypes.c_void_p(p_state), ctypes.c_char_p(filename.encode('utf-8')), ctypes.c_int(fileformat), ctypes.c_char_p(filename.encode('utf-8')), ctypes.c_int(idx_image), ctypes.c_int(idx_chain)) @@ -82,20 +140,22 @@ def chain_append(p_state, filename, fileformat=FILEFORMAT_OVF_TEXT, comment=" ", ### Read eigenmodes from disk _Eigenmodes_Read = _spirit.IO_Eigenmodes_Read -_Eigenmodes_Read.argtypes = [ctypes.c_void_p, ctypes.c_char_p, ctypes.c_int, ctypes.c_int, +_Eigenmodes_Read.argtypes = [ctypes.c_void_p, ctypes.c_char_p, ctypes.c_int, ctypes.c_int, ctypes.c_int] _Eigenmodes_Read.restype = None def eigenmodes_read(p_state, filename, fileformat=FILEFORMAT_OVF_TEXT, idx_image_inchain=-1, idx_chain=-1): - _Eigenmodes_Read(ctypes.c_void_p(p_state), ctypes.c_char_p(filename.encode('utf-8')), - ctypes.c_int(fileformat), ctypes.c_int(idx_image_inchain), + """Read the vector fields from a file as a set of eigenmodes for the spin system.""" + _Eigenmodes_Read(ctypes.c_void_p(p_state), ctypes.c_char_p(filename.encode('utf-8')), + ctypes.c_int(fileformat), ctypes.c_int(idx_image_inchain), ctypes.c_int(idx_chain)) ### Write eigenmodes to disk _Eigenmodes_Write = _spirit.IO_Eigenmodes_Write -_Eigenmodes_Write.argtypes = [ctypes.c_void_p, ctypes.c_char_p, ctypes.c_int, +_Eigenmodes_Write.argtypes = [ctypes.c_void_p, ctypes.c_char_p, ctypes.c_int, ctypes.c_char_p, ctypes.c_int, ctypes.c_int] _Eigenmodes_Write.restype = None def eigenmodes_write(p_state, filename, fileformat=FILEFORMAT_OVF_TEXT, comment=" ", idx_image=-1, idx_chain=-1): - _Eigenmodes_Write(ctypes.c_void_p(p_state), ctypes.c_char_p(filename.encode('utf-8')), + """Write the eigenmodes of a spin system to file, if they have been already calculated.""" + _Eigenmodes_Write(ctypes.c_void_p(p_state), ctypes.c_char_p(filename.encode('utf-8')), ctypes.c_int(fileformat), ctypes.c_char_p(comment.encode('utf-8')), ctypes.c_int(idx_image), ctypes.c_int(idx_chain)) \ No newline at end of file diff --git a/core/python/spirit/log.py b/core/python/spirit/log.py index 46f2a6535..939e65af9 100644 --- a/core/python/spirit/log.py +++ b/core/python/spirit/log.py @@ -1,3 +1,8 @@ +""" +Log +-------------------- +""" + import spirit.spiritlib as spiritlib import ctypes diff --git a/core/python/spirit/parameters/__init__.py b/core/python/spirit/parameters/__init__.py index 20c111a1a..e30993624 100644 --- a/core/python/spirit/parameters/__init__.py +++ b/core/python/spirit/parameters/__init__.py @@ -1,3 +1,10 @@ +""" +Parameters +-------------------- + +Change the parameters of the various methods, which can be used. +""" + __all__ = ["gneb", "llg", "mc", "ema", "mmf"] from spirit.parameters import * \ No newline at end of file diff --git a/core/python/spirit/quantities.py b/core/python/spirit/quantities.py index c82212300..1d18da95d 100644 --- a/core/python/spirit/quantities.py +++ b/core/python/spirit/quantities.py @@ -1,3 +1,8 @@ +""" +Quantities +-------------------- +""" + import spirit.spiritlib as spiritlib import spirit.system as system from spirit.scalar import scalar diff --git a/core/python/spirit/simulation.py b/core/python/spirit/simulation.py index e242a584b..09bf52671 100644 --- a/core/python/spirit/simulation.py +++ b/core/python/spirit/simulation.py @@ -1,3 +1,8 @@ +""" +Simulation +-------------------- +""" + import spirit.spiritlib as spiritlib import ctypes diff --git a/core/python/spirit/state.py b/core/python/spirit/state.py index a27022dbb..15d61dcae 100644 --- a/core/python/spirit/state.py +++ b/core/python/spirit/state.py @@ -1,3 +1,8 @@ +""" +State +-------------------- +""" + import spirit.spiritlib as spiritlib import ctypes diff --git a/core/python/spirit/system.py b/core/python/spirit/system.py index dc8b21481..0aa018259 100644 --- a/core/python/spirit/system.py +++ b/core/python/spirit/system.py @@ -1,3 +1,8 @@ +""" +System +-------------------- +""" + import spirit.spiritlib as spiritlib import ctypes diff --git a/core/python/spirit/transition.py b/core/python/spirit/transition.py index f952f7279..85cfdf30a 100644 --- a/core/python/spirit/transition.py +++ b/core/python/spirit/transition.py @@ -1,3 +1,8 @@ +""" +Transition +-------------------- +""" + import spirit.spiritlib as spiritlib import ctypes diff --git a/docs/index.rst b/docs/index.rst index 87642b260..d728e2aa2 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,55 +1,54 @@ .. Spirit documentation master file, created by - sphinx-quickstart on Thu Jul 13 16:49:07 2017. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - :navtree_shift: True - :navtree_root_links: True + sphinx-quickstart on Thu Jul 13 16:49:07 2017. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + :navtree_shift: True + :navtree_root_links: True Spirit - Spin Simulation Framework ================================== .. toctree:: - :maxdepth: 1 - :caption: Introduction: - - General <../README> - Desktop User Interface + :maxdepth: 1 + :caption: Introduction: + + General <../README> + Desktop User Interface .. toctree:: - :maxdepth: 1 - :caption: Framework: - - Building Framework Components + :maxdepth: 1 + :caption: Framework: + + Building Framework Components .. toctree:: - :maxdepth: 1 - :caption: Core Library: - - Input File Specification <../core/docs/INPUT> - Building the Core Library <../core/docs/BUILD> - C API Reference <../core/docs/API> - Python API Reference <../core/docs/API_Python> + :maxdepth: 1 + :caption: Core Library: + + Input File Specification <../core/docs/INPUT> + Building the Core Library <../core/docs/BUILD> + C API Reference <../core/docs/API> + Python API Reference <../core/docs/API_Python> -.. c:autodoc:: core/include/Spirit/Chain.h .. toctree:: :maxdepth: 1 :caption: Python API Reference + :glob: - pyapidoc/spirit - pyapidoc/spirit.parameters + pyapidoc/* .. toctree:: - :maxdepth: 1 - :caption: Further Information: - - License - Contributing - Contributors - Referencing this Code - Included Dependencies + :maxdepth: 1 + :caption: Further Information: + + License + Contributing + Contributors + Referencing this Code + Included Dependencies Indices and tables diff --git a/docs/requirements.txt b/docs/requirements.txt index 15b3b6864..a9d877d96 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,4 +1,5 @@ pandoc sphinx-markdown-tables +numpy cmake gcc7 \ No newline at end of file From 19e2ef708947683be9a5419808bc0ca64a0c555e Mon Sep 17 00:00:00 2001 From: Gideon Date: Fri, 11 Jan 2019 17:43:30 +0100 Subject: [PATCH 3/6] Docs: improved Python API toctree. --- conf.py | 10 ++++++++++ core/python/spirit/parameters/ema.py | 5 +++++ core/python/spirit/parameters/gneb.py | 5 +++++ core/python/spirit/parameters/llg.py | 5 +++++ core/python/spirit/parameters/mc.py | 5 +++++ core/python/spirit/parameters/mmf.py | 5 +++++ docs/index.rst | 20 ++++++++++++++------ 7 files changed, 49 insertions(+), 6 deletions(-) diff --git a/conf.py b/conf.py index 58ec8f959..0488e0487 100644 --- a/conf.py +++ b/conf.py @@ -226,6 +226,16 @@ def run_apidoc(_): apidoc_dir = os.path.join(source_dir, 'docs', 'pyapidoc') package_dir = os.path.join(source_dir, 'core', 'python', 'spirit') + if not os.path.exists(apidoc_dir): + os.mkdir(apidoc_dir) + with open(os.path.join(apidoc_dir, 'parameters.rst'), "w") as parameters_file: + parameters_file.write("Parameters\n" + "==================================\n\n" + ".. toctree::\n :maxdepth: 2\n\n" + " MC \n LLG \n" + " GNEB \n EMA \n" + " MMF ") + import subprocess cmd_path = 'sphinx-apidoc' if hasattr(sys, 'real_prefix'): # Check to see if we are in a virtualenv diff --git a/core/python/spirit/parameters/ema.py b/core/python/spirit/parameters/ema.py index 44d3fdb6b..0c487c585 100644 --- a/core/python/spirit/parameters/ema.py +++ b/core/python/spirit/parameters/ema.py @@ -1,3 +1,8 @@ +""" +Eigenmode analysis (EMA) method parameters +------------------------------------------------------------- +""" + import spirit.spiritlib as spiritlib import ctypes diff --git a/core/python/spirit/parameters/gneb.py b/core/python/spirit/parameters/gneb.py index 88d132590..a011351af 100644 --- a/core/python/spirit/parameters/gneb.py +++ b/core/python/spirit/parameters/gneb.py @@ -1,3 +1,8 @@ +""" +Geodesic nudged elastic band (GNEB) method parameters +------------------------------------------------------------- +""" + import spirit.spiritlib as spiritlib from spirit.io import FILEFORMAT_OVF_TEXT import ctypes diff --git a/core/python/spirit/parameters/llg.py b/core/python/spirit/parameters/llg.py index 01425d0ff..eda1f3aee 100644 --- a/core/python/spirit/parameters/llg.py +++ b/core/python/spirit/parameters/llg.py @@ -1,3 +1,8 @@ +""" +Landau-Lifshitz-Gilbert (LLG) method parameters +------------------------------------------------------------- +""" + import spirit.spiritlib as spiritlib from spirit.io import FILEFORMAT_OVF_TEXT import ctypes diff --git a/core/python/spirit/parameters/mc.py b/core/python/spirit/parameters/mc.py index bd949cec6..fb58fd4f0 100644 --- a/core/python/spirit/parameters/mc.py +++ b/core/python/spirit/parameters/mc.py @@ -1,3 +1,8 @@ +""" +Monte Carlo (MC) method parameters +------------------------------------------------------------- +""" + import spirit.spiritlib as spiritlib from spirit.io import FILEFORMAT_OVF_TEXT import ctypes diff --git a/core/python/spirit/parameters/mmf.py b/core/python/spirit/parameters/mmf.py index ee046bf46..087d40b59 100644 --- a/core/python/spirit/parameters/mmf.py +++ b/core/python/spirit/parameters/mmf.py @@ -1,3 +1,8 @@ +""" +Minimum mode following (MMF) method parameters +------------------------------------------------------------- +""" + import spirit.spiritlib as spiritlib import ctypes diff --git a/docs/index.rst b/docs/index.rst index d728e2aa2..9e81b2765 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -30,15 +30,23 @@ Spirit - Spin Simulation Framework C API Reference <../core/docs/API> Python API Reference <../core/docs/API_Python> - - - .. toctree:: - :maxdepth: 1 + :maxdepth: 2 :caption: Python API Reference - :glob: - pyapidoc/* + Chain + Configuration + Constants + Geometry + Hamiltonian + I/O + Log + Parameters + Quantities + Simulation + State + System + Transition .. toctree:: :maxdepth: 1 From e96f58b5711597b3de642ba40b23bf565d45f1d2 Mon Sep 17 00:00:00 2001 From: Gideon Date: Fri, 11 Jan 2019 18:54:53 +0100 Subject: [PATCH 4/6] Docs: moved Python API doc text from MD file to Python files. Also added a bunch of new documentation, so that the Python API is now documented quite completely. --- core/docs/API_Python.md | 277 -------------------------- core/python/spirit/chain.py | 78 +++++++- core/python/spirit/configuration.py | 60 ++++-- core/python/spirit/geometry.py | 95 ++++++--- core/python/spirit/hamiltonian.py | 51 +++-- core/python/spirit/io.py | 71 +++++-- core/python/spirit/log.py | 48 +++-- core/python/spirit/parameters/ema.py | 11 +- core/python/spirit/parameters/gneb.py | 84 +++++--- core/python/spirit/parameters/llg.py | 106 +++++++--- core/python/spirit/parameters/mc.py | 54 +++-- core/python/spirit/parameters/mmf.py | 45 +++-- core/python/spirit/quantities.py | 27 ++- core/python/spirit/simulation.py | 84 +++++++- core/python/spirit/state.py | 39 +++- core/python/spirit/system.py | 21 +- core/python/spirit/transition.py | 11 +- docs/index.rst | 27 ++- 18 files changed, 694 insertions(+), 495 deletions(-) delete mode 100644 core/docs/API_Python.md diff --git a/core/docs/API_Python.md b/core/docs/API_Python.md deleted file mode 100644 index 3acf51ac4..000000000 --- a/core/docs/API_Python.md +++ /dev/null @@ -1,277 +0,0 @@ -SPIRIT Python API -==================== - -State ------ - -To create a new state with one chain containing a single image, initialized by an [input file](INPUT.md), and run the most simple example of a **spin dynamics simulation**: -```python -from spirit import state -from spirit import simulation - -cfgfile = "input/input.cfg" # Input File -with state.State(cfgfile) as p_state: # State setup - simulation.start(p_state, simulation.METHOD_LLG, simulation.SOLVER_SIB) # Start a LLG simulation using the SIB solver -``` -or call setup and delete manually: -```python -from spirit import state -from spirit import simulation - -cfgfile = "input/input.cfg" # Input File -p_state = state.setup(cfgfile) # State setup -simulation.start(p_state, simulation.METHOD_LLG, simulation.SOLVER_SIB) # Start a LLG simulation using the SIB solver -state.delete(p_state) # State cleanup -``` - -You can pass a [config file](INPUT.md) specifying your initial system parameters. -If you do not pass a config file, the implemented defaults are used. -**Note that you currently cannot change the geometry of the systems in your state once they are initialized.** - -| State manipulation | Returns | -| ----------------------------------------------------------------------------------- | ---------- | -| `setup( configfile="", quiet=False )` | `None` | -| `delete(p_state )` | `None` | - - -System ------- - -| System | Returns | Description | -| --------------------------------------------------------------------- | -------- | ------------------------------------------------------------------------------------ | -| `get_index(p_state)` | `int` | Returns the index of the currently active image | -| `get_nos(p_state, idx_image=-1, idx_chain=-1)` | `int` | Returns the number of spins | -| `get_spin_directions(p_state, idx_image=-1, idx_chain=-1)` | `[3*NOS]`| Returns an `numpy.Array` of size `3*NOS` with the components of each spin's vector | -| `get_energy(p_state, idx_image=-1, idx_chain=-1)` | `float` | Returns the energy of the system | -| `update_data(p_state, idx_image=-1, idx_chain=-1)` | `None` | Update the data of the state | -| `print_energy_array(p_state, idx_image=-1, idx_chain=-1)` | `None` | Print the energy array of the state | - - -Chain ------ - -For having more images one can copy the active image in the Clipboard and then insert in a specified position of the chain. -```python -chain.image_to_clipboard(p_state ) # Copy p_state to Clipboard -chain.insert_image_after(p_state ) # Insert the image from Clipboard right after the currently active image -``` -For getting the total number of images in the chain -```python -number_of_images = chain.get_noi(p_state ) -``` - -| Get Info | Returns | Description | -| --------------------------------------------------------------------------- | -------------- | ---------------------------------------------------------- | -| `get_index(p_state )` | `int` | Get Chain index | -| `get_noi(p_state, idx_chain=-1)` | `int` | Get Chain number of images | -| `get_rx(p_state, idx_chain=-1)` | `Array` | Get Rx | -| `get_rx_interpolated(p_state, idx_chain=-1)` | `Array(float)` | Get Rx interpolated | -| `get_energy(p_state, idx_chain=-1)` | `Array(float)` | Get Energy of every System in Chain | -| `get_energy_interpolated(p_state, idx_chain=-1)` | `Array(float)` | Get interpolated Energy of every System in Chain | - -| Image Manipulation | Returns | Description | -| --------------------------------------------------------------- | -------------- | ---------------------------------------------------------- | -| `next_image(p_state, idx_chain=-1)` | `None` | Switch active to next image of chain (one with largest index). If the current active is the last there is no effect. | -| `prev_image(p_state, idx_chain=-1)` | `None` | Switch active to previous image of chain (one with smaller index). If the current active is the first one there is no effect | -| `jump_to_image(p_state, idx_image=-1, idx_chain=-1)` | `None` | Switch active to specific image of chain. If this image does not exist there is no effect. | -| `image_to_clipboard(p_state, idx_image=-1, idx_chain=-1)` | `None` | Copy active image to clipboard | -| `replace_image(p_state, idx_image=-1, idx_chain=-1)` | `None` | Replace active image in chain. If the image does not exist there is no effect. | -| `insert_image_before(p_state, idx_image=-1, idx_chain=-1)` | `None` | Inserts clipboard image before the current active image. Active image index is increment by one. | -| `insert_image_after(p_state, idx_image=-1, idx_chain=-1)` | `None` | Insert clipboard image after the current active image. Active image has the same index. | -| `push_back(p_state, idx_chain=-1)` | `None` | Insert clipboard image at end of chain (after the image with the largest index). | -| `delete_image(p_state, idx_image=-1, idx_chain=-1)` | `None` | Delete active image. If index is specified delete the corresponding image. If the image does not exist there is no effect. | -| `pop_back(p_state, idx_chain=-1)` | `None` | Delete image at end of chain. | - -| Data | Returns | Description | -| ------------------------------------------- | -------------- | ---------------------------------------------------------- | -| `update_data(p_state, idx_chain=-1)` | `None` | Update the chain's data (interpolated energies etc.) | -| `setup_data(p_state, idx_chain=-1)` | `None` | Setup the chain's data arrays | - - -Constants ---------- - -| Physical Constants | Returns | Description | -| --------------------------------------- | -------------- | -------------------------------------------------- | -| `mu_B` | `float` | The Bohr Magneton [meV / T] | -| `k_B` | `float` | The Boltzmann constant [meV / K] | -| `hbar` | `float` | Planck's constant over 2pi [meV*ps / rad] | -| `mRy` | `float` | Millirydberg [mRy / meV] | -| `gamma` | `float` | The Gyromagnetic ratio of electron [rad / (ps*T)] | -| `g_e` | `float` | The Electron g-factor [unitless] | - - -Geometry --------- - -| Set Geometry parameters | Description | -| ----------------------------------------------------------------------------- | ----------------------------------------------------- | -| `set_bravais_lattice_type(p_state, lattice_type, idx_image=-1, idx_chain=-1)` | Set the bravais vectors to a pre-defined lattice type | -| `set_n_cells(p_state, n_cells=[1, 1, 1], idx_image=-1, idx_chain=-1)` | Set the number of basis cells along bravais vectors | -| `set_mu_s(p_state, mu_s, idx_image=-1, idx_chain=-1)` | Set the magnetic moment of all atoms | -| `set_cell_atom_types(p_state, atom_types, idx_image=-1, idx_chain=-1)` | Set the atom types of the cell atoms | -| `set_bravais_vectors(p_state, ta=[1.0, 0.0, 0.0], tb=[0.0, 1.0, 0.0], tc=[0.0, 0.0, 1.0], idx_image=-1, idx_chain=-1)` | Manually specify bravais vectors | -| `set_lattice_constant(p_state, lattice_constant, idx_image=-1, idx_chain=-1)` | Set the global lattice constant | - -| Get Geometry parameters | Returns | Description | -| -------------------------------------------------------------------- | --------------------- | -------------------------------------------------- | -| `get_bounds(p_state, idx_image=-1, idx_chain=-1)` | `[3], [3]` | Get bounds (minimum and maximum arrays) | -| `get_center(p_state, idx_image=-1, idx_chain=-1)` | `float, float, float` | Get center | -| `get_basis_vectors(p_state, idx_image=-1, idx_chain=-1)` | `[3],[3],[3]` | Get basis vectors | -| `get_n_cells(p_state, idx_image=-1, idx_chain=-1)` | `Int, Int, Int` | Get number of cells in each dimension | -| `get_translation_vectors(p_state, idx_image=-1, idx_chain=-1)` | `[3],[3],[3]` | Get translation vectors | -| `get_dimensionality(p_state, idx_image=-1, idx_chain=-1)` | `int` | Get dimensionality of the system | -| `get_spin_positions(p_state, idx_image=-1, idx_chain=-1)` | `[3*NOS]` | Get Spin positions | -| `get_atom_types(p_state, idx_image=-1, idx_chain=-1)` | `[NOS]` | Get atom types | - - -Hamiltonian ------------ - -| Set Parameters | Returns | Description | -| ------------------------------------------------------------------------------- | --------------------- | ----------------------------------------------------------- | -| `set_boundary_conditions(p_state, boundaries, idx_image=-1, idx_chain=-1)` | `None` | Set the boundary conditions [a, b, c]: 0=open, 1=periodical | -| `set_field(p_state, magnitude, direction, idx_image=-1, idx_chain=-1)` | `None` | Set external magnetic field | -| `set_anisotropy(p_state, magnitude, direction, idx_image=-1, idx_chain=-1)` | `None` | Set a magnitude and normal of anisotropy for all spins | -| `set_exchange(p_state, n_shells, J_ij, idx_image=-1, idx_chain=-1)` | `None` | Set the exchange pairs in terms of neighbour shells | -| `set_dmi(p_state, n_shells, D_ij, idx_image=-1, idx_chain=-1)` | `None` | Set the DMI pairs in terms of neighbour shells | -| `set_ddi(p_state, radius, idx_image=-1, idx_chain=-1)` | `None` | Set dipole-dipole cutoff radius | - - -Log ---- - -| Log manipulation | Returns | Description | -| ------------------------------------------------------------------------ | --------- | --------------------------- | -| `send(p_state, level, sender, message, idx_image=-1, idx_chain=-1)` | `None` | Send a Log message | -| `append(p_state)` | `None` | Append Log to file | - - -Parameters ----------- - -### LLG - -| Set LLG Parameters | Returns | -| --------------------------------------------------------------------------------------------- | ------------- | -| `set_iterations(p_state, n_iterations, n_iterations_log, idx_image=-1, idx_chain=-1)` | `None` | -| `set_direct_minimization(p_state, use_minimization, idx_image=-1, idx_chain=-1)` | `None` | -| `set_convergence(p_state, convergence, idx_image=-1, idx_chain=-1)` | `None` | -| `set_time_step(p_state, dt, idx_image=-1, idx_chain=-1)` | `None` | -| `set_damping(p_state, damping, idx_image=-1, idx_chain=-1)` | `None` | -| `set_stt(p_state, use_gradient, magnitude, direction, idx_image=-1, idx_chain=-1)` | `None` | -| `set_temperature(p_state, temperature, idx_image=-1, idx_chain=-1)` | `None` | - -| Get LLG Parameters | Returns | -| ---------------------------------------------------------------------- | ------------- | -| `get_iterations(p_state, idx_image=-1, idx_chain=-1)` | `int, int` | -| `get_direct_minimization(p_state, idx_image=-1, idx_chain=-1)` | `int` | -| `get_convergence(p_state, idx_image=-1, idx_chain=-1)` | `float` | -| `get_time_step(p_state, idx_image=-1, idx_chain=-1)` | `float` | -| `get_damping(p_state, idx_image=-1, idx_chain=-1)` | `float` | -| `get_stt(p_state, idx_image=-1, idx_chain=-1)` | `float, [3], bool` | -| `get_temperature(p_state, idx_image=-1, idx_chain=-1)` | `float` | - -### GNEB - -| Set GNEB Parameters | Returns | -| -------------------------------------------------------------------------------------------------- | ------------- | -| `set_iterations(p_state, n_iterations, n_iterations_log, idx_image=-1, idx_chain=-1)` | `None` | -| `set_convergence(p_state, convergence, idx_image=-1, idx_chain=-1)` | `None` | -| `set_spring_force(p_state, spring_constant=1, ratio=0, idx_image=-1, idx_chain=-1)` | `None` | -| `set_climbing_falling(p_state, image_type, idx_image=-1, idx_chain=-1)` | `None` | -| `set_image_type_automatically(p_state, idx_chain=-1)` | `None` | - -| Get GNEB Parameters | Returns | -| -------------------------------------------------------------------- | ------------- | -| `get_iterations(p_state, idx_chain=-1)` | `int, int` | -| `get_convergence(p_state, idx_image=-1, idx_chain=-1)` | `float` | -| `get_spring_force(p_state, idx_image=-1, idx_chain=-1)` | `float` | -| `get_climbing_falling(p_state, idx_image=-1, idx_chain=-1)` | `int` | -| `get_energy_interpolations(p_state, idx_chain=-1)` | `int` | - - -Quantities ----------- - -| Get Physical Quantities | Returns | -| -------------------------------------------------------------------- | ------------- | -| `get_magnetization(p_state, idx_image=-1, idx_chain=-1)` | `[3*float]` | - -Simulation ----------- - -The available `method_type`s are: - -| Method | Argument | -| ----------------------------- | :----------: | -| Monte-Carlo | `METHOD_MC` | -| Landau-Lifshitz-Gilbert | `METHOD_LLG` | -| Geodesic Nudged Elastic Band | `METHOD_GNEB`| -| Mode Following Method | `METHOD_MMF` | -| Eigenmode analysis | `METHOD_EMA` | - -The available `solver_type`s are: - -| Solver | Argument | -| ----------------------------- | :-----------: | -| Semi-Implicit Method B | `SOLVER_SIB` | -| Heun Method | `SOLVER_HEUN` | -| Depondt Method | `SOLVER_HEUN` | -| Velocity Projection | `SOLVER_VP` | - -Note that the VP and NCG Solvers are only meant for direct minimization and not for dynamics. - -| Simulation state | Returns | -| ------------------------------------------------------- | ---------- | -| `start(p_state, method_type, solver_type=None, n_iterations=-1, n_iterations_log=-1, single_shot=False, idx_image=-1, idx_chain=-1)` | `None` | -| `single_shot(p_state, idx_image=-1, idx_chain=-1)` | `None` | -| `stop(p_state, idx_image=-1, idx_chain=-1)` | `None` | -| `stop_all(p_state)` | `None` | -| `running_on_image(p_state, idx_image=-1, idx_chain=-1)` | `Boolean` | -| `running_on_chain(p_state, idx_chain=-1)` | `Boolean` | -| `running_anywhere_on_chain(p_state, idx_chain=-1)` | `Boolean` | - - -Transition ----------- - -| Transition options | Returns | Description | -| ---------------------------------------------------------------------------- | -------- | ---------------------------------------------------------------------------------- | -| `homogeneous(p_state, idx_1, idx_2, idx_chain=-1)` | `None` | Generate homogeneous transition between two images of a chain | -| `add_noise(p_state, temperature, idx_1, idx_2, idx_chain=-1)` | `None` | Add some temperature-scaled noise to a transition between two images of a chain | - - -Input/Output ------------- - -Note that, when reading an image or chain from file, the file will automatically be tested for an OVF header. -If it cannot be identified as OVF, it will be tried to be read as three plain text columns (Sx Sy Sz). - -Note also, IO is still being re-written and only OVF will be supported as output format. - -| For Image | Description | -| ----------------------------------------------------------------------------------------- | ------------------------------------ | -| `n_images_in_file(p_state, filename, idx_image_inchain=-1, idx_chain=-1)` | Read specified image from a file to specified image in the chain | -| `image_read(p_state, filename, idx_image_infile=0, idx_image_inchain=-1, idx_chain=-1)` | Read specified image from a file to specified image in the chain | -| `image_write(p_state, filename, fileformat=FILEFORMAT_OVF_TEXT, comment=" ", idx_image=-1, idx_chain=-1)` | Write an image to disk | -| `image_append(p_state, filename, fileformat=FILEFORMAT_OVF_TEXT, comment=" ", idx_image=-1, idx_chain=-1)` | Append an image to an existing file | - -| For Chain | Description | -| ----------------------------------------------------------------------------- | ------------------------------------ | -| `chain_read(p_state, filename, starting_image=-1, ending_image=-1, insert_idx=-1, idx_chain=-1)` | Read some images from a file and insert them into the chain, starting at a specified index | -| `chain_write(p_state, filename, fileformat=FILEFORMAT_OVF_TEXT, comment=" ", idx_chain=-1)` | Write a chain of images to disk | -| `chain_append(p_state, filename, fileformat=FILEFORMAT_OVF_TEXT, comment=" ", idx_chain=-1)` | Append a chain of images to disk | - -| Macros of File Formats for Vector Fields | values | Description | -| ---------------------------------------- | :-----: | --------------------------------------------------| -| `FILEFORMAT_OVF_BIN` | 0 | [OOMMF vector field (OVF) v2.0](http://math.nist.gov/oommf/doc/userguide12a5/userguide/OVF_2.0_format.html) file format (binary, automatically determined size) | -| `FILEFORMAT_OVF_BIN4` | 1 | [OOMMF vector field (OVF) v2.0](http://math.nist.gov/oommf/doc/userguide12a5/userguide/OVF_2.0_format.html) file format (binary 4) | -| `FILEFORMAT_OVF_BIN8` | 2 | [OOMMF vector field (OVF) v2.0](http://math.nist.gov/oommf/doc/userguide12a5/userguide/OVF_2.0_format.html) file format (binary 8) | -| `FILEFORMAT_OVF_TEXT` | 3 | [OOMMF vector field (OVF) v2.0](http://math.nist.gov/oommf/doc/userguide12a5/userguide/OVF_2.0_format.html) file format (plaintext) | -| `FILEFORMAT_OVF_CSV` | 4 | [OOMMF vector field (OVF) v2.0](http://math.nist.gov/oommf/doc/userguide12a5/userguide/OVF_2.0_format.html) file format (comma-separated plaintext) | - - ---- - -[Home](README.md) \ No newline at end of file diff --git a/core/python/spirit/chain.py b/core/python/spirit/chain.py index 7984a081d..d986b419a 100644 --- a/core/python/spirit/chain.py +++ b/core/python/spirit/chain.py @@ -2,7 +2,7 @@ Chain -------------------- -Manipulate the chain of spin systems (images), e.g. add, remove or change active image. +Manipulate the chain of spin systems (also called images), e.g. add, remove or change active image. Get information, such as number of images or energies and reaction coordinates. """ @@ -20,6 +20,7 @@ _Get_NOI.argtypes = [ctypes.c_void_p, ctypes.c_int] _Get_NOI.restype = ctypes.c_int def get_noi(p_state, idx_chain=-1): + """Get number of images (NOI) in the chain.""" return int(_Get_NOI(ctypes.c_void_p(p_state), ctypes.c_int(idx_chain))) @@ -28,6 +29,7 @@ def get_noi(p_state, idx_chain=-1): _next_Image.argtypes = [ctypes.c_void_p, ctypes.c_int] _next_Image.restype = ctypes.c_bool def next_image(p_state, idx_chain=-1): + """Switch the active image index to the next highest in the chain.""" return bool(_next_Image(ctypes.c_void_p(p_state), ctypes.c_int(idx_chain))) ### Switch active to previous image of chain @@ -35,6 +37,7 @@ def next_image(p_state, idx_chain=-1): _prev_Image.argtypes = [ctypes.c_void_p, ctypes.c_int] _prev_Image.restype = ctypes.c_bool def prev_image(p_state, idx_chain=-1): + """Switch the active image index to the next lowest in the chain.""" return bool(_prev_Image(ctypes.c_void_p(p_state), ctypes.c_int(idx_chain))) ### Switch active to specific image of chain @@ -42,6 +45,7 @@ def prev_image(p_state, idx_chain=-1): _Jump_To_Image.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_int] _Jump_To_Image.restype = ctypes.c_bool def jump_to_image(p_state, idx_image=-1, idx_chain=-1): + """Set the index of the active image in the chain.""" return bool(_Jump_To_Image(ctypes.c_void_p(p_state), ctypes.c_int(idx_image), ctypes.c_int(idx_chain))) @@ -50,6 +54,16 @@ def jump_to_image(p_state, idx_image=-1, idx_chain=-1): _Set_Length.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_int] _Set_Length.restype = None def set_length(p_state, n_images, idx_chain=-1): + """Set the number of images (NOI) in the chain. + + If the chain is longer, the corresponding number of images is erased from the end. + + If the chain is shorter, the corresponding number of images is appended. + + Note that the active image might change. + + If no image is in the clipboard, no action is taken. + """ _Set_Length(ctypes.c_void_p(p_state), ctypes.c_int(n_images), ctypes.c_int(idx_chain)) ### Copy active image to clipboard @@ -57,6 +71,7 @@ def set_length(p_state, n_images, idx_chain=-1): _Image_to_Clipboard.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_int] _Image_to_Clipboard.restype = None def image_to_clipboard(p_state, idx_image=-1, idx_chain=-1): + """Copies an image to the clipboard of Spirit. It can then be later e.g. inserted or appended.""" _Image_to_Clipboard(ctypes.c_void_p(p_state), ctypes.c_int(idx_image), ctypes.c_int(idx_chain)) ### Replace active image in chain @@ -64,6 +79,10 @@ def image_to_clipboard(p_state, idx_image=-1, idx_chain=-1): _Replace_Image.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_int] _Replace_Image.restype = None def replace_image(p_state, idx_image=-1, idx_chain=-1): + """Replaces the image from the one in the clipboard. + + If no image is in the clipboard, no action is taken. + """ _Replace_Image(ctypes.c_void_p(p_state), ctypes.c_int(idx_image), ctypes.c_int(idx_chain)) @@ -72,6 +91,12 @@ def replace_image(p_state, idx_image=-1, idx_chain=-1): _Insert_Image_Before.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_int] _Insert_Image_Before.restype = None def insert_image_before(p_state, idx_image=-1, idx_chain=-1): + """Inserts an image in front of the specified index. + + Note that the active image might change. + + If no image is in the clipboard, no action is taken. + """ _Insert_Image_Before(ctypes.c_void_p(p_state), ctypes.c_int(idx_image), ctypes.c_int(idx_chain)) ### Insert clipboard image after image in chain @@ -79,6 +104,12 @@ def insert_image_before(p_state, idx_image=-1, idx_chain=-1): _Insert_Image_After.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_int] _Insert_Image_After.restype = None def insert_image_after(p_state, idx_image=-1, idx_chain=-1): + """Inserts an image after the specified index. + + Note that the active image might change. + + If no image is in the clipboard, no action is taken. + """ _Insert_Image_After(ctypes.c_void_p(p_state), ctypes.c_int(idx_image), ctypes.c_int(idx_chain)) ### Insert clipboard image at end of chain @@ -86,6 +117,10 @@ def insert_image_after(p_state, idx_image=-1, idx_chain=-1): _Push_Back.argtypes = [ctypes.c_void_p, ctypes.c_int] _Push_Back.restype = None def push_back(p_state, idx_chain=-1): + """Appends an image to the chain. + + If no image is in the clipboard, no action is taken. + """ _Push_Back(ctypes.c_void_p(p_state), ctypes.c_int(idx_chain)) @@ -95,6 +130,12 @@ def push_back(p_state, idx_chain=-1): _Delete_Image.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_int] _Delete_Image.restype = ctypes.c_bool def delete_image(p_state, idx_image=-1, idx_chain=-1): + """Removes the specified image from the chain. + + Note that the active image might change. + + If it is the last remaining image in the chain, no action is taken. + """ return bool(_Delete_Image(ctypes.c_void_p(p_state), ctypes.c_int(idx_image), ctypes.c_int(idx_chain))) ### Delete image at end of chain @@ -102,6 +143,12 @@ def delete_image(p_state, idx_image=-1, idx_chain=-1): _Pop_Back.argtypes = [ctypes.c_void_p, ctypes.c_int] _Pop_Back.restype = ctypes.c_bool def pop_back(p_state, idx_chain=-1): + """Removes the last image from the chain. + + Note that the active image might change. + + If it is the last remaining image in the chain, no action is taken. + """ return bool(_Pop_Back(ctypes.c_void_p(p_state), ctypes.c_int(idx_chain))) @@ -110,6 +157,12 @@ def pop_back(p_state, idx_chain=-1): _Update_Data.argtypes = [ctypes.c_void_p, ctypes.c_int] _Update_Data.restype = None def update_data(p_state, idx_chain=-1): + """Updates various data of the chain, including: + + - Energies of images + - Reaction coordinates of images + - Interpolated energy and reaction coordinate values + """ _Update_Data(ctypes.c_void_p(p_state), ctypes.c_int(idx_chain)) @@ -126,6 +179,7 @@ def setup_data(p_state, idx_chain=-1): _Get_Rx.argtypes = [ctypes.c_void_p, ctypes.POINTER(ctypes.c_float), ctypes.c_int] _Get_Rx.restype = None def get_reaction_coordinate(p_state, idx_chain=-1): + """Returns an array of shape (NOI) containing the reaction coordinates of the images.""" noi = get_noi(p_state, idx_chain) Rx = (noi*ctypes.c_float)() _Get_Rx(ctypes.c_void_p(p_state), Rx, ctypes.c_int(idx_chain)) @@ -136,6 +190,10 @@ def get_reaction_coordinate(p_state, idx_chain=-1): _Get_Rx_Interpolated.argtypes = [ctypes.c_void_p, ctypes.POINTER(ctypes.c_float), ctypes.c_int] _Get_Rx_Interpolated.restype = None def get_reaction_coordinate_interpolated(p_state, idx_chain=-1): + """Returns an array containing the interpolated reaction coordinate values along the chain. + + The number of interpolated values between images can be set in the GNEB parameters. + """ noi = get_noi(p_state, idx_chain) n_interp = parameters.gneb.get_n_energy_interpolations(p_state, idx_chain) len_Rx = noi + (noi-1)*n_interp @@ -148,6 +206,7 @@ def get_reaction_coordinate_interpolated(p_state, idx_chain=-1): _Get_Energy.argtypes = [ctypes.c_void_p, ctypes.POINTER(ctypes.c_float), ctypes.c_int] _Get_Energy.restype = None def get_energy(p_state, idx_chain=-1): + """Returns an array of shape (NOI) containing the energies of the images.""" noi = get_noi(p_state, idx_chain) Energy = (noi*ctypes.c_float)() _Get_Energy(ctypes.c_void_p(p_state), Energy, ctypes.c_int(idx_chain)) @@ -158,6 +217,10 @@ def get_energy(p_state, idx_chain=-1): _Get_Energy_Interpolated.argtypes = [ctypes.c_void_p, ctypes.POINTER(ctypes.c_float), ctypes.c_int] _Get_Energy_Interpolated.restype = None def get_energy_interpolated(p_state, idx_chain=-1): + """Returns an array containing the interpolated energy values along the chain. + + The number of interpolated values between images can be set in the GNEB parameters. + """ noi = get_noi(p_state, idx_chain) n_interp = parameters.gneb.get_n_energy_interpolations(p_state, idx_chain) len_Energy = noi + (noi-1)*n_interp @@ -173,6 +236,19 @@ def get_energy_interpolated(p_state, idx_chain=-1): ctypes.POINTER(ctypes.c_float), ctypes.POINTER(ctypes.c_float), ctypes.c_int] _Get_HTST_Info.restype = None def get_htst_info(p_state, idx_chain=-1): + """Calculates and returns a set of HTST information: + + - eigenvalues at the minimum + - eigenvalues at the saddle point + - the exponent of the temperature-dependence + - `me` + - `Omega_0` + - `s` + - zero mode volume at the minimum + - zero mode volume at the saddle point + - dynamical prefactor + - full rate prefactor (without temperature dependent part) + """ nos = system.get_nos(p_state, -1, idx_chain) eigenvalues_min = (2*nos*ctypes.c_float)() eigenvalues_sp = (2*nos*ctypes.c_float)() diff --git a/core/python/spirit/configuration.py b/core/python/spirit/configuration.py index 326926786..05becb554 100644 --- a/core/python/spirit/configuration.py +++ b/core/python/spirit/configuration.py @@ -11,8 +11,6 @@ ### Load Library _spirit = spiritlib.load_spirit_library() - -### Domain (homogeneous) configuration _Domain = _spirit.Configuration_Domain _Domain.argtypes = [ctypes.c_void_p, ctypes.POINTER(ctypes.c_float), ctypes.POINTER(ctypes.c_float), ctypes.POINTER(ctypes.c_float), @@ -20,13 +18,12 @@ _Domain.restype = None def domain(p_state, dir, pos=[0,0,0], border_rectangular=[-1,-1,-1], border_cylindrical=-1, border_spherical=-1, inverted=False, idx_image=-1, idx_chain=-1): + """Set a domain (homogeneous) configuration.""" vec3 = ctypes.c_float * 3 _Domain(ctypes.c_void_p(p_state), vec3(*dir), vec3(*pos), vec3(*border_rectangular), ctypes.c_float(border_cylindrical), ctypes.c_float(border_spherical), ctypes.c_bool(inverted), ctypes.c_int(idx_image), ctypes.c_int(idx_chain)) - -### All spins in +z direction _PlusZ = _spirit.Configuration_PlusZ _PlusZ.argtypes = [ctypes.c_void_p, ctypes.POINTER(ctypes.c_float), ctypes.POINTER(ctypes.c_float), ctypes.c_float, ctypes.c_float, ctypes.c_bool, @@ -34,13 +31,12 @@ def domain(p_state, dir, pos=[0,0,0], border_rectangular=[-1,-1,-1], border_cyli _PlusZ.restype = None def plus_z(p_state, pos=[0.0,0.0,0.0], border_rectangular=[-1.0,-1.0,-1.0], border_cylindrical=-1.0, border_spherical=-1.0, inverted=False, idx_image=-1, idx_chain=-1): + """Set a +z (homogeneous) configuration.""" vec3 = ctypes.c_float * 3 _PlusZ(ctypes.c_void_p(p_state), vec3(*pos), vec3(*border_rectangular), ctypes.c_float(border_cylindrical), ctypes.c_float(border_spherical), ctypes.c_bool(inverted), ctypes.c_int(idx_image), ctypes.c_int(idx_chain)) - -### All spins in -z direction _MinusZ = _spirit.Configuration_MinusZ _MinusZ.argtypes = [ctypes.c_void_p, ctypes.POINTER(ctypes.c_float), ctypes.POINTER(ctypes.c_float), ctypes.c_float, ctypes.c_float, @@ -48,12 +44,12 @@ def plus_z(p_state, pos=[0.0,0.0,0.0], border_rectangular=[-1.0,-1.0,-1.0], bord _MinusZ.restype = None def minus_z(p_state, pos=[0,0,0], border_rectangular=[-1,-1,-1], border_cylindrical=-1, border_spherical=-1, inverted=False, idx_image=-1, idx_chain=-1): + """Set a -z (homogeneous) configuration.""" vec3 = ctypes.c_float * 3 _MinusZ(ctypes.c_void_p(p_state), vec3(*pos), vec3(*border_rectangular), ctypes.c_float(border_cylindrical), ctypes.c_float(border_spherical), ctypes.c_bool(inverted), ctypes.c_int(idx_image), ctypes.c_int(idx_chain)) -### Random configuration _Random = _spirit.Configuration_Random _Random.argtypes = [ctypes.c_void_p, ctypes.POINTER(ctypes.c_float), ctypes.POINTER(ctypes.c_float), ctypes.c_float, ctypes.c_float, @@ -61,13 +57,12 @@ def minus_z(p_state, pos=[0,0,0], border_rectangular=[-1,-1,-1], border_cylindri _Random.restype = None def random(p_state, pos=[0,0,0], border_rectangular=[-1,-1,-1], border_cylindrical=-1, border_spherical=-1, inverted=False, idx_image=-1, idx_chain=-1): + """Distribute all spins randomly on the unit sphere.""" vec3 = ctypes.c_float * 3 _Random(ctypes.c_void_p(p_state), vec3(*pos), vec3(*border_rectangular), ctypes.c_float(border_cylindrical), ctypes.c_float(border_spherical), ctypes.c_bool(inverted), False, ctypes.c_int(idx_image), ctypes.c_int(idx_chain)) - -### Add temperature-scaled random noise to configuration _Add_Noise_Temperature = _spirit.Configuration_Add_Noise_Temperature _Add_Noise_Temperature.argtypes = [ctypes.c_void_p, ctypes.c_float, ctypes.POINTER(ctypes.c_float), ctypes.POINTER(ctypes.c_float), @@ -77,23 +72,34 @@ def random(p_state, pos=[0,0,0], border_rectangular=[-1,-1,-1], border_cylindric def add_noise(p_state, temperature, pos=[0,0,0], border_rectangular=[-1,-1,-1], border_cylindrical=-1, border_spherical=-1, inverted=False, idx_image=-1, idx_chain=-1): + """Add temperature-scaled random noise to configuration.""" vec3 = ctypes.c_float * 3 _Add_Noise_Temperature(ctypes.c_void_p(p_state), ctypes.c_float(temperature), vec3(*pos), vec3(*border_rectangular), ctypes.c_float(border_cylindrical), ctypes.c_float(border_spherical), ctypes.c_bool(inverted), ctypes.c_int(idx_image), ctypes.c_int(idx_chain)) - -### Skyrmion configuration _Skyrmion = _spirit.Configuration_Skyrmion _Skyrmion.argtypes = [ctypes.c_void_p, ctypes.c_float, ctypes.c_float, ctypes.c_float, ctypes.c_bool, ctypes.c_bool, ctypes.c_bool, ctypes.POINTER(ctypes.c_float), ctypes.POINTER(ctypes.c_float), ctypes.c_float, ctypes.c_float, ctypes.c_bool, ctypes.c_int, ctypes.c_int] _Skyrmion.restype = None -def skyrmion(p_state, radius, order=1, phase=1, upDown=False, achiral=False, rightleft=False, +def skyrmion(p_state, radius, order=1, phase=1, up_down=False, achiral=False, right_left=False, pos=[0,0,0], border_rectangular=[-1,-1,-1], border_cylindrical=-1, border_spherical=-1, inverted=False, idx_image=-1, idx_chain=-1): + """Set a skyrmion configuration. + + - radius: the extent of the skyrmion, at which it points approximately upwards + - order: the number of twists along a circle cutting the skyrmion + - phase: 0 corresponds to a Neel skyrmion, -90 to a Bloch skyrmion + - up_down: if `True`, the z-orientation is inverted + - achiral: if `True`, the topological charge is inverted + - right_left: if `True`, the in-plane rotation is inverted + + The skyrmion only extends up to `radius`, meaning that `border_cylindrical` is + not usually necessary. + """ vec3 = ctypes.c_float * 3 _Skyrmion(ctypes.c_void_p(p_state), ctypes.c_float(radius), ctypes.c_float(order), ctypes.c_float(phase), ctypes.c_bool(upDown), ctypes.c_bool(achiral), @@ -101,7 +107,6 @@ def skyrmion(p_state, radius, order=1, phase=1, upDown=False, achiral=False, rig ctypes.c_float(border_cylindrical), ctypes.c_float(border_spherical), ctypes.c_bool(inverted), ctypes.c_int(idx_image), ctypes.c_int(idx_chain)) -### Hopfion configuration _Hopfion = _spirit.Configuration_Hopfion _Hopfion.argtypes = [ctypes.c_void_p, ctypes.c_float, ctypes.c_int, ctypes.POINTER(ctypes.c_float), ctypes.POINTER(ctypes.c_float), ctypes.c_float, ctypes.c_float, ctypes.c_bool, @@ -109,14 +114,19 @@ def skyrmion(p_state, radius, order=1, phase=1, upDown=False, achiral=False, rig _Hopfion.restype = None def hopfion(p_state, radius, order=1, pos=[0,0,0], border_rectangular=[-1,-1,-1], border_cylindrical=-1, border_spherical=-1, inverted=False, idx_image=-1, idx_chain=-1): + """Set a Hopfion configuration. + + - radius: the distance from the center to the center of the corresponding tubular isosurface + - order: TODO + + In contrast to the skyrmion, it extends over the whole allowed space. + """ vec3 = ctypes.c_float * 3 _Hopfion(ctypes.c_void_p(p_state), ctypes.c_float(radius), ctypes.c_int(order), vec3(*pos), vec3(*border_rectangular), ctypes.c_float(border_cylindrical), ctypes.c_float(border_spherical), ctypes.c_bool(inverted), ctypes.c_int(idx_image), ctypes.c_int(idx_chain)) - -### Spin Spiral configuration _SpinSpiral = _spirit.Configuration_SpinSpiral _SpinSpiral.argtypes = [ctypes.c_void_p, ctypes.c_char_p, ctypes.POINTER(ctypes.c_float), ctypes.POINTER(ctypes.c_float), ctypes.c_float, @@ -127,6 +137,14 @@ def hopfion(p_state, radius, order=1, pos=[0,0,0], border_rectangular=[-1,-1,-1] def spin_spiral(p_state, direction_type, q_vector, axis, theta, pos=[0,0,0], border_rectangular=[-1,-1,-1], border_cylindrical=-1, border_spherical=-1, inverted=False, idx_image=-1, idx_chain=-1): + """Set a spin spiral configuration. + + TODO: document parameters + - direction_type: + - q_vector: + - axis: + - theta: + """ vec3 = ctypes.c_float * 3 _SpinSpiral(ctypes.c_void_p(p_state), ctypes.c_char_p(direction_type.encode('utf-8')), vec3(*q_vector), vec3(*axis), ctypes.c_float(theta), vec3(*pos), @@ -134,8 +152,6 @@ def spin_spiral(p_state, direction_type, q_vector, axis, theta, pos=[0,0,0], ctypes.c_float(border_spherical), ctypes.c_bool(inverted), ctypes.c_int(idx_image), ctypes.c_int(idx_chain)) - -### Pin spins in a selected area _Set_Pinned = _spirit.Configuration_Set_Pinned _Set_Pinned.argtypes = [ctypes.c_void_p, ctypes.c_bool, ctypes.POINTER(ctypes.c_float), ctypes.POINTER(ctypes.c_float), ctypes.c_float, ctypes.c_float, ctypes.c_bool, @@ -143,13 +159,15 @@ def spin_spiral(p_state, direction_type, q_vector, axis, theta, pos=[0,0,0], _Set_Pinned.restype = None def set_pinned(p_state, pinned, pos=[0.0,0.0,0.0], border_rectangular=[-1.0,-1.0,-1.0], border_cylindrical=-1.0, border_spherical=-1.0, inverted=False, idx_image=-1, idx_chain=-1): + """Set whether the spins within the given region are pinned or not. + + If they are pinned, they are pinned to their current orientation. + """ vec3 = ctypes.c_float * 3 _Set_Pinned(ctypes.c_void_p(p_state), ctypes.c_bool(pinned), vec3(*pos), vec3(*border_rectangular), ctypes.c_float(border_cylindrical), ctypes.c_float(border_spherical), ctypes.c_bool(inverted), ctypes.c_int(idx_image), ctypes.c_int(idx_chain)) - -### Set atom types in a selected area _Set_Atom_Type = _spirit.Configuration_Set_Atom_Type _Set_Atom_Type.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.POINTER(ctypes.c_float), ctypes.POINTER(ctypes.c_float), ctypes.c_float, ctypes.c_float, ctypes.c_bool, @@ -157,6 +175,10 @@ def set_pinned(p_state, pinned, pos=[0.0,0.0,0.0], border_rectangular=[-1.0,-1.0 _Set_Atom_Type.restype = None def set_atom_type(p_state, atom_type=0, pos=[0.0,0.0,0.0], border_rectangular=[-1.0,-1.0,-1.0], border_cylindrical=-1.0, border_spherical=-1.0, inverted=False, idx_image=-1, idx_chain=-1): + """Set the type of the atoms in the given region (default: 0). + + This can be used e.g. to insert defects (-1). + """ vec3 = ctypes.c_float * 3 _Set_Atom_Type(ctypes.c_void_p(p_state), ctypes.c_int(atom_type), vec3(*pos), vec3(*border_rectangular), ctypes.c_float(border_cylindrical), ctypes.c_float(border_spherical), diff --git a/core/python/spirit/geometry.py b/core/python/spirit/geometry.py index ef43a9a95..ddbbc3167 100644 --- a/core/python/spirit/geometry.py +++ b/core/python/spirit/geometry.py @@ -31,130 +31,152 @@ ### ---------------------------------- Set ---------------------------------- -### Set the type of Bravais lattice. Can be e.g. "sc" or "bcc" _Set_Bravais_Lattice_Type = _spirit.Geometry_Set_Bravais_Lattice_Type _Set_Bravais_Lattice_Type.argtypes = [ctypes.c_void_p, ctypes.c_int] _Set_Bravais_Lattice_Type.restype = None def set_bravais_lattice_type(p_state, lattice_type, idx_image=-1, idx_chain=-1): + """Set the bravais vectors to a pre-defined lattice type: + + - sc: simple cubic + - bcc: body centered cubic + - fcc: face centered cubic + - hex2d: hexagonal (120deg) + - hed2d120: hexagonal (120deg) + - hex2d60: hexagonal (60deg) + """ _Set_Bravais_Lattice_Type(ctypes.c_void_p(p_state), ctypes.c_int(lattice_type)) -### Set number of cells in bravais lattice directions a, b, c _Set_N_Cells = _spirit.Geometry_Set_N_Cells _Set_N_Cells.argtypes = [ctypes.c_void_p, ctypes.POINTER(ctypes.c_int)] _Set_N_Cells.restype = None def set_n_cells(p_state, n_cells=[1, 1, 1], idx_image=-1, idx_chain=-1): + """Set the number of basis cells along the three bravais vectors.""" vec3 = ctypes.c_int * 3 _Set_N_Cells(ctypes.c_void_p(p_state), vec3(*n_cells)) -### Set magnetic moment globally _Set_mu_s = _spirit.Geometry_Set_mu_s _Set_mu_s.argtypes = [ctypes.c_void_p, ctypes.c_float, ctypes.c_int, ctypes.c_int] _Set_mu_s.restype = None def set_mu_s(p_state, mu_s, idx_image=-1, idx_chain=-1): + """Set the magnetic moment of all atoms.""" _Set_mu_s(ctypes.c_void_p(p_state), ctypes.c_float(mu_s), ctypes.c_int(idx_image), ctypes.c_int(idx_chain)) -### Set the types of the atoms in a basis cell _Set_Cell_Atom_Types = _spirit.Geometry_Set_Cell_Atom_Types _Set_Cell_Atom_Types.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.POINTER(ctypes.c_float)] _Set_Cell_Atom_Types.restype = None def set_cell_atom_types(p_state, atom_types, idx_image=-1, idx_chain=-1): + """Set the atom types of the atoms in the basis cell.""" n = len(atom_types) vec = ctypes.c_int * n _Set_Cell_Atom_Types(ctypes.c_void_p(p_state), ctypes.c_int(n), vec(*atom_types)) -### Set the bravais vectors _Set_Bravais_Vectors = _spirit.Geometry_Set_Bravais_Vectors _Set_Bravais_Vectors.argtypes = [ctypes.c_void_p, ctypes.POINTER(ctypes.c_float), ctypes.POINTER(ctypes.c_float), ctypes.POINTER(ctypes.c_float)] _Set_Bravais_Vectors.restype = None def set_bravais_vectors(p_state, ta=[1.0, 0.0, 0.0], tb=[0.0, 1.0, 0.0], tc=[0.0, 0.0, 1.0], idx_image=-1, idx_chain=-1): + """Manually specify the bravais vectors.""" vec3 = ctypes.c_float * 3 _Set_Bravais_Vectors(ctypes.c_void_p(p_state), vec3(ta), vec3(tb), vec3(tc)) -### Set the overall lattice constant _Set_Lattice_Constant = _spirit.Geometry_Set_Lattice_Constant _Set_Lattice_Constant.argtypes = [ctypes.c_void_p, ctypes.c_float] _Set_Lattice_Constant.restype = None def set_lattice_constant(p_state, lattice_constant, idx_image=-1, idx_chain=-1): + """Set the global lattice scaling constant.""" _Set_Lattice_Constant(p_state, ctypes.c_float(lattice_constant)) ### ---------------------------------- Get ---------------------------------- -### Get Bounds _Get_Bounds = _spirit.Geometry_Get_Bounds -_Get_Bounds.argtypes = [ctypes.c_void_p, ctypes.POINTER(ctypes.c_float), +_Get_Bounds.argtypes = [ctypes.c_void_p, ctypes.POINTER(ctypes.c_float), ctypes.POINTER(ctypes.c_float), ctypes.c_int, ctypes.c_int] _Get_Bounds.restype = None def get_bounds(p_state, idx_image=-1, idx_chain=-1): + """Get the bounds of the system in global coordinates. + + Returns two arrays of shape (3) containing minimum and maximum bounds respectively. + """ _min = (3*ctypes.c_float)() _max = (3*ctypes.c_float)() - _Get_Bounds(ctypes.c_void_p(p_state), _min, _max, + _Get_Bounds(ctypes.c_void_p(p_state), _min, _max, ctypes.c_int(idx_image), ctypes.c_int(idx_chain)) - return [_min[i] for i in range(3)], [_max[i] for i in range(3)] + return [_min[i] for i in range(3)], [_max[i] for i in range(3)] -### Get Center _Get_Center = _spirit.Geometry_Get_Center _Get_Center.argtypes = [ctypes.c_void_p, ctypes.POINTER(ctypes.c_float), ctypes.c_int, ctypes.c_int] _Get_Center.restype = None def get_center(p_state, idx_image=-1, idx_chain=-1): + """Get the center of the system in global coordinates. + + Returns an array of shape (3). + """ _center = (3*ctypes.c_float)() _Get_Center(ctypes.c_void_p(p_state), _center, ctypes.c_int(idx_image), ctypes.c_int(idx_chain)) return [_center[i] for i in range(3)] -### Get Bravais lattice type _Get_Bravais_Lattice_Type = _spirit.Geometry_Get_Bravais_Lattice_Type _Get_Bravais_Lattice_Type.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_int] _Get_Bravais_Lattice_Type.restype = ctypes.c_int def get_bravais_lattice_type(p_state, idx_image=-1, idx_chain=-1): - return int(_Get_Bravais_Lattice_Type(ctypes.c_void_p(p_state), ctypes.c_int(idx_image), + """Get the bravais lattice type corresponding to one of the integers defined above.""" + return int(_Get_Bravais_Lattice_Type(ctypes.c_void_p(p_state), ctypes.c_int(idx_image), ctypes.c_int(idx_chain))) -### Get Bravais vectors _Get_Bravais_Vectors = _spirit.Geometry_Get_Bravais_Vectors -_Get_Bravais_Vectors.argtypes = [ctypes.c_void_p, ctypes.POINTER(ctypes.c_float), - ctypes.POINTER(ctypes.c_float), ctypes.POINTER(ctypes.c_float), +_Get_Bravais_Vectors.argtypes = [ctypes.c_void_p, ctypes.POINTER(ctypes.c_float), + ctypes.POINTER(ctypes.c_float), ctypes.POINTER(ctypes.c_float), ctypes.c_int, ctypes.c_int] _Get_Bravais_Vectors.restype = None def get_bravais_vectors(p_state, idx_image=-1, idx_chain=-1): + """Get the bravais vectors. + + Returns three arrays of shape (3). + """ _a = (3*ctypes.c_float)() _b = (3*ctypes.c_float)() _c = (3*ctypes.c_float)() - _Get_Bravais_Vectors(ctypes.c_void_p(p_state), _a, _b, _c, + _Get_Bravais_Vectors(ctypes.c_void_p(p_state), _a, _b, _c, ctypes.c_int(idx_image), ctypes.c_int(idx_chain)) return [a for a in _a], [b for b in _b], [c for c in _c] - -### Get N Cells + _Get_N_Cells = _spirit.Geometry_Get_N_Cells _Get_N_Cells.argtypes = [ctypes.c_void_p, ctypes.POINTER(ctypes.c_int), ctypes.c_int, ctypes.c_int] _Get_N_Cells.restype = None def get_n_cells(p_state, idx_image=-1, idx_chain=-1): + """Get the number of basis cells along the three bravais vectors. + + Returns an array of shape (3). + """ n_cells = (3*ctypes.c_int)() _Get_N_Cells(ctypes.c_void_p(p_state), n_cells, ctypes.c_int(idx_image), ctypes.c_int(idx_chain)) return [n for n in n_cells] -### Get Translation Vectors _Get_Translation_Vectors = _spirit.Geometry_Get_Translation_Vectors -_Get_Translation_Vectors.argtypes = [ctypes.c_void_p, ctypes.POINTER(ctypes.c_float), - ctypes.POINTER(ctypes.c_float), ctypes.POINTER(ctypes.c_float), +_Get_Translation_Vectors.argtypes = [ctypes.c_void_p, ctypes.POINTER(ctypes.c_float), + ctypes.POINTER(ctypes.c_float), ctypes.POINTER(ctypes.c_float), ctypes.c_int, ctypes.c_int] _Get_Translation_Vectors.restype = None def get_translation_vectors(p_state, idx_image=-1, idx_chain=-1): + """Get the translation vectors in global coordinates. + + Returns three arrays of shape (3). + """ ta = (3*ctypes.c_float)() tb = (3*ctypes.c_float)() tc = (3*ctypes.c_float)() - _Get_Translation_Vectors(ctypes.c_void_p(p_state), ta, tb, tc, + _Get_Translation_Vectors(ctypes.c_void_p(p_state), ta, tb, tc, ctypes.c_int(idx_image), ctypes.c_int(idx_chain)) return [a for a in ta], [b for b in tb], [c for c in tc] -### Get Translation Vectors _Get_Dimensionality = _spirit.Geometry_Get_Dimensionality _Get_Dimensionality.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_int] _Get_Dimensionality.restype = ctypes.c_int def get_dimensionality(p_state, idx_image=-1, idx_chain=-1): - return int(_Get_Dimensionality(ctypes.c_void_p(p_state), ctypes.c_int(idx_image), - ctypes.c_int(idx_chain))) + """Get the dimensionality of the geometry.""" + return int(_Get_Dimensionality(ctypes.c_void_p(p_state), ctypes.c_int(idx_image), ctypes.c_int(idx_chain))) ### Get Pointer to Spin Positions # NOTE: Changing the values of the array_view one can alter the value of the data of the state @@ -162,26 +184,39 @@ def get_dimensionality(p_state, idx_image=-1, idx_chain=-1): _Get_Positions.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_int] _Get_Positions.restype = ctypes.POINTER(scalar) def get_positions(p_state, idx_image=-1, idx_chain=-1): + """Returns a `numpy.array_view` of shape (NOS, 3) with the components of each spins position. + + Changing the contents of this array_view will have direct effect on the state and should not be done. + """ nos = system.get_nos(p_state, idx_image, idx_chain) ArrayType = scalar*3*nos - Data = _Get_Positions(ctypes.c_void_p(p_state), - ctypes.c_int(idx_image), ctypes.c_int(idx_chain)) + Data = _Get_Positions(ctypes.c_void_p(p_state), ctypes.c_int(idx_image), ctypes.c_int(idx_chain)) array_pointer = ctypes.cast(Data, ctypes.POINTER(ArrayType)) array = np.frombuffer(array_pointer.contents, dtype=scalar) array_view = array.view() array_view.shape = (nos, 3) return array_view +_Get_N_Cell_Atoms = _spirit.Geometry_Get_N_Cell_Atoms +_Get_N_Cell_Atoms.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_int] +_Get_N_Cell_Atoms.restype = ctypes.c_int +def get_n_cell_atoms(p_state, idx_image=-1, idx_chain=-1): + """Get the number of atoms in the basis cell.""" + return int(_Get_N_Cell_Atoms(ctypes.c_void_p(p_state), ctypes.c_int(idx_image), ctypes.c_int(idx_chain))) + ### Get Pointer to atom types # NOTE: Changing the values of the array_view one can alter the value of the data of the state _Get_Atom_Types = _spirit.Geometry_Get_Atom_Types _Get_Atom_Types.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_int] _Get_Atom_Types.restype = ctypes.POINTER(ctypes.c_int) def get_atom_types(p_state, idx_image=-1, idx_chain=-1): + """Get the types of all atoms as a `numpy.array_view` of shape (NOS). + + If e.g. disorder is activated, this allows to view and manipulate the types of individual atoms. + """ nos = system.get_nos(p_state, idx_image, idx_chain) ArrayType = ctypes.c_int*nos - Data = _Get_Atom_Types(ctypes.c_void_p(p_state), - ctypes.c_int(idx_image), ctypes.c_int(idx_chain)) + Data = _Get_Atom_Types(ctypes.c_void_p(p_state), ctypes.c_int(idx_image), ctypes.c_int(idx_chain)) array_pointer = ctypes.cast(Data, ctypes.POINTER(ArrayType)) array = np.frombuffer(array_pointer.contents, dtype=ctypes.c_int) array_view = array.view() diff --git a/core/python/spirit/hamiltonian.py b/core/python/spirit/hamiltonian.py index 28acdfe8c..b7d116a76 100644 --- a/core/python/spirit/hamiltonian.py +++ b/core/python/spirit/hamiltonian.py @@ -13,114 +13,141 @@ ### DM vector chirality CHIRALITY_BLOCH = 1 +"""DMI Bloch chirality type for neighbour shells""" + CHIRALITY_NEEL = 2 +"""DMI Neel chirality type for neighbour shells""" + CHIRALITY_BLOCH_INVERSE = -1 +"""DMI Bloch chirality type for neighbour shells with opposite sign""" + CHIRALITY_NEEL_INVERSE = -2 +"""DMI Neel chirality type for neighbour shells with opposite sign""" ### DDI METHOD DDI_METHOD_NONE = 0 +"""Dipole-dipole interaction: do not calculate""" + DDI_METHOD_FFT = 1 +"""Dipole-dipole interaction: use FFT convolutions""" + DDI_METHOD_FMM = 2 +"""Dipole-dipole interaction: use a fast multipole method (FMM)""" + DDI_METHOD_CUTOFF = 3 +"""Dipole-dipole interaction: use a direct summation with a cutoff radius""" ### ---------------------------------- Set ---------------------------------- -### Set boundary conditions _Set_Boundary_Conditions = _spirit.Hamiltonian_Set_Boundary_Conditions _Set_Boundary_Conditions.argtypes = [ctypes.c_void_p, ctypes.POINTER(ctypes.c_bool), ctypes.c_int, ctypes.c_int] _Set_Boundary_Conditions.restype = None def set_boundary_conditions(p_state, boundaries, idx_image=-1, idx_chain=-1): + """Set the boundary conditions along the translation directions [a, b, c]. + + 0 = open, 1 = periodical + """ bool3 = ctypes.c_bool * 3 _Set_Boundary_Conditions(ctypes.c_void_p(p_state), bool3(*boundaries), ctypes.c_int(idx_image), ctypes.c_int(idx_chain)) -### Set global external magnetic field _Set_Field = _spirit.Hamiltonian_Set_Field _Set_Field.argtypes = [ctypes.c_void_p, ctypes.c_float, ctypes.POINTER(ctypes.c_float), ctypes.c_int, ctypes.c_int] _Set_Field.restype = None def set_field(p_state, magnitude, direction, idx_image=-1, idx_chain=-1): + """Set the (homogeneous) external magnetic field.""" vec3 = ctypes.c_float * 3 _Set_Field(ctypes.c_void_p(p_state), ctypes.c_float(magnitude), vec3(*direction), ctypes.c_int(idx_image), ctypes.c_int(idx_chain)) -### Set global anisotropy _Set_Anisotropy = _spirit.Hamiltonian_Set_Anisotropy _Set_Anisotropy.argtypes = [ctypes.c_void_p, ctypes.c_float, ctypes.POINTER(ctypes.c_float), ctypes.c_int, ctypes.c_int] _Set_Anisotropy.restype = None def set_anisotropy(p_state, magnitude, direction, idx_image=-1, idx_chain=-1): + """Set the (homogeneous) magnetocrystalline anisotropy.""" vec3 = ctypes.c_float * 3 - _Set_Anisotropy(ctypes.c_void_p(p_state), ctypes.c_float(magnitude), vec3(*direction), + _Set_Anisotropy(ctypes.c_void_p(p_state), ctypes.c_float(magnitude), vec3(*direction), ctypes.c_int(idx_image), ctypes.c_int(idx_chain)) -### Set exchange interaction in form of neighbour shells _Set_Exchange = _spirit.Hamiltonian_Set_Exchange _Set_Exchange.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.POINTER(ctypes.c_float), ctypes.c_int, ctypes.c_int] _Set_Exchange.restype = None def set_exchange(p_state, n_shells, J_ij, idx_image=-1, idx_chain=-1): + """Set the Exchange interaction in terms of neighbour shells.""" vec = ctypes.c_float * n_shells _Set_Exchange(ctypes.c_void_p(p_state), ctypes.c_int(n_shells), vec(*J_ij), ctypes.c_int(idx_image), ctypes.c_int(idx_chain)) -### Set Dzyaloshinskii-Moriya interaction in form of neighbour shells _Set_DMI = _spirit.Hamiltonian_Set_DMI _Set_DMI.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.POINTER(ctypes.c_float), ctypes.c_int, ctypes.c_int, ctypes.c_int] _Set_DMI.restype = None def set_dmi(p_state, n_shells, D_ij, chirality=CHIRALITY_BLOCH, idx_image=-1, idx_chain=-1): + """Set the Dzyaloshinskii-Moriya interaction in terms of neighbour shells.""" vec = ctypes.c_float * n_shells _Set_DMI(ctypes.c_void_p(p_state), ctypes.c_int(n_shells), vec(*D_ij), ctypes.c_int(chirality), ctypes.c_int(idx_image), ctypes.c_int(idx_chain)) -### Set dipole-dipole interaction in form of exact calculation within a cutoff radius _Set_DDI = _spirit.Hamiltonian_Set_DDI _Set_DDI.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.POINTER(ctypes.c_int), ctypes.c_float, ctypes.c_int, ctypes.c_int] _Set_DDI.restype = None def set_ddi(p_state, ddi_method, n_periodic_images=[4,4,4], radius=0.0, idx_image=-1, idx_chain=-1): + """Set the dipolar interaction calculation method. + + - ddi_method -- one of the integers defined above + - n_periodic_images -- the number of periodical images in the three translation directions, taken into account + when boundaries in the corresponding direction are periodical + - radius -- the cutoff radius for the direct summation method + """ vec3 = ctypes.c_int * 3 _Set_DDI(ctypes.c_void_p(p_state), ctypes.c_int(ddi_method) , vec3(*n_periodic_images), ctypes.c_float(radius), ctypes.c_int(idx_image), ctypes.c_int(idx_chain)) ### ---------------------------------- Get ---------------------------------- -### Get the name of the Hamiltonian _Get_Name = _spirit.Hamiltonian_Get_Name _Get_Name.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_int] _Get_Name.restype = ctypes.c_char_p def get_name(p_state, idx_image=-1, idx_chain=-1): + """Returns a string containing the name of the Hamiltonian currently in use.""" return str(_Get_Name(ctypes.c_void_p(p_state), ctypes.c_int(idx_image), ctypes.c_int(idx_chain))) -### Get the boundary conditions [a, b, c] _Get_Boundary_Conditions = _spirit.Hamiltonian_Get_Boundary_Conditions _Get_Boundary_Conditions.argtypes = [ctypes.c_void_p, ctypes.POINTER(ctypes.c_bool), ctypes.c_int, ctypes.c_int] _Get_Boundary_Conditions.restype = None def get_boundary_conditions(p_state, idx_image=-1, idx_chain=-1): + """Returns an array of shape (3) containing the boundary conditions in the + three translation directions [a, b, c] of the lattice. + """ boundaries = (3*ctypes.c_bool)() _Get_Boundary_Conditions(ctypes.c_void_p(p_state), boundaries, ctypes.c_int(idx_image), ctypes.c_int(idx_chain)) return [bc for bc in boundaries] -### Get the global external magnetic field _Get_Field = _spirit.Hamiltonian_Get_Field _Get_Field.argtypes = [ctypes.c_void_p, ctypes.POINTER(ctypes.c_float), ctypes.POINTER(ctypes.c_float), ctypes.c_int, ctypes.c_int] _Get_Field.restype = None def get_field(p_state, idx_image=-1, idx_chain=-1): + """Returns the magnitude and an array of shape (3) containing the direction of + the external magnetic field. + """ magnitude = (1*ctypes.c_float)() normal = (3*ctypes.c_float)() _Get_Field(ctypes.c_void_p(p_state), magnitude, normal, ctypes.c_int(idx_image), ctypes.c_int(idx_chain)) return float(magnitude), [n for n in normal] -### Get dipole-dipole interaction cutoff radius _Get_DDI = _spirit.Hamiltonian_Get_DDI _Get_DDI.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_int] _Get_DDI.restype = ctypes.c_float def get_ddi(p_state, idx_image=-1, idx_chain=-1): - return float(_Get_DDI(ctypes.c_void_p(p_state), ctypes.c_int(idx_image), + """Returns the cutoff radius of the DDI.""" + return float(_Get_DDI(ctypes.c_void_p(p_state), ctypes.c_int(idx_image), ctypes.c_int(idx_chain))) \ No newline at end of file diff --git a/core/python/spirit/io.py b/core/python/spirit/io.py index 8c51c20f1..a916f4120 100644 --- a/core/python/spirit/io.py +++ b/core/python/spirit/io.py @@ -3,6 +3,12 @@ -------------------- Read and write spin configurations, chains or eigenmodes. +Vectorfields are generally written in the [OOMMF vector field (OVF) file format](http://math.nist.gov/oommf/doc/userguide12a5/userguide/OVF_2.0_format.html). + +Note that, when reading an image or chain from file, the file will automatically be tested for an OVF header. +If it cannot be identified as OVF, it will be tried to be read as three plain text columns (Sx Sy Sz). + +Note also, IO is still being re-written and only OVF will be supported as output format. """ import spirit.spiritlib as spiritlib @@ -27,11 +33,9 @@ FILEFORMAT_OVF_CSV = 4 """OVF text format with comma-separated columns""" -### Get the number of images in a file _N_Images_In_File = _spirit.IO_N_Images_In_File _N_Images_In_File.argtypes = [ctypes.c_void_p, ctypes.c_char_p, ctypes.c_int, ctypes.c_int] _N_Images_In_File.restype = ctypes.c_int -"""test docstring above n_images_in_file""" def n_images_in_file(p_state, filename, idx_image_inchain=-1, idx_chain=-1): """Returns the number of segments or images in a given file. @@ -42,28 +46,25 @@ def n_images_in_file(p_state, filename, idx_image_inchain=-1, idx_chain=-1): return int(_N_Images_In_File(ctypes.c_void_p(p_state), ctypes.c_char_p(filename.encode('utf-8')), ctypes.c_int(idx_image_inchain), ctypes.c_int(idx_chain))) -### Read an image from disk _Image_Read = _spirit.IO_Image_Read _Image_Read.argtypes = [ctypes.c_void_p, ctypes.c_char_p, ctypes.c_int, ctypes.c_int, ctypes.c_int] _Image_Read.restype = None -"""test docstring above image_read""" def image_read(p_state, filename, idx_image_infile=0, idx_image_inchain=-1, idx_chain=-1): - """Attempts to read a spin configuration from a file into an image of the chain. + """Attempt to read a spin configuration from a file into an image of the chain. Arguments: p_state -- state pointer filename -- the name of the file to read Keyword arguments: - idx_image_infile -- the index of the image in the file which should be read in - idx_image_inchain -- the index of the image in the chain into which the data should be read + idx_image_infile -- the index of the image in the file which should be read in (default: 0) + idx_image_inchain -- the index of the image in the chain into which the data should be read (default: active image) """ _Image_Read(ctypes.c_void_p(p_state), ctypes.c_char_p(filename.encode('utf-8')), ctypes.c_int(idx_image_infile), ctypes.c_int(idx_image_inchain), ctypes.c_int(idx_chain)) -### Write an image to disk _Image_Write = _spirit.IO_Image_Write _Image_Write.argtypes = [ctypes.c_void_p, ctypes.c_char_p, ctypes.c_int, ctypes.c_char_p, ctypes.c_int, ctypes.c_int] @@ -78,13 +79,12 @@ def image_write(p_state, filename, fileformat=FILEFORMAT_OVF_TEXT, comment="", i Keyword arguments: fileformat -- the format in which to write the data (default: OVF text) comment -- a comment string to be inserted in the header (default: empty) - idx_image -- the index of the image to be written to the file + idx_image -- the index of the image to be written to the file (default: active image) """ _Image_Write(ctypes.c_void_p(p_state), ctypes.c_char_p(filename.encode('utf-8')), ctypes.c_int(fileformat), ctypes.c_char_p(comment.encode('utf-8')), ctypes.c_int(idx_image), ctypes.c_int(idx_chain)) -### Append an image to an existing file _Image_Append = _spirit.IO_Image_Append _Image_Append.argtypes = [ctypes.c_void_p, ctypes.c_char_p, ctypes.c_int, ctypes.c_char_p, ctypes.c_int, ctypes.c_int] @@ -101,44 +101,76 @@ def image_append(p_state, filename, fileformat=FILEFORMAT_OVF_TEXT, comment="", Keyword arguments: fileformat -- the format in which to write the data (default: OVF text) comment -- a comment string to be inserted in the header (default: empty) - idx_image -- the index of the image to be written to the file + idx_image -- the index of the image to be written to the file (default: active image) """ _Image_Append(ctypes.c_void_p(p_state), ctypes.c_char_p(filename.encode('utf-8')), ctypes.c_int(fileformat), ctypes.c_char_p(filename.encode('utf-8')), ctypes.c_int(idx_image), ctypes.c_int(idx_chain)) -### Read a chain of images from disk _Chain_Read = _spirit.IO_Chain_Read _Chain_Read.argtypes = [ctypes.c_void_p, ctypes.c_char_p, ctypes.c_int, ctypes.c_int, ctypes.c_int, ctypes.c_int] _Chain_Read.restype = None -def chain_read(p_state, filename, starting_image=-1, ending_image=-1, insert_idx=-1, - idx_chain=-1): +def chain_read(p_state, filename, starting_image=0, ending_image=0, insert_idx=-1, idx_chain=-1): + """Attempt to read a chain of images from a given file. + + Arguments: + p_state -- state pointer + filename -- the name of the file to read + + Keyword arguments: + starting_image -- the index within the file at which to start reading (default: 0) + ending_image -- the index within the file at which to stop reading (default: 0) + insert_idx -- the index within the chain at which to start placing the images (default: active image) + + Images of the chain will be overwritten with what is read from the file. + If the chain is not long enough for the number of images to be read, it is automatically set to the + right length. + """ _Chain_Read(ctypes.c_void_p(p_state), ctypes.c_char_p(filename.encode('utf-8')), ctypes.c_int(starting_image), ctypes.c_int(ending_image), ctypes.c_int(insert_idx), ctypes.c_int(idx_chain)) -### Write a chain of images to disk _Chain_Write = _spirit.IO_Chain_Write _Chain_Write.argtypes = [ctypes.c_void_p, ctypes.c_char_p, ctypes.c_int, ctypes.c_char_p, ctypes.c_int] _Chain_Write.restype = None -def chain_write(p_state, filename, fileformat=FILEFORMAT_OVF_TEXT, comment=" ", idx_chain=-1): +def chain_write(p_state, filename, fileformat=FILEFORMAT_OVF_TEXT, comment="", idx_chain=-1): + """Write a chain of images to a file. + + Arguments: + p_state -- state pointer + filename -- the name of the file to write + + Keyword arguments: + fileformat -- the format in which to write the data (default: OVF text) + comment -- a comment string to be inserted in the header (default: empty) + """ _Chain_Write(ctypes.c_void_p(p_state), ctypes.c_char_p(filename.encode('utf-8')), ctypes.c_int(fileformat), ctypes.c_char_p(comment.encode('utf-8')), ctypes.c_int(idx_chain)) -### Append a chain of images to disk _Chain_Append = _spirit.IO_Chain_Append _Chain_Append.argtypes = [ctypes.c_void_p, ctypes.c_char_p, ctypes.c_int, ctypes.c_char_p, ctypes.c_int] _Chain_Append.restype = None -def chain_append(p_state, filename, fileformat=FILEFORMAT_OVF_TEXT, comment=" ", idx_chain=-1): +def chain_append(p_state, filename, fileformat=FILEFORMAT_OVF_TEXT, comment="", idx_chain=-1): + """Append a chain of images to a given file. + + If the file does not exist, it is created. + + Arguments: + p_state -- state pointer + filename -- the name of the file to append to + + Keyword arguments: + fileformat -- the format in which to write the data (default: OVF text) + comment -- a comment string to be inserted in the header (default: empty) + """ _Chain_Append(ctypes.c_void_p(p_state), ctypes.c_char_p(filename.encode('utf-8')), ctypes.c_int(fileformat), ctypes.c_char_p(comment.encode('utf-8')), ctypes.c_int(idx_chain)) -### Read eigenmodes from disk _Eigenmodes_Read = _spirit.IO_Eigenmodes_Read _Eigenmodes_Read.argtypes = [ctypes.c_void_p, ctypes.c_char_p, ctypes.c_int, ctypes.c_int, ctypes.c_int] @@ -149,7 +181,6 @@ def eigenmodes_read(p_state, filename, fileformat=FILEFORMAT_OVF_TEXT, idx_image ctypes.c_int(fileformat), ctypes.c_int(idx_image_inchain), ctypes.c_int(idx_chain)) -### Write eigenmodes to disk _Eigenmodes_Write = _spirit.IO_Eigenmodes_Write _Eigenmodes_Write.argtypes = [ctypes.c_void_p, ctypes.c_char_p, ctypes.c_int, ctypes.c_char_p, ctypes.c_int, ctypes.c_int] diff --git a/core/python/spirit/log.py b/core/python/spirit/log.py index 939e65af9..6e02d5add 100644 --- a/core/python/spirit/log.py +++ b/core/python/spirit/log.py @@ -9,6 +9,7 @@ ### Load Library _spirit = spiritlib.load_spirit_library() +# Log levels LEVEL_ALL = 0 LEVEL_SEVERE = 1 LEVEL_ERROR = 2 @@ -17,6 +18,7 @@ LEVEL_INFO = 5 LEVEL_DEBUG = 6 +# Log message senders SENDER_ALL = 0 SENDER_IO = 1 SENDER_GNEB = 2 @@ -26,95 +28,111 @@ SENDER_API = 6 SENDER_UI = 7 -### Send a Log message _Send = _spirit.Log_Send -_Send.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_int, ctypes.c_char_p, +_Send.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_int, ctypes.c_char_p, ctypes.c_int, ctypes.c_int] _Send.restype = None def send(p_state, level, sender, message, idx_image=-1, idx_chain=-1): - _Send(ctypes.c_void_p(p_state), ctypes.c_int(level), ctypes.c_int(sender), + """Add a message to the log. + + - level: see integers defined above. The message may be printed to the console and/or written + to the log file, depending on the current log parameters + - sender: see integers defined above. Used to distinguish context + - message: a string which to log + - idx_image: can be used to specify to which image the message relates (default: active image) + """ + _Send(ctypes.c_void_p(p_state), ctypes.c_int(level), ctypes.c_int(sender), ctypes.c_char_p(message.encode('utf-8')), ctypes.c_int(idx_image), ctypes.c_int(idx_chain)) -### Append Log to file _Append = _spirit.Log_Append _Append.argtypes = [ctypes.c_void_p] _Append.restype = None def append(p_state): + """Force the appending of new messages to the log file.""" _Append(ctypes.c_void_p(p_state)) -### Get number of Log entries _Get_N_Entries = _spirit.Log_Get_N_Entries _Get_N_Entries.argtypes = [ctypes.c_void_p] _Get_N_Entries.restype = ctypes.c_int def get_n_entries(p_state): + """Returns the number of Log entries.""" return int(_Get_N_Entries(ctypes.c_void_p(p_state))) -### Get number of error messages _Get_N_Errors = _spirit.Log_Get_N_Errors _Get_N_Errors.argtypes = [ctypes.c_void_p] _Get_N_Errors.restype = ctypes.c_int def get_n_errors(p_state): + """Returns the number of error messages that have been logged.""" return int(_Get_N_Errors(ctypes.c_void_p(p_state))) -### Get number of warning messages _Get_N_Warnings = _spirit.Log_Get_N_Warnings _Get_N_Warnings.argtypes = [ctypes.c_void_p] _Get_N_Warnings.restype = ctypes.c_int def get_n_warnings(p_state): + """Returns the number of warning messages that have been logged.""" return int(_Get_N_Warnings(ctypes.c_void_p(p_state))) -### Set the tag in front of the Log file _Set_Output_File_Tag = _spirit.Log_Set_Output_File_Tag _Set_Output_File_Tag.argtypes = [ctypes.c_void_p, ctypes.c_char_p] _Set_Output_File_Tag.restype = None def set_output_file_tag(p_state, tag): + """Set the tagging string which is placed in front of the log file. + + If "