Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Core: new Python bindings wrapper. #562

Draft
wants to merge 1 commit into
base: develop
Choose a base branch
from
Draft

Conversation

GPMueller
Copy link
Member

@GPMueller GPMueller commented Apr 5, 2020

Note: this API requires Python3

A set of classes to provide a more pythonic API.
This class-based API should not be used in parallel with the functional API, as it could lead to unintuitive behaviour and therefore bugs.

TODO:

  • state
  • log
  • io
  • eigenmodes/ema
  • geometry
  • hamiltonian
  • reaction coordinates, interpolated E and Rx
  • docstrings for enums, classes and methods

Usage examples:

import os
import sys

# spirit_py_dir = os.path.dirname(os.path.realpath(__file__))
spirit_py_dir = os.path.abspath(os.path.join(os.path.dirname( __file__ ), ".."))
sys.path.insert(0, spirit_py_dir)

from spirit import constants
from spirit import version
from spirit.wrapper import State, SolverKind, LogLevel

if __name__ == '__main__':
    state = State(configfile="input/input.cfg")

    # Set some logging parameters
    state.log.console_level = LogLevel.info
    state.log.output_file_tag = 'new_state'
    state.log.output_folder = 'output'
    # print("level", state.log.console_level)

    # Set the orientations by hand
    spins = state.active_image.directions
    spins[:] = [0, 0, 1]
    spins.shape = (20, 20, 1, 3)
    spins[48:52, 48:52, :] = [0, 0, -1]
    # Use a pre-built setter
    state.systems[0].set_configuration.skyrmion(r=10.0)

    state.active_image.write_file("input/testimage.ovf")

    # The chain is easily resized
    state.systems.resize(10)
    # Also by list manipulations
    state.systems[9].set_configuration.plus_z()
    state.systems.append(state.systems[9])

    state.systems.write_file("input/testchain_first.ovf")

    # Parameters can be accessed through the systems:
    state.systems[2].parameters.llg.dt = 0.01
    # Groups of parameters can be set from a dict:
    for image in state.systems:
        # image.parameters.llg.dt = 0.001
        # image.parameters.llg.output_tag = "new_state"
        image.parameters.llg.set({
            'dt': 0.001,
            'output_tag': 'new_state' })

    # Chain-wide parameters are accessed through state.parameters
    # state.parameters.gneb.spring_force = 0.5
    state.parameters.gneb.set(
        {
            'dt': 0.001,
            'spring_force': 0.5,
            'output_tag': 'new_state'
        })

    # Logging is easy, by default messages go to 'All'
    state.log(">>>>>> Message to all")
    state.log(">>>>>> Error message", level=LogLevel.error)
    if state.log.n_errors > 0:
        state.log("this is intolerable!", level=LogLevel.severe)

    # calc = state.calculate.gneb(n_iterations=100000)
    # calc.start()

    # For pre-defined output etc, use:
    # state.calculate.llg(iterations=100)
    # To customise what happens after each iteration, use:
    # for i in state.calculation_llg(0, iterations=100):
    #     print(f'iteration {i}')
    #     if i > 10: break

    # If you call a calculation, it is executed immediately
    # state.calculation_llg()
    # You can also assign a calculation and use it later
    # calc = state.systems[0].calculation.llg(n_iterations=100)
    # # calc.start() # Maybe you want to do this asynchronously
    # # calc.stop()  # And stop it asynchronously on some event
    # calc() # Or you run it like so
    # # You can also iterate over a calculation manually
    # for i in state.calculation_llg(n_iterations=100):
    #     print(f'iteration {i}')
    # for i in calc:
    #     print(f'iteration {i}')
    #     if i >= 10: break

    state.systems[0].calculation.llg(solver=SolverKind.sib, n_iterations=1000000).start()
    # for i in state.systems[0].calculation.llg(solver=SolverKind.sib):
    #     if i >= 10: break
    state.systems[-1].calculation.llg(solver=SolverKind.vp, n_iterations=200).start()
    state.systems.interpolate()

    state.systems.write_file("input/testchain_second.ovf")

    state.calculation.gneb(solver=SolverKind.vp, n_iterations=200).start()

    state.systems.write_file("input/testchain_relaxed.ovf")

    state.log(f'Topological charge of first image: {state.systems[0].topological_charge()}')

    idx_image_minimum = 0
    idx_image_sp = 10
    htst_result = state.calculation.htst(idx_image_minimum, idx_image_sp, n_eigenmodes_keep=-1)
    state.log("------------------------")
    state.log(f"exponent   = {htst_result.temperature_exponent}")
    state.log(f"volume_min = {htst_result.volume_min}")
    state.log(f"volume_sp  = {htst_result.volume_sp}")
    eigval_min = htst_result.eigenvalues_min
    eigvec_min = htst_result.eigenvectors_min
    eigval_sp = htst_result.eigenvalues_sp
    eigvec_sp = htst_result.eigenvectors_sp
    velocities = htst_result.velocities

    print(eigval_min)
    print(eigvec_min)

A set of classes to provide a more pythonic API.
@coveralls
Copy link

Coverage Status

Coverage remained the same at 79.423% when pulling 0c3c994 on feature-pythonic-api into 55cc299 on develop.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants