Skip to content

Commit

Permalink
API: Implemented an easy way to get basic information about a simulat…
Browse files Browse the repository at this point in the history
…ion run via the API.

Previously one could only get this information by querying from a concurrent thread.
The `Simulation_XXX_Start` methods now take a pointer to a `Simulation_Run_Info` object that contains the following information
 - the total walltime
 - the maximum torque norm
 - the total number of iterations
 - the total iterations per second

In the python API the `simulation_run_info` object is returned by the `simulation.start` method.
  • Loading branch information
Moritz Sallermann committed Dec 8, 2021
1 parent 7c1e2e2 commit 57486d7
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 53 deletions.
35 changes: 19 additions & 16 deletions core/include/Spirit/Simulation.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ struct State;

/*
Simulation
====================================================================
//====================================================================
```C
#include "Spirit/Simulation.h"
Expand Down Expand Up @@ -53,35 +53,38 @@ Note that the VP and LBFGS Solvers are only meant for direct minimization and no
// `Solver_VP_OSO`: Verlet-like velocity projection, exponential transform
#define Solver_VP_OSO 7

struct Simulation_Run_Info
{
int total_iterations = 0;
int total_walltime = 0;
float total_ips = 0;
float max_torque = 0;
};

/*
Start or stop a simulation
--------------------------------------------------------------------
*/

// Monte Carlo
PREFIX void Simulation_MC_Start(
State * state, int n_iterations = -1, int n_iterations_log = -1, bool singleshot = false, int idx_image = -1,
int idx_chain = -1 ) SUFFIX;
PREFIX void Simulation_MC_Start(State *state, int n_iterations=-1, int n_iterations_log=-1,
bool singleshot=false, Simulation_Run_Info * info = NULL, int idx_image=-1, int idx_chain=-1) SUFFIX;

// Landau-Lifshitz-Gilbert dynamics and energy minimisation
PREFIX void Simulation_LLG_Start(
State * state, int solver_type, int n_iterations = -1, int n_iterations_log = -1, bool singleshot = false,
int idx_image = -1, int idx_chain = -1 ) SUFFIX;
PREFIX void Simulation_LLG_Start(State *state, int solver_type, int n_iterations=-1, int n_iterations_log=-1,
bool singleshot=false, Simulation_Run_Info * info = NULL, int idx_image=-1, int idx_chain=-1) SUFFIX;

// Geodesic nudged elastic band method
PREFIX void Simulation_GNEB_Start(
State * state, int solver_type, int n_iterations = -1, int n_iterations_log = -1, bool singleshot = false,
int idx_chain = -1 ) SUFFIX;
PREFIX void Simulation_GNEB_Start(State *state, int solver_type, int n_iterations=-1, int n_iterations_log=-1,
bool singleshot=false, Simulation_Run_Info * info = NULL, int idx_chain=-1) SUFFIX;

// Minimum mode following method
PREFIX void Simulation_MMF_Start(
State * state, int solver_type, int n_iterations = -1, int n_iterations_log = -1, bool singleshot = false,
int idx_image = -1, int idx_chain = -1 ) SUFFIX;
PREFIX void Simulation_MMF_Start(State *state, int solver_type, int n_iterations=-1, int n_iterations_log=-1,
bool singleshot=false, Simulation_Run_Info * info = NULL, int idx_image=-1, int idx_chain=-1) SUFFIX;

// Eigenmode analysis
PREFIX void Simulation_EMA_Start(
State * state, int n_iterations = -1, int n_iterations_log = -1, bool singleshot = false, int idx_image = -1,
int idx_chain = -1 ) SUFFIX;
PREFIX void Simulation_EMA_Start(State *state, int n_iterations=-1, int n_iterations_log=-1,
bool singleshot=false, Simulation_Run_Info * info = NULL, int idx_image=-1, int idx_chain=-1) SUFFIX;

/*
Single iteration of a Method
Expand Down
28 changes: 21 additions & 7 deletions core/python/spirit/simulation.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
"""
Simulation
====================
This module of Spirit is used to run and monitor iterative calculation methods.
Expand Down Expand Up @@ -88,32 +87,39 @@
of images corresponding to the movement of the system under the mode.
"""

class simulation_run_info(ctypes.Structure):
_fields_ = [
("total_iterations", ctypes.c_int),
("total_walltime", ctypes.c_int),
("total_ips", ctypes.c_float),
("max_torque", ctypes.c_float)
]

### ----- Start methods
### MC
_MC_Start = _spirit.Simulation_MC_Start
_MC_Start.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_int,
ctypes.c_bool, ctypes.c_int, ctypes.c_int]
ctypes.c_bool, ctypes.POINTER(simulation_run_info), ctypes.c_int, ctypes.c_int]
_MC_Start.restype = None
### LLG
_LLG_Start = _spirit.Simulation_LLG_Start
_LLG_Start.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_int, ctypes.c_int,
ctypes.c_bool, ctypes.c_int, ctypes.c_int]
ctypes.c_bool, ctypes.POINTER(simulation_run_info), ctypes.c_int, ctypes.c_int]
_LLG_Start.restype = None
### GNEB
_GNEB_Start = _spirit.Simulation_GNEB_Start
_GNEB_Start.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_int,
ctypes.c_int, ctypes.c_bool, ctypes.c_int]
ctypes.c_int, ctypes.c_bool, ctypes.POINTER(simulation_run_info), ctypes.c_int]
_GNEB_Start.restype = None
### MMF
_MMF_Start = _spirit.Simulation_MMF_Start
_MMF_Start.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_int, ctypes.c_int,
ctypes.c_bool, ctypes.c_int, ctypes.c_int]
ctypes.c_bool, ctypes.POINTER(simulation_run_info), ctypes.c_int, ctypes.c_int]
_MMF_Start.restype = None
### EMA
_EMA_Start = _spirit.Simulation_EMA_Start
_EMA_Start.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_int,
ctypes.c_bool, ctypes.c_int, ctypes.c_int]
ctypes.c_bool, ctypes.POINTER(simulation_run_info), ctypes.c_int, ctypes.c_int]
_EMA_Start.restype = None
### ----- Wrapper
def start(p_state, method_type, solver_type=None, n_iterations=-1, n_iterations_log=-1,
Expand All @@ -128,37 +134,45 @@ def start(p_state, method_type, solver_type=None, n_iterations=-1, n_iterations_
- `idx_image`: the image on which to run the calculation (default: active image). Not used for GNEB
"""

info = simulation_run_info()

if method_type == METHOD_MC:
spiritlib.wrap_function(_MC_Start, [ctypes.c_void_p(p_state),
ctypes.c_int(n_iterations), ctypes.c_int(n_iterations_log),
ctypes.c_bool(single_shot),
ctypes.pointer(info),
ctypes.c_int(idx_image), ctypes.c_int(idx_chain)])
elif method_type == METHOD_LLG:
spiritlib.wrap_function(_LLG_Start, [ctypes.c_void_p(p_state),
ctypes.c_int(solver_type),
ctypes.c_int(n_iterations), ctypes.c_int(n_iterations_log),
ctypes.c_bool(single_shot),
ctypes.pointer(info),
ctypes.c_int(idx_image), ctypes.c_int(idx_chain)])
elif method_type == METHOD_GNEB:
spiritlib.wrap_function(_GNEB_Start, [ctypes.c_void_p(p_state),
ctypes.c_int(solver_type),
ctypes.c_int(n_iterations), ctypes.c_int(n_iterations_log),
ctypes.c_bool(single_shot),
ctypes.c_int(idx_image), ctypes.c_int(idx_chain)])
ctypes.pointer(info),
ctypes.c_int(idx_chain)])
elif method_type == METHOD_MMF:
spiritlib.wrap_function(_MMF_Start, [ctypes.c_void_p(p_state),
ctypes.c_int(solver_type),
ctypes.c_int(n_iterations), ctypes.c_int(n_iterations_log),
ctypes.c_bool(single_shot),
ctypes.pointer(info),
ctypes.c_int(idx_image), ctypes.c_int(idx_chain)])
elif method_type == METHOD_EMA:
spiritlib.wrap_function(_EMA_Start, [ctypes.c_void_p(p_state),
ctypes.c_int(n_iterations), ctypes.c_int(n_iterations_log),
ctypes.c_bool(single_shot),
ctypes.pointer(info),
ctypes.c_int(idx_image), ctypes.c_int(idx_chain)])
else:
print("Invalid method_type passed to simulation.start...")

return info
# _Start(ctypes.c_void_p(p_state), ctypes.c_char_p(method_type),
# ctypes.c_char_p(solver_type), ctypes.c_int(n_iterations),
# ctypes.c_int(n_iterations_log), ctypes.c_int(idx_image), ctypes.c_int(idx_chain))
Expand Down
42 changes: 24 additions & 18 deletions core/src/Spirit/Simulation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
#include <utility/Logging.hpp>

// Helper function to start a simulation once a Method has been created
void run_method( std::shared_ptr<Engine::Method> method, bool singleshot )
void run_method(std::shared_ptr<Engine::Method> method, bool singleshot, Simulation_Run_Info * info = nullptr)
{
if( singleshot )
{
Expand All @@ -32,11 +32,18 @@ void run_method( std::shared_ptr<Engine::Method> method, bool singleshot )
else
{
method->Iterate();
if(info)
{
info->max_torque = method->getTorqueMaxNorm();
info->total_iterations = method->getNIterations();
info->total_walltime = method->getWallTime();
info->total_ips = float(info->total_iterations) / info->total_walltime * 1000.0;
}
}
}

void Simulation_MC_Start(
State * state, int n_iterations, int n_iterations_log, bool singleshot, int idx_image, int idx_chain ) noexcept
void Simulation_MC_Start(State *state,
int n_iterations, int n_iterations_log, bool singleshot, Simulation_Run_Info * info, int idx_image, int idx_chain) noexcept
try
{
// Fetch correct indices and pointers for image and chain
Expand Down Expand Up @@ -83,17 +90,16 @@ try
image->Unlock();

state->method_image[idx_image] = method;
run_method( method, singleshot );
run_method(method, singleshot, info);
}
}
catch( ... )
{
spirit_handle_exception_api( idx_image, idx_chain );
}

void Simulation_LLG_Start(
State * state, int solver_type, int n_iterations, int n_iterations_log, bool singleshot, int idx_image,
int idx_chain ) noexcept
void Simulation_LLG_Start(State *state, int solver_type,
int n_iterations, int n_iterations_log, bool singleshot, Simulation_Run_Info * info, int idx_image, int idx_chain) noexcept
try
{
// Fetch correct indices and pointers for image and chain
Expand Down Expand Up @@ -168,16 +174,16 @@ try
image->Unlock();

state->method_image[idx_image] = method;
run_method( method, singleshot );
run_method(method, singleshot, info);
}
}
catch( ... )
{
spirit_handle_exception_api( idx_image, idx_chain );
}

void Simulation_GNEB_Start(
State * state, int solver_type, int n_iterations, int n_iterations_log, bool singleshot, int idx_chain ) noexcept
void Simulation_GNEB_Start(State *state, int solver_type,
int n_iterations, int n_iterations_log, bool singleshot, Simulation_Run_Info * info, int idx_chain) noexcept
try
{
// Fetch correct indices and pointers for image and chain
Expand Down Expand Up @@ -264,7 +270,7 @@ try
chain->Unlock();

state->method_chain = method;
run_method( method, singleshot );
run_method(method, singleshot, info);
}
}
}
Expand All @@ -273,9 +279,8 @@ catch( ... )
spirit_handle_exception_api( -1, idx_chain );
}

void Simulation_MMF_Start(
State * state, int solver_type, int n_iterations, int n_iterations_log, bool singleshot, int idx_image,
int idx_chain ) noexcept
void Simulation_MMF_Start(State *state, int solver_type,
int n_iterations, int n_iterations_log, bool singleshot, Simulation_Run_Info * info, int idx_image, int idx_chain) noexcept
try
{
// Fetch correct indices and pointers for image and chain
Expand Down Expand Up @@ -339,16 +344,16 @@ try
image->Unlock();

state->method_image[idx_image] = method;
run_method( method, singleshot );
run_method(method, singleshot, info);
}
}
catch( ... )
{
spirit_handle_exception_api( idx_image, idx_chain );
}

void Simulation_EMA_Start(
State * state, int n_iterations, int n_iterations_log, bool singleshot, int idx_image, int idx_chain ) noexcept
void Simulation_EMA_Start(State *state,
int n_iterations, int n_iterations_log, bool singleshot, Simulation_Run_Info * info, int idx_image, int idx_chain) noexcept
try
{
// Fetch correct indices and pointers for image and chain
Expand Down Expand Up @@ -395,7 +400,8 @@ try
image->Unlock();

state->method_image[idx_image] = method;
run_method( method, singleshot );

run_method(method, singleshot, info);
}
}
catch( ... )
Expand Down
14 changes: 7 additions & 7 deletions ui-cpp/ui-imgui/src/main_window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -723,46 +723,46 @@ try
if( threads_image[idx].joinable() )
threads_image[System_Get_Index( state.get() )].join();
this->threads_image[System_Get_Index( state.get() )] = std::thread(
&Simulation_LLG_Start, this->state.get(), ui_shared_state.selected_solver_min, -1, -1, false, -1, -1 );
&Simulation_LLG_Start, this->state.get(), ui_shared_state.selected_solver_min, -1, -1, false, nullptr, -1, -1 );
}
if( ui_shared_state.selected_mode == GUI_Mode::LLG )
{
int idx = System_Get_Index( state.get() );
if( threads_image[idx].joinable() )
threads_image[System_Get_Index( state.get() )].join();
this->threads_image[System_Get_Index( state.get() )] = std::thread(
&Simulation_LLG_Start, this->state.get(), ui_shared_state.selected_solver_llg, -1, -1, false, -1, -1 );
&Simulation_LLG_Start, this->state.get(), ui_shared_state.selected_solver_llg, -1, -1, false, nullptr, -1, -1 );
}
else if( ui_shared_state.selected_mode == GUI_Mode::MC )
{
int idx = System_Get_Index( state.get() );
if( threads_image[idx].joinable() )
threads_image[System_Get_Index( state.get() )].join();
this->threads_image[System_Get_Index( state.get() )]
= std::thread( &Simulation_MC_Start, this->state.get(), -1, -1, false, -1, -1 );
= std::thread( &Simulation_MC_Start, this->state.get(), -1, -1, false, nullptr, -1, -1 );
}
else if( ui_shared_state.selected_mode == GUI_Mode::GNEB )
{
if( thread_chain.joinable() )
thread_chain.join();
this->thread_chain = std::thread(
&Simulation_GNEB_Start, this->state.get(), ui_shared_state.selected_solver_min, -1, -1, false, -1 );
&Simulation_GNEB_Start, this->state.get(), ui_shared_state.selected_solver_min, -1, -1, false, nullptr, -1 );
}
else if( ui_shared_state.selected_mode == GUI_Mode::MMF )
{
{
int idx = System_Get_Index( state.get() );
if( threads_image[idx].joinable() )
threads_image[System_Get_Index( state.get() )].join();
this->threads_image[System_Get_Index( state.get() )] = std::thread(
&Simulation_MMF_Start, this->state.get(), ui_shared_state.selected_solver_min, -1, -1, false, -1, -1 );
&Simulation_MMF_Start, this->state.get(), ui_shared_state.selected_solver_min, -1, -1, false, nullptr, -1, -1 );
}
else if( ui_shared_state.selected_mode == GUI_Mode::EMA )
{
int idx = System_Get_Index( state.get() );
if( threads_image[idx].joinable() )
threads_image[System_Get_Index( state.get() )].join();
this->threads_image[System_Get_Index( state.get() )]
= std::thread( &Simulation_EMA_Start, this->state.get(), -1, -1, false, -1, -1 );
= std::thread( &Simulation_EMA_Start, this->state.get(), -1, -1, false, nullptr, -1, -1 );
}
this->ui_shared_state.notify( "started calculation" );
}
Expand Down
10 changes: 5 additions & 5 deletions ui-cpp/ui-qt/src/ControlWidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -195,37 +195,37 @@ void ControlWidget::play_pause()
if( threads_image[idx].joinable() )
threads_image[System_Get_Index( state.get() )].join();
this->threads_image[System_Get_Index( state.get() )]
= std::thread( &Simulation_LLG_Start, this->state.get(), solver, -1, -1, false, -1, -1 );
= std::thread( &Simulation_LLG_Start, this->state.get(), solver, -1, -1, false, nullptr, -1, -1 );
}
else if( this->s_method == "MC" )
{
int idx = System_Get_Index( state.get() );
if( threads_image[idx].joinable() )
threads_image[System_Get_Index( state.get() )].join();
this->threads_image[System_Get_Index( state.get() )]
= std::thread( &Simulation_MC_Start, this->state.get(), -1, -1, false, -1, -1 );
= std::thread( &Simulation_MC_Start, this->state.get(), -1, -1, false, nullptr, -1, -1 );
}
else if( this->s_method == "GNEB" )
{
if( thread_chain.joinable() )
thread_chain.join();
this->thread_chain = std::thread( &Simulation_GNEB_Start, this->state.get(), solver, -1, -1, false, -1 );
this->thread_chain = std::thread( &Simulation_GNEB_Start, this->state.get(), solver, -1, -1, false, nullptr, -1 );
}
else if( this->s_method == "MMF" )
{
int idx = System_Get_Index( state.get() );
if( threads_image[idx].joinable() )
threads_image[System_Get_Index( state.get() )].join();
this->threads_image[System_Get_Index( state.get() )]
= std::thread( &Simulation_MMF_Start, this->state.get(), solver, -1, -1, false, -1, -1 );
= std::thread( &Simulation_MMF_Start, this->state.get(), solver, -1, -1, false, nullptr, -1, -1 );
}
else if( this->s_method == "EMA" )
{
int idx = System_Get_Index( state.get() );
if( threads_image[idx].joinable() )
threads_image[System_Get_Index( state.get() )].join();
this->threads_image[System_Get_Index( state.get() )]
= std::thread( &Simulation_EMA_Start, this->state.get(), -1, -1, false, -1, -1 );
= std::thread( &Simulation_EMA_Start, this->state.get(), -1, -1, false, nullptr, -1, -1 );
}
// New button text
this->pushButton_PlayPause->setText( "Stop" );
Expand Down

0 comments on commit 57486d7

Please sign in to comment.